mirror of
https://github.com/4sval/FModel.git
synced 2026-06-21 07:20:05 -05:00
commit
5db52e720c
|
|
@ -1 +1 @@
|
|||
Subproject commit d2163de354e97a0e62222221b96666a678255884
|
||||
Subproject commit 763aca666c1782ce51287100641bc31d9fce0d41
|
||||
|
|
@ -44,9 +44,9 @@ namespace FModel
|
|||
}
|
||||
|
||||
if (!Directory.Exists(UserSettings.Default.OutputDirectory))
|
||||
{
|
||||
UserSettings.Default.OutputDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Output");
|
||||
}
|
||||
if (!Directory.Exists(UserSettings.Default.ModelDirectory))
|
||||
UserSettings.Default.ModelDirectory = Path.Combine(UserSettings.Default.OutputDirectory, "Saves");
|
||||
|
||||
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FModel"));
|
||||
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, "Backups"));
|
||||
|
|
|
|||
|
|
@ -102,10 +102,19 @@ namespace FModel.Creator.Bases.FN
|
|||
if (!bShort) return base.GetCosmeticSeason(seasonNumber);
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var number = int.Parse(s);
|
||||
if (number == 10)
|
||||
s = "X";
|
||||
|
||||
return number > 10 ? $"C{number / 10 + 1} S{s[^1..]}" : $"C1 S{s}";
|
||||
switch (number)
|
||||
{
|
||||
case 10:
|
||||
s = "X";
|
||||
break;
|
||||
case > 18:
|
||||
number += 2;
|
||||
s = number.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
return $"C{number / 10 + 1} S{s[^1..]}";
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
|
|
|
|||
|
|
@ -199,8 +199,17 @@ namespace FModel.Creator.Bases.FN
|
|||
{
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var number = int.Parse(s);
|
||||
if (number == 10)
|
||||
s = "X";
|
||||
|
||||
switch (number)
|
||||
{
|
||||
case 10:
|
||||
s = "X";
|
||||
break;
|
||||
case > 18:
|
||||
number += 2;
|
||||
s = number.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
var season = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "SeasonTextFormat", "Season {0}");
|
||||
var introduced = Utils.GetLocalizedResource("Fort.Cosmetics", "CosmeticItemDescription_Season", "\nIntroduced in <SeasonText>{0}</>.");
|
||||
|
|
|
|||
|
|
@ -142,10 +142,10 @@ namespace FModel.Creator.Bases.FN
|
|||
if (property.TryGetValue(out FStructFallback curve, "Curve") &&
|
||||
curve.TryGetValue(out FName rowName, "RowName") &&
|
||||
curve.TryGetValue(out UCurveTable curveTable, "CurveTable") &&
|
||||
curveTable.TryGetCurveTableRow(rowName.Text, StringComparison.OrdinalIgnoreCase, out var rowValue) &&
|
||||
rowValue.TryGetValue(out FSimpleCurveKey[] keys, "Keys") && keys.Length > 0)
|
||||
curveTable.TryFindCurve(rowName, out var rowValue) &&
|
||||
rowValue is FSimpleCurve s && s.Keys.Length > 0)
|
||||
{
|
||||
statValue = keys[0].Value;
|
||||
statValue = s.Keys[0].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -274,6 +274,8 @@ namespace FModel.Creator.Bases.FN
|
|||
c.DrawText(_value.ToString(), new SKPoint(width - 50, y + 10), _statPaint);
|
||||
|
||||
if (_maxValue < 1 || !float.TryParse(_value.ToString(), out var floatValue)) return;
|
||||
if (floatValue < 0)
|
||||
floatValue = 0;
|
||||
var sliderWidth = (sliderRight - height * 2) * (floatValue / _maxValue);
|
||||
c.DrawRect(new SKRect(height * 2, y, Math.Min(height * 2 + sliderWidth, sliderRight), y + 5), _statPaint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace FModel.Creator.Bases.SOD2
|
||||
{
|
||||
public class BaseDecayIcon : BaseIcon
|
||||
{
|
||||
private int _maxStackCount;
|
||||
private readonly SKBitmap _backgroundOverlay;
|
||||
|
||||
public BaseDecayIcon(UObject uObject, EIconStyle style) : base(uObject, style)
|
||||
{
|
||||
Margin = 0;
|
||||
Background = new[] {SKColor.Parse("000000"), SKColor.Parse("B24E18")};
|
||||
_backgroundOverlay = Utils.GetBitmap("StateOfDecay2/Content/Art/UI/settings/icon_sod_eagle_09_square.icon_sod_eagle_09_square").Resize(512);
|
||||
}
|
||||
|
||||
public override void ParseForInfo()
|
||||
{
|
||||
if (Object.TryGetValue(out FStructFallback stackingInfo, "StackingInfo") &&
|
||||
stackingInfo.TryGetValue(out int maxStackCount, "MaxStackCount"))
|
||||
_maxStackCount = maxStackCount;
|
||||
|
||||
if (Object.Class.SuperStruct != null && Utils.TryGetPackageIndexExport(Object.Class.SuperStruct, out UObject t))
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (Object.TryGetValue(out FStructFallback displayInfo, "DisplayInfo"))
|
||||
{
|
||||
if (displayInfo.TryGetValue(out FText displayName, "DisplayName"))
|
||||
DisplayName = displayName.Text;
|
||||
if (displayInfo.TryGetValue(out FText displayDescription, "DisplayDescription"))
|
||||
Description = displayDescription.Text;
|
||||
|
||||
if (displayInfo.TryGetValue(out string iconFills, "IconFills"))
|
||||
Preview = Utils.GetBitmap(iconFills);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
//
|
||||
// ExtraLargeBackpackBase - for extra large
|
||||
// SmallBackpackBase - for small
|
||||
// ExtraSmallBackpackBase - for extra small
|
||||
// MediumBackpackBase - for medium
|
||||
// LargeBackpackBase - for large
|
||||
|
||||
public override SKImage Draw()
|
||||
{
|
||||
using var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(ret);
|
||||
|
||||
DrawBackground(c);
|
||||
DrawPreview(c);
|
||||
|
||||
return SKImage.FromBitmap(ret);
|
||||
}
|
||||
|
||||
private new void DrawPreview(SKCanvas c)
|
||||
{
|
||||
c.DrawBitmap(Preview ?? DefaultPreview, new SKRect(Margin, Margin, Width - Margin, Height - Margin), new SKPaint
|
||||
{
|
||||
// BlendMode = SKBlendMode.SrcATop -- Need Asval's assistance.
|
||||
});
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
{
|
||||
c.DrawRect(new SKRect(Margin, Margin, Width - Margin, Height - Margin),
|
||||
new SKPaint
|
||||
{
|
||||
IsAntialias = true, FilterQuality = SKFilterQuality.High,
|
||||
Shader = SKShader.CreateRadialGradient(new SKPoint(Width / 2, Height / 2), Width / 5 * 2,
|
||||
new[] {Background[0], Background[1]},
|
||||
SKShaderTileMode.Clamp)
|
||||
});
|
||||
|
||||
for (var i = 0; i < _backgroundOverlay.Width; i++)
|
||||
for (var j = 0; j < _backgroundOverlay.Height; j++)
|
||||
if (_backgroundOverlay.GetPixel(i, j) == SKColors.Black)
|
||||
{
|
||||
_backgroundOverlay.SetPixel(i, j, SKColors.Transparent);
|
||||
}
|
||||
|
||||
c.DrawBitmap(_backgroundOverlay, new SKRect(Margin, Margin, Width - Margin, Height - Margin), new SKPaint
|
||||
{
|
||||
IsAntialias = true,
|
||||
ColorFilter = SKColorFilter.CreateBlendMode(SKColors.Black.WithAlpha(150), SKBlendMode.DstIn),
|
||||
ImageFilter = SKImageFilter.CreateDropShadow(2, 2, 4, 4, new SKColor(0, 0, 0))
|
||||
});
|
||||
c.DrawColor(SKColors.Black.WithAlpha(125), SKBlendMode.DstIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ using FModel.Creator.Bases;
|
|||
using FModel.Creator.Bases.BB;
|
||||
using FModel.Creator.Bases.FN;
|
||||
using FModel.Creator.Bases.SB;
|
||||
using FModel.Creator.Bases.SOD2;
|
||||
|
||||
namespace FModel.Creator
|
||||
{
|
||||
|
|
@ -230,38 +229,6 @@ namespace FModel.Creator
|
|||
case "GLeagueDivision":
|
||||
creator = new BaseDivision(_object, EIconStyle.Default);
|
||||
return true;
|
||||
// State of Decay 2
|
||||
case "CureItem":
|
||||
case "AmmoItem":
|
||||
case "Pro_Brake_C":
|
||||
case "BackpackItem":
|
||||
case "MagicAmmoItem":
|
||||
case "ConsumableItem":
|
||||
case "MeleeWeaponItem":
|
||||
case "CloseCombatItem":
|
||||
case "FacilityModItem":
|
||||
case "RangedWeaponItem":
|
||||
case "MiscellaneousItem":
|
||||
case "RepairVehicleItem":
|
||||
case "ResourceItemBase_C":
|
||||
case "FuelResourceBase_C":
|
||||
case "MedsResourceBase_C":
|
||||
case "PartsResourceBase_C":
|
||||
case "RangedWeaponModItem":
|
||||
case "VehicleDeliveryItem":
|
||||
case "ConsumableBase_BP_C":
|
||||
case "SmallBackpackBase_C":
|
||||
case "LargeBackpackBase_C":
|
||||
case "MediumBackpackBase_C":
|
||||
case "ConsumableMedsBase_BP_C":
|
||||
case "MaterialsResourceBase_C":
|
||||
case "ExtraLargeBackpackBase_C":
|
||||
case "ExtraSmallBackpackBase_C":
|
||||
case "ConsumableStimsBase_BP_C":
|
||||
case "Consumable_TimedStatBuff_Base_BP_C":
|
||||
case "Consumable_SuspendFatigue_Base_BP_C":
|
||||
creator = new BaseDecayIcon(_object, EIconStyle.Default);
|
||||
return true;
|
||||
default:
|
||||
creator = null;
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ namespace FModel
|
|||
{
|
||||
Restart,
|
||||
ReloadLocres,
|
||||
CheckForUpdates,
|
||||
Nothing
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using FModel.Properties;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FModel.Properties;
|
||||
|
||||
namespace FModel.Extensions
|
||||
{
|
||||
|
|
@ -47,12 +47,12 @@ namespace FModel.Extensions
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T ToEnum<T>(this string value, T defaultValue)
|
||||
public static T ToEnum<T>(this string value, T defaultValue) where T : struct
|
||||
{
|
||||
if (!Enum.TryParse(typeof(T), value, true, out var ret))
|
||||
if (!Enum.TryParse(value, true, out T ret))
|
||||
return defaultValue;
|
||||
|
||||
return (T) ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -81,4 +81,4 @@ namespace FModel.Extensions
|
|||
return i == -1 ? (T) values.GetValue(values.Length - 1) : (T) values.GetValue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@
|
|||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationIcon>FModel.ico</ApplicationIcon>
|
||||
<Version>4.0.0</Version>
|
||||
<AssemblyVersion>4.0.2.0</AssemblyVersion>
|
||||
<FileVersion>4.0.2.0</FileVersion>
|
||||
<Version>4.2.0</Version>
|
||||
<AssemblyVersion>4.2.0.0</AssemblyVersion>
|
||||
<FileVersion>4.2.0.0</FileVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsPublishable>true</IsPublishable>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishSingleFile Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">true</PublishSingleFile>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
<StartupObject>FModel.App</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
|
@ -110,12 +110,12 @@
|
|||
<PackageReference Include="DiscordRichPresence" Version="1.0.175" />
|
||||
<PackageReference Include="EpicManifestParser" Version="1.2.70-temp" />
|
||||
<PackageReference Include="HelixToolkit.SharpDX.Core.Wpf" Version="2.20.0" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.2.15" />
|
||||
<PackageReference Include="K4os.Compression.LZ4.Streams" Version="1.2.16" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NVorbis" Version="0.10.4" />
|
||||
<PackageReference Include="Oodle.NET" Version="1.0.1" />
|
||||
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.0" />
|
||||
<PackageReference Include="RestSharp" Version="106.13.0" />
|
||||
<PackageReference Include="RestSharp" Version="106.15.0" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="SkiaSharp.HarfBuzz" Version="2.80.3" />
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Assets">
|
||||
<MenuItem Header="Packages">
|
||||
<MenuItem Header="Search" IsEnabled="{Binding IsReady}" InputGestureText="Ctrl+Shift+F" Click="OnSearchViewClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
|
|
@ -94,7 +94,7 @@
|
|||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Export Data" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem Header="Export Raw Data" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Export_Data" />
|
||||
|
|
@ -147,24 +147,15 @@
|
|||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="Export Data" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoExportData, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoExportData, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
<MenuItem Header="Save Properties" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoSaveProps, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoSaveProps, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
<MenuItem Header="Save Textures" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoSaveTextures, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoSaveTextures, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
<MenuItem Header="Save Animations" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoSaveAnimations, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoSaveAnimations, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
<MenuItem Header="Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
<MenuItem Header="Open Meshes & Materials" IsCheckable="True" StaysOpenOnClick="True"
|
||||
InputGestureText="{Binding AutoOpenMeshes, Source={x:Static local:Settings.UserSettings.Default}}"
|
||||
IsChecked="{Binding IsAutoOpenMeshes, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
</MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Views">
|
||||
|
|
@ -266,7 +257,7 @@
|
|||
<GroupBox Grid.Column="0" adonisExtensions:LayerExtension.Layer="2"
|
||||
Padding="{adonisUi:Space 0}" Background="Transparent">
|
||||
<TabControl x:Name="LeftTabControl" SelectionChanged="OnTabItemChange">
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}" Header="Directory">
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}" Header="Archives">
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -301,7 +292,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Separator Grid.Row="0" Style="{StaticResource CustomSeparator}" Tag="GAME DIRECTORY" />
|
||||
<Separator Grid.Row="0" Style="{StaticResource CustomSeparator}" Tag="GAME ARCHIVES" />
|
||||
<ListBox Grid.Row="1" x:Name="DirectoryFilesListBox" Style="{StaticResource DirectoryFilesListBox}" MouseDoubleClick="OnMouseDoubleClick" />
|
||||
<Separator Grid.Row="2" Style="{StaticResource CustomSeparator}" Tag="INFORMATION" />
|
||||
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="0 0 0 5">
|
||||
|
|
@ -352,7 +343,7 @@
|
|||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3.5 0" />
|
||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}'{0}' has {1} folders and {2} files">
|
||||
<MultiBinding StringFormat="{}'{0}' has {1} folders and {2} packages">
|
||||
<Binding Path="SelectedItem.Header" ElementName="AssetsFolderName" FallbackValue="None" />
|
||||
<Binding Path="SelectedItem.FoldersView.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
<Binding Path="SelectedItem.AssetsList.Assets.Count" ElementName="AssetsFolderName" FallbackValue="0" />
|
||||
|
|
@ -391,7 +382,7 @@
|
|||
<TreeView Grid.Row="2" x:Name="AssetsFolderName" Style="{StaticResource AssetsFolderTreeView}" PreviewMouseDoubleClick="OnAssetsTreeMouseDoubleClick">
|
||||
<TreeView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Extract Folder's Assets" Click="OnFolderExtractClick">
|
||||
<MenuItem Header="Extract Folder's Packages" Click="OnFolderExtractClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -400,7 +391,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Export Folder's Assets Data" Click="OnFolderExportClick">
|
||||
<MenuItem Header="Export Folder's Packages Raw Data" Click="OnFolderExportClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -409,7 +400,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Assets Properties" Click="OnFolderSaveClick">
|
||||
<MenuItem Header="Save Folder's Packages Properties" Click="OnFolderSaveClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -456,22 +447,22 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding SelectedItem.AssetsList.Assets.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Assets Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="Packages Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.FoldersView.Count, ElementName=AssetsFolderName, FallbackValue=0}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="Folders Count" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.Package, ElementName=AssetsFolderName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="Included In Package" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="Included In Archive" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding SelectedItem.MountPoint, ElementName=AssetsFolderName, FallbackValue='/', Converter={x:Static converters:TrimRightToLeftConverter.Instance}, ConverterParameter=275}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Package Mount Point" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Archive Mount Point" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="{Binding SelectedItem.Version, ElementName=AssetsFolderName, FallbackValue='VER_UE4_LATEST', Converter={x:Static converters:TrimRightToLeftConverter.Instance}, ConverterParameter=275}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Package Version" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Archive Version" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Style="{StaticResource TabItemFillSpace}"
|
||||
Header="{Binding SelectedItem.AssetsList.Assets.Count, FallbackValue=0, ElementName=AssetsFolderName}"
|
||||
HeaderStringFormat="{}{0} Assets">
|
||||
HeaderStringFormat="{}{0} Packages">
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top" ZIndex="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
|
@ -528,7 +519,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Export Data" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem Header="Export Raw Data" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Export_Data" />
|
||||
|
|
@ -582,7 +573,7 @@
|
|||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="File Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path" />
|
||||
|
|
@ -590,7 +581,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Name" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Name" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name" />
|
||||
|
|
@ -606,7 +597,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Path w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Path w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path_No_Extension" />
|
||||
|
|
@ -614,7 +605,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Name w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Name w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name_No_Extension" />
|
||||
|
|
@ -650,7 +641,7 @@
|
|||
<TextBlock Grid.Row="3" Grid.Column="0" Text="{Binding SelectedItem.IsEncrypted, ElementName=AssetsListName, FallbackValue='False'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="Is Encrypted" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="{Binding SelectedItem.Package, ElementName=AssetsListName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Included In Package" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="Included In Archive" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
|
@ -802,19 +793,6 @@
|
|||
</Viewbox>
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Export Data Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoExportData, Source={x:Static local:Settings.UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Hidden" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StatusBarItem.Style>
|
||||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="DTA" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Save Properties Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
|
|
@ -841,19 +819,6 @@
|
|||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="TEX" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="35" HorizontalContentAlignment="Stretch" ToolTip="Auto Save Animations Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoSaveAnimations, Source={x:Static local:Settings.UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Hidden" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StatusBarItem.Style>
|
||||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="ANM" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Open Sounds Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
|
|
@ -866,19 +831,6 @@
|
|||
</StatusBarItem.Style>
|
||||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="SND" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="35" HorizontalContentAlignment="Stretch" ToolTip="Auto Open Meshes & Materials Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoOpenMeshes, Source={x:Static local:Settings.UserSettings.Default}}" Value="False">
|
||||
<Setter Property="Visibility" Value="Hidden" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StatusBarItem.Style>
|
||||
<TextBlock HorizontalAlignment="Center" FontWeight="SemiBold" Text="MSH" />
|
||||
</StatusBarItem>
|
||||
</StackPanel>
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ using FModel.Settings;
|
|||
using FModel.ViewModels;
|
||||
using FModel.Views;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using ICSharpCode.AvalonEdit.Editing;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
|
|
@ -27,18 +26,12 @@ namespace FModel
|
|||
|
||||
public MainWindow()
|
||||
{
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoExportData", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoExportData.Key, UserSettings.Default.AutoExportData.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveProps", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveProps.Key, UserSettings.Default.AutoSaveProps.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveTextures", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveTextures.Key, UserSettings.Default.AutoSaveTextures.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoSaveAnimations", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoSaveAnimations.Key, UserSettings.Default.AutoSaveAnimations.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoOpenSounds", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoOpenSounds.Key, UserSettings.Default.AutoOpenSounds.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("AutoOpenMeshes", typeof(MainWindow), new InputGestureCollection
|
||||
{new KeyGesture(UserSettings.Default.AutoOpenMeshes.Key, UserSettings.Default.AutoOpenMeshes.Modifiers)}), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("ReloadMappings", typeof(MainWindow), new InputGestureCollection {new KeyGesture(Key.F12)}), OnMappingsReload));
|
||||
CommandBindings.Add(new CommandBinding(ApplicationCommands.Find, (s, e) => OnOpenAvalonFinder()));
|
||||
|
||||
|
|
@ -91,7 +84,7 @@ namespace FModel
|
|||
|
||||
private void OnWindowKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is TextArea or TextBox)
|
||||
if (e.OriginalSource is TextBox)
|
||||
return;
|
||||
|
||||
if (_threadWorkerView.CanBeCanceled && e.Key == Key.Escape)
|
||||
|
|
@ -137,24 +130,15 @@ namespace FModel
|
|||
{
|
||||
switch ((e.Command as RoutedCommand)?.Name)
|
||||
{
|
||||
case "AutoExportData":
|
||||
UserSettings.Default.IsAutoExportData = !UserSettings.Default.IsAutoExportData;
|
||||
break;
|
||||
case "AutoSaveProps":
|
||||
UserSettings.Default.IsAutoSaveProps = !UserSettings.Default.IsAutoSaveProps;
|
||||
break;
|
||||
case "AutoSaveTextures":
|
||||
UserSettings.Default.IsAutoSaveTextures = !UserSettings.Default.IsAutoSaveTextures;
|
||||
break;
|
||||
case "AutoSaveAnimations":
|
||||
UserSettings.Default.IsAutoSaveAnimations = !UserSettings.Default.IsAutoSaveAnimations;
|
||||
break;
|
||||
case "AutoOpenSounds":
|
||||
UserSettings.Default.IsAutoOpenSounds = !UserSettings.Default.IsAutoOpenSounds;
|
||||
break;
|
||||
case "AutoOpenMeshes":
|
||||
UserSettings.Default.IsAutoOpenMeshes = !UserSettings.Default.IsAutoOpenMeshes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -51,6 +51,13 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _outputDirectory, value);
|
||||
}
|
||||
|
||||
private string _modelDirectory;
|
||||
public string ModelDirectory
|
||||
{
|
||||
get => _modelDirectory;
|
||||
set => SetProperty(ref _modelDirectory, value);
|
||||
}
|
||||
|
||||
private string _gameDirectory;
|
||||
public string GameDirectory
|
||||
{
|
||||
|
|
@ -58,6 +65,20 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _gameDirectory, value);
|
||||
}
|
||||
|
||||
private bool _overwriteMapping;
|
||||
public bool OverwriteMapping
|
||||
{
|
||||
get => _overwriteMapping;
|
||||
set => SetProperty(ref _overwriteMapping, value);
|
||||
}
|
||||
|
||||
private string _mappingFilePath;
|
||||
public string MappingFilePath
|
||||
{
|
||||
get => _mappingFilePath;
|
||||
set => SetProperty(ref _mappingFilePath, value);
|
||||
}
|
||||
|
||||
private int _lastOpenedSettingTab;
|
||||
public int LastOpenedSettingTab
|
||||
{
|
||||
|
|
@ -65,13 +86,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _lastOpenedSettingTab, value);
|
||||
}
|
||||
|
||||
private bool _isAutoExportData;
|
||||
public bool IsAutoExportData
|
||||
{
|
||||
get => _isAutoExportData;
|
||||
set => SetProperty(ref _isAutoExportData, value);
|
||||
}
|
||||
|
||||
private bool _isAutoSaveProps;
|
||||
public bool IsAutoSaveProps
|
||||
{
|
||||
|
|
@ -86,13 +100,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _isAutoSaveTextures, value);
|
||||
}
|
||||
|
||||
private bool _isAutoSaveAnimations;
|
||||
public bool IsAutoSaveAnimations
|
||||
{
|
||||
get => _isAutoSaveAnimations;
|
||||
set => SetProperty(ref _isAutoSaveAnimations, value);
|
||||
}
|
||||
|
||||
private bool _isAutoOpenSounds = true;
|
||||
public bool IsAutoOpenSounds
|
||||
{
|
||||
|
|
@ -100,13 +107,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _isAutoOpenSounds, value);
|
||||
}
|
||||
|
||||
private bool _isAutoOpenMeshes = true;
|
||||
public bool IsAutoOpenMeshes
|
||||
{
|
||||
get => _isAutoOpenMeshes;
|
||||
set => SetProperty(ref _isAutoOpenMeshes, value);
|
||||
}
|
||||
|
||||
private bool _isLoggerExpanded = true;
|
||||
public bool IsLoggerExpanded
|
||||
{
|
||||
|
|
@ -235,7 +235,7 @@ namespace FModel.Settings
|
|||
private IDictionary<FGame, EGame> _overridedGame = new Dictionary<FGame, EGame>
|
||||
{
|
||||
{FGame.Unknown, EGame.GAME_UE4_LATEST},
|
||||
{FGame.FortniteGame, EGame.GAME_UE4_LATEST},
|
||||
{FGame.FortniteGame, EGame.GAME_UE5_LATEST},
|
||||
{FGame.ShooterGame, EGame.GAME_Valorant},
|
||||
{FGame.DeadByDaylight, EGame.GAME_UE4_LATEST},
|
||||
{FGame.OakGame, EGame.GAME_Borderlands3},
|
||||
|
|
@ -259,33 +259,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _overridedGame, value);
|
||||
}
|
||||
|
||||
private IDictionary<FGame, UE4Version> _overridedUEVersion = new Dictionary<FGame, UE4Version>
|
||||
{
|
||||
{FGame.Unknown, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.FortniteGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.ShooterGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.DeadByDaylight, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.OakGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.Dungeons, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.WorldExplorers, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.g3, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.StateOfDecay2, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.Prospect, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.Indiana, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.RogueCompany, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.SwGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.Platform, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.BendGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.TslGame, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.PortalWars, UE4Version.VER_UE4_DETERMINE_BY_GAME},
|
||||
{FGame.Gameface, UE4Version.VER_UE4_DETERMINE_BY_GAME}
|
||||
};
|
||||
public IDictionary<FGame, UE4Version> OverridedUEVersion
|
||||
{
|
||||
get => _overridedUEVersion;
|
||||
set => SetProperty(ref _overridedUEVersion, value);
|
||||
}
|
||||
|
||||
private IDictionary<FGame, List<FCustomVersion>> _overridedCustomVersions = new Dictionary<FGame, List<FCustomVersion>>
|
||||
{
|
||||
{FGame.Unknown, null},
|
||||
|
|
@ -364,7 +337,15 @@ namespace FModel.Settings
|
|||
new("Weapon Renders", "ShooterGame/Content/UI/Screens/OutOfGame/MainMenu/Collection/Assets/Large/")
|
||||
}
|
||||
},
|
||||
{FGame.DeadByDaylight, new List<CustomDirectory>()},
|
||||
{
|
||||
FGame.DeadByDaylight, new List<CustomDirectory>
|
||||
{
|
||||
new("Audio", "DeadByDaylight/Content/WwiseAudio/Windows/"),
|
||||
new("Characters", "DeadByDaylight/Content/Characters/"),
|
||||
new("Icons", "DeadByDaylight/Content/UI/UMGAssets/Icons/"),
|
||||
new("Strings", "DeadByDaylight/Content/Localization/")
|
||||
}
|
||||
},
|
||||
{FGame.OakGame, new List<CustomDirectory>()},
|
||||
{
|
||||
FGame.Dungeons, new List<CustomDirectory>
|
||||
|
|
@ -462,48 +443,27 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _assetRemoveTab, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoExportData = new(Key.F1);
|
||||
public Hotkey AutoExportData
|
||||
{
|
||||
get => _autoExportData;
|
||||
set => SetProperty(ref _autoExportData, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoSaveProps = new(Key.F2);
|
||||
private Hotkey _autoSaveProps = new(Key.F1);
|
||||
public Hotkey AutoSaveProps
|
||||
{
|
||||
get => _autoSaveProps;
|
||||
set => SetProperty(ref _autoSaveProps, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoSaveTextures = new(Key.F3);
|
||||
private Hotkey _autoSaveTextures = new(Key.F2);
|
||||
public Hotkey AutoSaveTextures
|
||||
{
|
||||
get => _autoSaveTextures;
|
||||
set => SetProperty(ref _autoSaveTextures, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoSaveAnimations = new(Key.F4);
|
||||
public Hotkey AutoSaveAnimations
|
||||
{
|
||||
get => _autoSaveAnimations;
|
||||
set => SetProperty(ref _autoSaveAnimations, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoOpenSounds = new(Key.F5);
|
||||
private Hotkey _autoOpenSounds = new(Key.F3);
|
||||
public Hotkey AutoOpenSounds
|
||||
{
|
||||
get => _autoOpenSounds;
|
||||
set => SetProperty(ref _autoOpenSounds, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoOpenMeshes = new(Key.F6);
|
||||
public Hotkey AutoOpenMeshes
|
||||
{
|
||||
get => _autoOpenMeshes;
|
||||
set => SetProperty(ref _autoOpenMeshes, value);
|
||||
}
|
||||
|
||||
private Hotkey _addAudio = new(Key.N, ModifierKeys.Control);
|
||||
public Hotkey AddAudio
|
||||
{
|
||||
|
|
@ -546,6 +506,85 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _lodExportFormat, value);
|
||||
}
|
||||
|
||||
private bool _previewStaticMeshes = true;
|
||||
public bool PreviewStaticMeshes
|
||||
{
|
||||
get => _previewStaticMeshes;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _previewStaticMeshes, value);
|
||||
if (_previewStaticMeshes && SaveStaticMeshes)
|
||||
SaveStaticMeshes = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _previewSkeletalMeshes = true;
|
||||
public bool PreviewSkeletalMeshes
|
||||
{
|
||||
get => _previewSkeletalMeshes;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _previewSkeletalMeshes, value);
|
||||
if (_previewSkeletalMeshes && SaveSkeletalMeshes)
|
||||
SaveSkeletalMeshes = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _previewMaterials = true;
|
||||
public bool PreviewMaterials
|
||||
{
|
||||
get => _previewMaterials;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _previewMaterials, value);
|
||||
if (_previewMaterials && SaveMaterials)
|
||||
SaveMaterials = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveStaticMeshes;
|
||||
public bool SaveStaticMeshes
|
||||
{
|
||||
get => _saveStaticMeshes;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _saveStaticMeshes, value);
|
||||
if (_saveStaticMeshes && PreviewStaticMeshes)
|
||||
PreviewStaticMeshes = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveSkeletalMeshes;
|
||||
public bool SaveSkeletalMeshes
|
||||
{
|
||||
get => _saveSkeletalMeshes;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _saveSkeletalMeshes, value);
|
||||
if (_saveSkeletalMeshes && PreviewSkeletalMeshes)
|
||||
PreviewSkeletalMeshes = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveMaterials;
|
||||
public bool SaveMaterials
|
||||
{
|
||||
get => _saveMaterials;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _saveMaterials, value);
|
||||
if (_saveMaterials && PreviewMaterials)
|
||||
PreviewMaterials = false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _saveAnimations;
|
||||
public bool SaveAnimations
|
||||
{
|
||||
get => _saveAnimations;
|
||||
set => SetProperty(ref _saveAnimations, value);
|
||||
}
|
||||
|
||||
private bool _saveSkeletonAsMesh;
|
||||
public bool SaveSkeletonAsMesh
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ namespace FModel.ViewModels
|
|||
private set => SetProperty(ref _mountPoint, value);
|
||||
}
|
||||
|
||||
private UE4Version _version;
|
||||
public UE4Version Version
|
||||
private int _version;
|
||||
public int Version
|
||||
{
|
||||
get => _version;
|
||||
private set => SetProperty(ref _version, value);
|
||||
|
|
@ -61,7 +61,7 @@ namespace FModel.ViewModels
|
|||
public RangeObservableCollection<TreeItem> Folders { get; }
|
||||
public ICollectionView FoldersView { get; }
|
||||
|
||||
public TreeItem(string header, string package, string mountPoint, UE4Version version, string pathHere)
|
||||
public TreeItem(string header, string package, string mountPoint, int version, string pathHere)
|
||||
{
|
||||
Header = header;
|
||||
Package = package;
|
||||
|
|
@ -129,7 +129,7 @@ namespace FModel.ViewModels
|
|||
if (lastNode == null)
|
||||
{
|
||||
var nodePath = builder.ToString();
|
||||
lastNode = new TreeItem(folder, item.Package, entry.Vfs.MountPoint, entry.Vfs.Ver, nodePath[..^1]);
|
||||
lastNode = new TreeItem(folder, item.Package, entry.Vfs.MountPoint, entry.Vfs.Ver.Value, nodePath[..^1]);
|
||||
lastNode.Folders.SetSuppressionState(true);
|
||||
lastNode.AssetsList.Assets.SetSuppressionState(true);
|
||||
parentNode.Add(lastNode);
|
||||
|
|
@ -168,4 +168,4 @@ namespace FModel.ViewModels
|
|||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace FModel.ViewModels
|
|||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
var backupFolder = Path.Combine(UserSettings.Default.OutputDirectory, "Backups");
|
||||
var fileName = $"{_gameName}_{DateTime.Now:MMddyyyy}.fbkp";
|
||||
var fileName = $"{_gameName}_{DateTime.Now:MM'_'dd'_'yyyy}.fbkp";
|
||||
var fullPath = Path.Combine(backupFolder, fileName);
|
||||
|
||||
using var fileStream = new FileStream(fullPath, FileMode.Create);
|
||||
|
|
@ -114,4 +114,4 @@ namespace FModel.ViewModels
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ namespace FModel.ViewModels
|
|||
set => SetProperty(ref _game, value);
|
||||
}
|
||||
|
||||
private bool _modelIsSwappingMaterial;
|
||||
public bool ModelIsSwappingMaterial
|
||||
private bool _modelIsOverwritingMaterial;
|
||||
public bool ModelIsOverwritingMaterial
|
||||
{
|
||||
get => _modelIsSwappingMaterial;
|
||||
set => SetProperty(ref _modelIsSwappingMaterial, value);
|
||||
get => _modelIsOverwritingMaterial;
|
||||
set => SetProperty(ref _modelIsOverwritingMaterial, value);
|
||||
}
|
||||
|
||||
public AbstractVfsFileProvider Provider { get; }
|
||||
|
|
@ -85,9 +85,8 @@ namespace FModel.ViewModels
|
|||
Provider = new StreamedFileProvider("FortniteLive", true,
|
||||
new VersionContainer(
|
||||
UserSettings.Default.OverridedGame[Game],
|
||||
UserSettings.Default.OverridedUEVersion[Game],
|
||||
UserSettings.Default.OverridedCustomVersions[Game],
|
||||
UserSettings.Default.OverridedOptions[Game]));
|
||||
customVersions: UserSettings.Default.OverridedCustomVersions[Game],
|
||||
optionOverrides: UserSettings.Default.OverridedOptions[Game]));
|
||||
break;
|
||||
}
|
||||
case Constants._VAL_LIVE_TRIGGER:
|
||||
|
|
@ -96,17 +95,16 @@ namespace FModel.ViewModels
|
|||
Provider = new StreamedFileProvider("ValorantLive", true,
|
||||
new VersionContainer(
|
||||
UserSettings.Default.OverridedGame[Game],
|
||||
UserSettings.Default.OverridedUEVersion[Game],
|
||||
UserSettings.Default.OverridedCustomVersions[Game],
|
||||
UserSettings.Default.OverridedOptions[Game]));
|
||||
customVersions: UserSettings.Default.OverridedCustomVersions[Game],
|
||||
optionOverrides: UserSettings.Default.OverridedOptions[Game]));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Game = gameDirectory.SubstringBeforeLast("\\Content").SubstringAfterLast("\\").ToEnum(FGame.Unknown);
|
||||
var versions = new VersionContainer(
|
||||
UserSettings.Default.OverridedGame[Game], UserSettings.Default.OverridedUEVersion[Game],
|
||||
UserSettings.Default.OverridedCustomVersions[Game], UserSettings.Default.OverridedOptions[Game]);
|
||||
var versions = new VersionContainer(UserSettings.Default.OverridedGame[Game],
|
||||
customVersions: UserSettings.Default.OverridedCustomVersions[Game],
|
||||
optionOverrides: UserSettings.Default.OverridedOptions[Game]);
|
||||
|
||||
if (Game == FGame.StateOfDecay2)
|
||||
Provider = new DefaultFileProvider(new DirectoryInfo(gameDirectory), new List<DirectoryInfo>
|
||||
|
|
@ -299,35 +297,44 @@ namespace FModel.ViewModels
|
|||
{
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
{
|
||||
var mappingsFolder = Path.Combine(UserSettings.Default.OutputDirectory, ".data");
|
||||
var mappings = _apiEndpointView.BenbotApi.GetMappings(cancellationToken);
|
||||
if (mappings is {Length: > 0})
|
||||
if (UserSettings.Default.OverwriteMapping && File.Exists(UserSettings.Default.MappingFilePath))
|
||||
{
|
||||
foreach (var mapping in mappings)
|
||||
{
|
||||
if (mapping.Meta.CompressionMethod != "Oodle") continue;
|
||||
|
||||
var mappingPath = Path.Combine(mappingsFolder, mapping.FileName);
|
||||
if (!File.Exists(mappingPath))
|
||||
{
|
||||
_apiEndpointView.BenbotApi.DownloadFile(mapping.Url, mappingPath);
|
||||
}
|
||||
|
||||
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(mappingPath);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Mappings pulled from '{mapping.FileName}'", Constants.WHITE, true);
|
||||
break;
|
||||
}
|
||||
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(UserSettings.Default.MappingFilePath);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Mappings pulled from '{UserSettings.Default.MappingFilePath.SubstringAfterLast("\\")}'", Constants.WHITE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var latestUsmaps = new DirectoryInfo(mappingsFolder).GetFiles("*_oo.usmap");
|
||||
if (Provider.MappingsContainer != null || latestUsmaps.Length <= 0) return;
|
||||
var mappingsFolder = Path.Combine(UserSettings.Default.OutputDirectory, ".data");
|
||||
var mappings = _apiEndpointView.BenbotApi.GetMappings(cancellationToken);
|
||||
if (mappings is {Length: > 0})
|
||||
{
|
||||
foreach (var mapping in mappings)
|
||||
{
|
||||
if (mapping.Meta.CompressionMethod != "Oodle") continue;
|
||||
|
||||
var latestUsmapInfo = latestUsmaps.OrderBy(f => f.LastWriteTime).Last();
|
||||
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(latestUsmapInfo.FullName);
|
||||
FLogger.AppendWarning();
|
||||
FLogger.AppendText($"Mappings pulled from '{latestUsmapInfo.Name}'", Constants.WHITE, true);
|
||||
var mappingPath = Path.Combine(mappingsFolder, mapping.FileName);
|
||||
if (!File.Exists(mappingPath))
|
||||
{
|
||||
_apiEndpointView.BenbotApi.DownloadFile(mapping.Url, mappingPath);
|
||||
}
|
||||
|
||||
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(mappingPath);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Mappings pulled from '{mapping.FileName}'", Constants.WHITE, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var latestUsmaps = new DirectoryInfo(mappingsFolder).GetFiles("*_oo.usmap");
|
||||
if (Provider.MappingsContainer != null || latestUsmaps.Length <= 0) return;
|
||||
|
||||
var latestUsmapInfo = latestUsmaps.OrderBy(f => f.LastWriteTime).Last();
|
||||
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(latestUsmapInfo.FullName);
|
||||
FLogger.AppendWarning();
|
||||
FLogger.AppendText($"Mappings pulled from '{latestUsmapInfo.Name}'", Constants.WHITE, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -365,9 +372,7 @@ namespace FModel.ViewModels
|
|||
/// <remarks>Functions only when LoadLocalizedResources is used prior to this (Asval: Why?).</remarks>
|
||||
private async Task LoadHotfixedLocalizedResources()
|
||||
{
|
||||
if (Game != FGame.FortniteGame) return;
|
||||
|
||||
if (HotfixedResourcesDone) return;
|
||||
if (Game != FGame.FortniteGame || HotfixedResourcesDone) return;
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
{
|
||||
var hotfixes = ApplicationService.ApiEndpointView.BenbotApi.GetHotfixes(cancellationToken, Provider.GetLanguageCode(UserSettings.Default.AssetLanguage));
|
||||
|
|
@ -395,7 +400,7 @@ namespace FModel.ViewModels
|
|||
if (VirtualPathCount > 0) return;
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
{
|
||||
VirtualPathCount = Provider.LoadVirtualPaths(UserSettings.Default.OverridedUEVersion[Game], cancellationToken);
|
||||
VirtualPathCount = Provider.LoadVirtualPaths(UserSettings.Default.OverridedGame[Game].GetVersion(), cancellationToken);
|
||||
if (VirtualPathCount > 0)
|
||||
{
|
||||
FLogger.AppendInformation();
|
||||
|
|
@ -603,13 +608,10 @@ namespace FModel.ViewModels
|
|||
break;
|
||||
}
|
||||
case "ufont":
|
||||
FLogger.AppendWarning();
|
||||
FLogger.AppendText($"Export '{fileName}' and change its extension if you want it to be an installable font file", Constants.WHITE, true);
|
||||
break;
|
||||
case "otf":
|
||||
case "ttf":
|
||||
FLogger.AppendWarning();
|
||||
FLogger.AppendText($"Export '{fileName}' if you want it to be an installable font file", Constants.WHITE, true);
|
||||
FLogger.AppendText($"Export '{fileName}' raw data and change its extension if you want it to be an installable font file", Constants.WHITE, true);
|
||||
break;
|
||||
case "ushaderbytecode":
|
||||
case "ushadercode":
|
||||
|
|
@ -625,13 +627,10 @@ namespace FModel.ViewModels
|
|||
default:
|
||||
{
|
||||
FLogger.AppendWarning();
|
||||
FLogger.AppendText($"The file '{fileName}' is of an unknown type.", Constants.WHITE, true);
|
||||
FLogger.AppendText($"The package '{fileName}' is of an unknown type.", Constants.WHITE, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (UserSettings.Default.IsAutoExportData)
|
||||
ExportData(fullPath);
|
||||
}
|
||||
|
||||
public void ExtractAndScroll(string fullPath, string objectName)
|
||||
|
|
@ -646,9 +645,6 @@ namespace FModel.ViewModels
|
|||
|
||||
if (!exports.Any(CheckExport))
|
||||
TabControl.SelectedTab.Image = null;
|
||||
|
||||
if (UserSettings.Default.IsAutoExportData)
|
||||
ExportData(fullPath);
|
||||
}
|
||||
|
||||
private bool CheckExport(UObject export) // return true once you wanna stop searching for exports
|
||||
|
|
@ -672,9 +668,9 @@ namespace FModel.ViewModels
|
|||
SaveAndPlaySound(Path.Combine(TabControl.SelectedTab.Directory, TabControl.SelectedTab.Header.SubstringBeforeLast('.')).Replace('\\', '/'), audioFormat, data);
|
||||
return false;
|
||||
}
|
||||
case UStaticMesh when UserSettings.Default.IsAutoOpenMeshes:
|
||||
case USkeletalMesh when UserSettings.Default.IsAutoOpenMeshes:
|
||||
case UMaterialInstance when UserSettings.Default.IsAutoOpenMeshes && !ModelIsSwappingMaterial &&
|
||||
case UStaticMesh when UserSettings.Default.PreviewStaticMeshes:
|
||||
case USkeletalMesh when UserSettings.Default.PreviewSkeletalMeshes:
|
||||
case UMaterialInstance when UserSettings.Default.PreviewMaterials && !ModelIsOverwritingMaterial &&
|
||||
!(Game == FGame.FortniteGame && export.Owner != null && (export.Owner.Name.EndsWith($"/MI_OfferImages/{export.Name}", StringComparison.OrdinalIgnoreCase) ||
|
||||
export.Owner.Name.EndsWith($"/RenderSwitch_Materials/{export.Name}", StringComparison.OrdinalIgnoreCase) ||
|
||||
export.Owner.Name.EndsWith($"/MI_BPTile/{export.Name}", StringComparison.OrdinalIgnoreCase))):
|
||||
|
|
@ -686,17 +682,20 @@ namespace FModel.ViewModels
|
|||
});
|
||||
return true;
|
||||
}
|
||||
case UMaterialInstance m when ModelIsSwappingMaterial:
|
||||
case UMaterialInstance m when ModelIsOverwritingMaterial:
|
||||
{
|
||||
Application.Current.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var modelViewer = Helper.GetWindow<ModelViewer>("Model Viewer", () => new ModelViewer().Show());
|
||||
modelViewer.Swap(m);
|
||||
modelViewer.Overwrite(m);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
case UStaticMesh when UserSettings.Default.SaveStaticMeshes:
|
||||
case USkeletalMesh when UserSettings.Default.SaveSkeletalMeshes:
|
||||
case UMaterialInstance when UserSettings.Default.SaveMaterials:
|
||||
case USkeleton when UserSettings.Default.SaveSkeletonAsMesh:
|
||||
case UAnimSequence when UserSettings.Default.IsAutoSaveAnimations:
|
||||
case UAnimSequence when UserSettings.Default.SaveAnimations:
|
||||
{
|
||||
SaveExport(export);
|
||||
return true;
|
||||
|
|
@ -744,7 +743,7 @@ namespace FModel.ViewModels
|
|||
private void SaveExport(UObject export)
|
||||
{
|
||||
var toSave = new Exporter(export, UserSettings.Default.TextureExportFormat, UserSettings.Default.LodExportFormat, UserSettings.Default.MeshExportFormat);
|
||||
var toSaveDirectory = new DirectoryInfo(Path.Combine(UserSettings.Default.OutputDirectory, "Saves"));
|
||||
var toSaveDirectory = new DirectoryInfo(UserSettings.Default.ModelDirectory);
|
||||
if (toSave.TryWriteToDir(toSaveDirectory, out var savedFileName))
|
||||
{
|
||||
Log.Information("Successfully saved {FileName}", savedFileName);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace FModel.ViewModels.Commands
|
|||
if (_applicationView.CUE4Parse.Provider.Files.Count <= 0)
|
||||
{
|
||||
FLogger.AppendError();
|
||||
FLogger.AppendText("An encrypted file has been found. In order to decrypt it, please specify a working AES encryption key", Constants.WHITE, true);
|
||||
FLogger.AppendText("An encrypted archive has been found. In order to decrypt it, please specify a working AES encryption key", Constants.WHITE, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ namespace FModel.ViewModels.Commands
|
|||
_applicationView.CUE4Parse.Provider.MappingsContainer == null)
|
||||
{
|
||||
FLogger.AppendError();
|
||||
FLogger.AppendText("Mappings could not get pulled, extracting assets might not work properly. If so, press F12 or please restart.", Constants.WHITE, true);
|
||||
FLogger.AppendText("Mappings could not get pulled, extracting packages might not work properly. If so, press F12 or please restart.", Constants.WHITE, true);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
|
@ -154,7 +154,7 @@ namespace FModel.ViewModels.Commands
|
|||
if (!(bool) openFileDialog.ShowDialog()) return;
|
||||
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Backup file older than current game version is '{openFileDialog.FileName.SubstringAfterLast("\\")}'", Constants.WHITE, true);
|
||||
FLogger.AppendText($"Backup file older than current game is '{openFileDialog.FileName.SubstringAfterLast("\\")}'", Constants.WHITE, true);
|
||||
|
||||
await using var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open);
|
||||
await using var memoryStream = new MemoryStream();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ namespace FModel.ViewModels.Commands
|
|||
case "Settings":
|
||||
Helper.OpenWindow<AdonisWindow>("Settings", () => new SettingsView().Show());
|
||||
break;
|
||||
case "ModelSettings":
|
||||
UserSettings.Default.LastOpenedSettingTab = contextViewModel.CUE4Parse.Game == FGame.FortniteGame ? 2 : 1;
|
||||
Helper.OpenWindow<AdonisWindow>("Settings", () => new SettingsView().Show());
|
||||
break;
|
||||
case "Help_About":
|
||||
Helper.OpenWindow<AdonisWindow>("About", () => new About().Show());
|
||||
break;
|
||||
|
|
@ -101,9 +105,9 @@ namespace FModel.ViewModels.Commands
|
|||
parent.IsExpanded = isExpanded;
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
foreach (var f in parent.Folders) LoopFolders(cancellationToken, f, isExpanded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ namespace FModel.ViewModels
|
|||
yield return GetRiotGame("VALORANT", "ShooterGame\\Content\\Paks");
|
||||
yield return new DetectedGame { GameName = "Valorant [LIVE]", GameDirectory = Constants._VAL_LIVE_TRIGGER };
|
||||
yield return GetMojangGame("MinecraftDungeons", "\\dungeons\\dungeons\\Dungeons\\Content\\Paks");
|
||||
yield return GetSteamGame(381210, "\\DeadByDaylight\\Content\\Paks"); // Dead By Daylight
|
||||
yield return GetSteamGame(578080, "\\TslGame\\Content\\Paks"); // PUBG
|
||||
yield return GetSteamGame(677620, "\\PortalWars\\Content\\Paks"); // Splitgate
|
||||
yield return GetRockstarGamesGame("GTA III - Definitive Edition", "\\Gameface\\Content\\Paks");
|
||||
|
|
@ -287,6 +288,7 @@ namespace FModel.ViewModels
|
|||
var libraries = new List<string> { steamPath };
|
||||
|
||||
var listFile = Path.Combine(steamPath, @"steamapps\libraryfolders.vdf");
|
||||
if (!File.Exists(listFile)) return new List<string>();
|
||||
var lines = File.ReadAllLines(listFile);
|
||||
foreach (var line in lines)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
using FModel.Framework;
|
||||
using FModel.ViewModels.Commands;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using FModel.Settings;
|
||||
using FModel.Framework;
|
||||
using FModel.ViewModels.Commands;
|
||||
|
||||
namespace FModel.ViewModels
|
||||
{
|
||||
|
|
@ -20,6 +18,6 @@ namespace FModel.ViewModels
|
|||
Modes = new ReadOnlyObservableCollection<ELoadingMode>(new ObservableCollection<ELoadingMode>(EnumerateLoadingModes()));
|
||||
}
|
||||
|
||||
private IEnumerable<ELoadingMode> EnumerateLoadingModes() => Enum.GetValues(UserSettings.Default.LoadingMode.GetType()).Cast<ELoadingMode>();
|
||||
private IEnumerable<ELoadingMode> EnumerateLoadingModes() => Enum.GetValues<ELoadingMode>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using CUE4Parse.UE4.Assets.Exports.Texture;
|
|||
using CUE4Parse.UE4.Assets.Objects;
|
||||
using CUE4Parse.UE4.Objects.Core.i18N;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.GameplayTags;
|
||||
using CUE4Parse.UE4.Objects.UObject;
|
||||
using FModel.Creator;
|
||||
using FModel.Extensions;
|
||||
|
|
@ -88,18 +89,11 @@ namespace FModel.ViewModels
|
|||
set => SetProperty(ref _brVendingMachines, value, "ApolloGameplay_VendingMachines");
|
||||
}
|
||||
|
||||
private bool _brFireflies;
|
||||
public bool BrFireflies
|
||||
private bool _brBountyBoards;
|
||||
public bool BrBountyBoards
|
||||
{
|
||||
get => _brFireflies;
|
||||
set => SetProperty(ref _brFireflies, value, "ApolloGameplay_Fireflies");
|
||||
}
|
||||
|
||||
private bool _brCubeMovements;
|
||||
public bool BrCubeMovements
|
||||
{
|
||||
get => _brCubeMovements;
|
||||
set => SetProperty(ref _brCubeMovements, value, "ApolloGameplay_CubeMovements");
|
||||
get => _brBountyBoards;
|
||||
set => SetProperty(ref _brBountyBoards, value, "ApolloGameplay_BountyBoards");
|
||||
}
|
||||
|
||||
private bool _prLandmarks;
|
||||
|
|
@ -273,11 +267,8 @@ namespace FModel.ViewModels
|
|||
case "ApolloGameplay_VendingMachines":
|
||||
await LoadBrVendingMachines();
|
||||
break;
|
||||
case "ApolloGameplay_Fireflies":
|
||||
await LoadFireflies();
|
||||
break;
|
||||
case "ApolloGameplay_CubeMovements":
|
||||
await LoadCubeMovements();
|
||||
case "ApolloGameplay_BountyBoards":
|
||||
await LoadBountyBoards();
|
||||
break;
|
||||
case "PapayaGameplay_CannonballGame":
|
||||
await LoadCannonballGame();
|
||||
|
|
@ -384,12 +375,9 @@ namespace FModel.ViewModels
|
|||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
if (!Utils.TryLoadObject("FortniteGame/Content/UI/IngameMap/UIMapManagerBR.Default__UIMapManagerBR_C", out UObject mapManager) ||
|
||||
!mapManager.TryGetValue(out UObject mapMaterial, "MapMaterial") ||
|
||||
!mapMaterial.TryGetValue(out FStructFallback cachedExpressionData, "CachedExpressionData") ||
|
||||
!cachedExpressionData.TryGetValue(out FStructFallback parameters, "Parameters") ||
|
||||
!parameters.TryGetValue(out UTexture2D[] textureValues, "TextureValues")) return;
|
||||
!mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.ReferencedTextures.Count < 1) return;
|
||||
|
||||
_bitmaps[0][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(textureValues[0]), IsEnabled = true};
|
||||
_bitmaps[0][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(mapMaterial.ReferencedTextures[0] as UTexture2D), IsEnabled = true};
|
||||
_brMiniMapImage = GetImageSource(_bitmaps[0][_FIRST_BITMAP].Layer);
|
||||
});
|
||||
}
|
||||
|
|
@ -402,8 +390,7 @@ namespace FModel.ViewModels
|
|||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
if (!Utils.TryLoadObject("FortniteGame/Content/UI/IngameMap/UIMapManagerPapaya.Default__UIMapManagerPapaya_C", out UObject mapManager) ||
|
||||
!mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") ||
|
||||
mapMaterial.ReferencedTextures.Count < 1) return;
|
||||
!mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.ReferencedTextures.Count < 1) return;
|
||||
|
||||
_bitmaps[1][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(mapMaterial.ReferencedTextures[0] as UTexture2D), IsEnabled = true};
|
||||
_prMiniMapImage = GetImageSource(_bitmaps[1][_FIRST_BITMAP].Layer);
|
||||
|
|
@ -474,12 +461,16 @@ namespace FModel.ViewModels
|
|||
var patrolsPathBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(patrolsPathBitmap);
|
||||
|
||||
var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibrary_Overlay_S18");
|
||||
var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Artemis_Overlay_S19_NPCLibrary");
|
||||
foreach (var export in exports)
|
||||
{
|
||||
if (!export.ExportType.Equals("FortAthenaPatrolPath", StringComparison.OrdinalIgnoreCase) ||
|
||||
!export.TryGetValue(out FPackageIndex[] patrolPoints, "PatrolPoints")) continue;
|
||||
|
||||
var displayName = export.Name["FortAthenaPatrolPath_".Length..];
|
||||
if (export.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags") && gameplayTags.GameplayTags.Length > 0)
|
||||
displayName = gameplayTags.GameplayTags[0].Text["Athena.AI.SpawnLocation.Tandem.".Length..];
|
||||
|
||||
if (!Utils.TryGetPackageIndexExport(patrolPoints[0], out UObject uObject) ||
|
||||
!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") ||
|
||||
!Utils.TryGetPackageIndexExport(rootComponent, out uObject) ||
|
||||
|
|
@ -487,7 +478,6 @@ namespace FModel.ViewModels
|
|||
|
||||
var path = new SKPath();
|
||||
var vector = GetMapPosition(relativeLocation, _brRadius);
|
||||
var displayName = export.Name["FortAthenaPatrolPath_Tandem_S18_".Length..];
|
||||
path.MoveTo(vector.X, vector.Y);
|
||||
|
||||
for (var i = 1; i < patrolPoints.Length; i++)
|
||||
|
|
@ -737,7 +727,7 @@ namespace FModel.ViewModels
|
|||
var upgradeBenchesBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(upgradeBenchesBitmap);
|
||||
|
||||
var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Apollo_Terrain_NPCLibrary_Stations_UpgradeBenches");
|
||||
var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Artemis_Overlay_S19_UpgradeBenches");
|
||||
foreach (var export in exports)
|
||||
{
|
||||
if (!export.ExportType.Equals("B_Athena_Spawner_UpgradeStation_C", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
|
@ -793,7 +783,7 @@ namespace FModel.ViewModels
|
|||
var vendingMachinesBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(vendingMachinesBitmap);
|
||||
|
||||
var exports = Utils.LoadExports("FortniteGame/Content/Athena/Apollo/Maps/Special/ItemCollections/Apollo_Item_VendingMachines");
|
||||
var exports = Utils.LoadExports("/NPCLibrary/LevelOverlays/Artemis_Overlay_S19_ServiceStations");
|
||||
foreach (var export in exports)
|
||||
{
|
||||
if (!export.ExportType.Equals("B_Athena_Spawner_VendingMachine_MendingOnly_C", StringComparison.OrdinalIgnoreCase) &&
|
||||
|
|
@ -814,19 +804,19 @@ namespace FModel.ViewModels
|
|||
});
|
||||
}
|
||||
|
||||
private async Task LoadFireflies()
|
||||
private async Task LoadBountyBoards()
|
||||
{
|
||||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
_fillPaint.StrokeWidth = 5;
|
||||
var firefliesBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(firefliesBitmap);
|
||||
var bountyBoardsBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(bountyBoardsBitmap);
|
||||
|
||||
var exports = Utils.LoadExports("FortniteGame/Content/Athena/Apollo/Maps/Special/ItemCollections/Apollo_Item_Fireflies");
|
||||
var exports = Utils.LoadExports("Bounties/Maps/BB_Overlay_S19_ServiceStations.umap");
|
||||
foreach (var export in exports)
|
||||
{
|
||||
if (!export.ExportType.Equals("BP_BGACSpawner_Fireflies_C", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
var displayName = $"FF_{export.Name["BP_BGACSpawnerFireFlies".Length..]}";
|
||||
if (!export.ExportType.Equals("B_Bounties_Spawner_BountyBoard_C", StringComparison.OrdinalIgnoreCase)) continue;
|
||||
var displayName = $"BountyBoard_{export.Name["BP_BountyBoard_C_".Length..]}";
|
||||
|
||||
if (!export.TryGetValue(out FPackageIndex rootComponent, "RootComponent") ||
|
||||
!Utils.TryGetPackageIndexExport(rootComponent, out UObject uObject) ||
|
||||
|
|
@ -838,7 +828,7 @@ namespace FModel.ViewModels
|
|||
c.DrawText(displayName, vector.X, vector.Y - 12.5F, _textPaint);
|
||||
}
|
||||
|
||||
_bitmaps[0]["ApolloGameplay_Fireflies"] = new MapLayer {Layer = firefliesBitmap, IsEnabled = false};
|
||||
_bitmaps[0]["ApolloGameplay_BountyBoards"] = new MapLayer {Layer = bountyBoardsBitmap, IsEnabled = false};
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -874,93 +864,5 @@ namespace FModel.ViewModels
|
|||
_bitmaps[0]["ApolloGameplay_TagsLocation"] = new MapLayer {Layer = tagsLocationBitmap, IsEnabled = false};
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FortniteGame/Plugins/GameFeatures/CorruptionGameplay/Content/CorruptionGameplay_LevelOverlay.uasset
|
||||
/// too lazy to filters
|
||||
/// </summary>
|
||||
private async Task LoadCubeMovements()
|
||||
{
|
||||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
_fillPaint.StrokeWidth = 5;
|
||||
var cubeMovementsBitmap = new SKBitmap(_widthHeight, _widthHeight, SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
using var c = new SKCanvas(cubeMovementsBitmap);
|
||||
|
||||
if (!Utils.TryLoadObject("/CorruptionGameplay/Levels/CorruptionGameplay_ApolloTerrain_Overlay.BP_CubeMovementGradient_2", out UObject overlay) ||
|
||||
!overlay.TryGetValue(out FSoftObjectPath[] cubeMovementStaticPaths, "cubeMovementStaticPaths") || cubeMovementStaticPaths.Length < 1)
|
||||
return;
|
||||
|
||||
var oldColor = _pathPaint.Color;
|
||||
_pathPaint.Color = SKColors.Purple;
|
||||
foreach (var cubeMovementStaticPath in cubeMovementStaticPaths)
|
||||
{
|
||||
var objectPath = cubeMovementStaticPath.AssetPathName.Text.SubstringBeforeLast(".");
|
||||
var objectName = cubeMovementStaticPath.SubPathString.SubstringAfterLast(".");
|
||||
if (!Utils.TryLoadObject($"{objectPath}.{objectName}", out UObject staticPath))
|
||||
return;
|
||||
|
||||
DrawCubeMovements(c, staticPath, true);
|
||||
}
|
||||
|
||||
if (Utils.TryLoadObject("/CorruptionGameplay/Levels/CubeMovement/Apollo_CM_Gold_Overlay.CM_Spline_Gold", out UObject goldPath))
|
||||
{
|
||||
_pathPaint.Color = SKColors.Gold;
|
||||
DrawCubeMovements(c, goldPath, false);
|
||||
}
|
||||
|
||||
_pathPaint.Color = oldColor;
|
||||
_bitmaps[0]["ApolloGameplay_CubeMovements"] = new MapLayer {Layer = cubeMovementsBitmap, IsEnabled = false};
|
||||
});
|
||||
}
|
||||
|
||||
private void DrawCubeMovements(SKCanvas c, UObject staticPath, bool fixLocation)
|
||||
{
|
||||
if (!staticPath.TryGetValue(out FStructFallback[] pathTravelers, "PathTravelers") || pathTravelers.Length < 1 ||
|
||||
!pathTravelers[0].TryGetValue(out FPackageIndex[] generatedSplinesArray, "GeneratedSplinesArray") || generatedSplinesArray.Length < 1)
|
||||
return;
|
||||
|
||||
UObject uObject;
|
||||
var parentRelativeLocation = new FVector();
|
||||
if (fixLocation)
|
||||
{
|
||||
if (!pathTravelers[0].TryGetValue(out FPackageIndex pathTraveler, "PathTraveler") ||
|
||||
!Utils.TryGetPackageIndexExport(pathTraveler, out uObject) ||
|
||||
!uObject.TryGetValue(out FPackageIndex rootComponent, "RootComponent") ||
|
||||
!Utils.TryGetPackageIndexExport(rootComponent, out uObject) ||
|
||||
!uObject.TryGetValue(out parentRelativeLocation, "RelativeLocation"))
|
||||
return;
|
||||
}
|
||||
|
||||
var bDone = false;
|
||||
var path = new SKPath();
|
||||
foreach (var generatedSpline in generatedSplinesArray)
|
||||
{
|
||||
if (!Utils.TryGetPackageIndexExport(generatedSpline, out uObject) ||
|
||||
!uObject.TryGetValue(out FVector relativeLocation, "RelativeLocation")) continue;
|
||||
|
||||
if (!uObject.TryGetValue(out FStructFallback splineCurves, "SplineCurves") ||
|
||||
!splineCurves.TryGetValue(out FStructFallback positions, "Position") ||
|
||||
!positions.TryGetValue(out FStructFallback[] positionPoints, "Points")) continue;
|
||||
|
||||
foreach (var positionPoint in positionPoints)
|
||||
{
|
||||
if (!positionPoint.TryGetValue(out FVector point, "OutVal")) continue;
|
||||
|
||||
var vector = GetMapPosition(parentRelativeLocation + relativeLocation + point, _brRadius);
|
||||
if (!bDone)
|
||||
{
|
||||
path.MoveTo(vector.X, vector.Y);
|
||||
bDone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.LineTo(vector.X, vector.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.DrawPath(path, _pathPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media.Media3D;
|
||||
using CUE4Parse.UE4.Assets;
|
||||
using CUE4Parse.UE4.Assets.Exports;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.StaticMesh;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.Utils;
|
||||
using CUE4Parse_Conversion.Materials;
|
||||
using CUE4Parse_Conversion.Meshes;
|
||||
using CUE4Parse_Conversion.Meshes.glTF;
|
||||
using CUE4Parse_Conversion.Meshes.PSK;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using FModel.Framework;
|
||||
|
|
@ -25,10 +31,18 @@ using HelixToolkit.Wpf.SharpDX;
|
|||
using Ookii.Dialogs.Wpf;
|
||||
using Serilog;
|
||||
using SharpDX;
|
||||
using SharpGLTF.Geometry;
|
||||
using SharpGLTF.Geometry.VertexTypes;
|
||||
using SharpGLTF.Scenes;
|
||||
using SharpGLTF.Schema2;
|
||||
using SharpGLTF.Transforms;
|
||||
using SkiaSharp;
|
||||
using Camera = HelixToolkit.Wpf.SharpDX.Camera;
|
||||
using Geometry3D = HelixToolkit.SharpDX.Core.Geometry3D;
|
||||
using PerspectiveCamera = HelixToolkit.Wpf.SharpDX.PerspectiveCamera;
|
||||
using Vector2 = SharpDX.Vector2;
|
||||
using Vector3 = SharpDX.Vector3;
|
||||
using VERTEX = SharpGLTF.Geometry.VertexTypes.VertexPositionNormalTangent;
|
||||
|
||||
namespace FModel.ViewModels
|
||||
{
|
||||
|
|
@ -36,7 +50,6 @@ namespace FModel.ViewModels
|
|||
{
|
||||
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
|
||||
|
||||
#region BINDINGS
|
||||
private EffectsManager _effectManager;
|
||||
public EffectsManager EffectManager
|
||||
{
|
||||
|
|
@ -51,43 +64,11 @@ namespace FModel.ViewModels
|
|||
set => SetProperty(ref _cam, value);
|
||||
}
|
||||
|
||||
private Geometry3D _xAxis;
|
||||
public Geometry3D XAxis
|
||||
{
|
||||
get => _xAxis;
|
||||
set => SetProperty(ref _xAxis, value);
|
||||
}
|
||||
|
||||
private Geometry3D _yAxis;
|
||||
public Geometry3D YAxis
|
||||
{
|
||||
get => _yAxis;
|
||||
set => SetProperty(ref _yAxis, value);
|
||||
}
|
||||
|
||||
private Geometry3D _zAxis;
|
||||
public Geometry3D ZAxis
|
||||
{
|
||||
get => _zAxis;
|
||||
set => SetProperty(ref _zAxis, value);
|
||||
}
|
||||
|
||||
private ModelAndCam _selectedModel; // selected mesh
|
||||
public ModelAndCam SelectedModel
|
||||
{
|
||||
get => _selectedModel;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _selectedModel, value);
|
||||
if (_selectedModel == null) return;
|
||||
|
||||
XAxis = _selectedModel.XAxis;
|
||||
YAxis = _selectedModel.YAxis;
|
||||
ZAxis = _selectedModel.ZAxis;
|
||||
Cam.UpDirection = new Vector3D(0, 1, 0);
|
||||
Cam.Position = _selectedModel.Position;
|
||||
Cam.LookDirection = _selectedModel.LookDirection;
|
||||
}
|
||||
set => SetProperty(ref _selectedModel, value);
|
||||
}
|
||||
|
||||
private readonly ObservableCollection<ModelAndCam> _loadedModels; // mesh list
|
||||
|
|
@ -103,7 +84,6 @@ namespace FModel.ViewModels
|
|||
public bool CanAppend => SelectedModel != null;
|
||||
|
||||
public TextureModel HDRi { get; private set; }
|
||||
#endregion
|
||||
|
||||
private readonly FGame _game;
|
||||
private readonly int[] _facesIndex = { 1, 0, 2 };
|
||||
|
|
@ -133,70 +113,64 @@ namespace FModel.ViewModels
|
|||
|
||||
ModelAndCam p;
|
||||
if (AppendMode && CanAppend)
|
||||
{
|
||||
p = SelectedModel;
|
||||
_loadedModels.Add(new ModelAndCam(export) {IsVisible = false});
|
||||
}
|
||||
else
|
||||
{
|
||||
p = new ModelAndCam(export);
|
||||
_loadedModels.Add(p);
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
valid = export switch
|
||||
switch (export)
|
||||
{
|
||||
UStaticMesh st => TryLoadStaticMesh(st, p),
|
||||
USkeletalMesh sk => TryLoadSkeletalMesh(sk, p),
|
||||
UMaterialInstance mi => TryLoadMaterialInstance(mi, p),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(export))
|
||||
};
|
||||
case UStaticMesh st:
|
||||
LoadStaticMesh(st, p);
|
||||
break;
|
||||
case USkeletalMesh sk:
|
||||
LoadSkeletalMesh(sk, p);
|
||||
break;
|
||||
case UMaterialInstance mi:
|
||||
LoadMaterialInstance(mi, p);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(export));
|
||||
}
|
||||
});
|
||||
if (!valid) return;
|
||||
|
||||
if (AppendMode && CanAppend) return;
|
||||
SelectedModel = p;
|
||||
Cam.UpDirection = new Vector3D(0, 1, 0);
|
||||
Cam.Position = p.Position;
|
||||
Cam.LookDirection = p.LookDirection;
|
||||
}
|
||||
|
||||
#region PUBLIC METHODS
|
||||
public void RenderingToggle()
|
||||
{
|
||||
if (SelectedModel == null) return;
|
||||
foreach (var g in SelectedModel.Group3d)
|
||||
{
|
||||
if (g is not MeshGeometryModel3D geometryModel)
|
||||
continue;
|
||||
|
||||
geometryModel.IsRendering = !geometryModel.IsRendering;
|
||||
}
|
||||
SelectedModel.RenderingToggle = !SelectedModel.RenderingToggle;
|
||||
}
|
||||
|
||||
public void WirefreameToggle()
|
||||
{
|
||||
if (SelectedModel == null) return;
|
||||
foreach (var g in SelectedModel.Group3d)
|
||||
{
|
||||
if (g is not MeshGeometryModel3D geometryModel)
|
||||
continue;
|
||||
SelectedModel.WireframeToggle = !SelectedModel.WireframeToggle;
|
||||
}
|
||||
|
||||
geometryModel.RenderWireframe = !geometryModel.RenderWireframe;
|
||||
}
|
||||
public void MaterialColorToggle()
|
||||
{
|
||||
if (SelectedModel == null) return;
|
||||
SelectedModel.ShowMaterialColor = !SelectedModel.ShowMaterialColor;
|
||||
}
|
||||
|
||||
public void DiffuseOnlyToggle()
|
||||
{
|
||||
if (SelectedModel == null) return;
|
||||
foreach (var g in SelectedModel.Group3d)
|
||||
{
|
||||
if (g is not MeshGeometryModel3D { Material: PBRMaterial mat })
|
||||
continue;
|
||||
|
||||
//mat.RenderAmbientOcclusionMap = !mat.RenderAmbientOcclusionMap;
|
||||
mat.RenderDisplacementMap = !mat.RenderDisplacementMap;
|
||||
//mat.RenderEmissiveMap = !mat.RenderEmissiveMap;
|
||||
mat.RenderEnvironmentMap = !mat.RenderEnvironmentMap;
|
||||
mat.RenderIrradianceMap = !mat.RenderIrradianceMap;
|
||||
mat.RenderRoughnessMetallicMap = !mat.RenderRoughnessMetallicMap;
|
||||
mat.RenderShadowMap = !mat.RenderShadowMap;
|
||||
mat.RenderNormalMap = !mat.RenderNormalMap;
|
||||
}
|
||||
SelectedModel.DiffuseOnlyToggle = !SelectedModel.DiffuseOnlyToggle;
|
||||
}
|
||||
|
||||
public void FocusOnSelectedMesh()
|
||||
|
|
@ -204,83 +178,170 @@ namespace FModel.ViewModels
|
|||
Cam.AnimateTo(SelectedModel.Position, SelectedModel.LookDirection, new Vector3D(0, 1, 0), 500);
|
||||
}
|
||||
|
||||
public void SaveLoadedModels()
|
||||
public async Task SaveLoadedModels()
|
||||
{
|
||||
if (_loadedModels.Count < 1) return;
|
||||
|
||||
var folderBrowser = new VistaFolderBrowserDialog {ShowNewFolderButton = true};
|
||||
if (folderBrowser.ShowDialog() == false) return;
|
||||
|
||||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
foreach (var model in _loadedModels)
|
||||
{
|
||||
var toSave = new CUE4Parse_Conversion.Exporter(model.Export, UserSettings.Default.TextureExportFormat, UserSettings.Default.LodExportFormat, UserSettings.Default.MeshExportFormat);
|
||||
if (toSave.TryWriteToDir(new DirectoryInfo(folderBrowser.SelectedPath), out var savedFileName))
|
||||
{
|
||||
Log.Information("Successfully saved {FileName}", savedFileName);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Successfully saved {savedFileName}", Constants.WHITE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("{FileName} could not be saved", savedFileName);
|
||||
FLogger.AppendError();
|
||||
FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SaveAsScene()
|
||||
{
|
||||
if (_loadedModels.Count < 1) return;
|
||||
|
||||
var fileBrowser = new VistaSaveFileDialog
|
||||
{
|
||||
Title = "Save Loaded Models As...",
|
||||
DefaultExt = ".glb",
|
||||
Filter = "glTF Binary File (*.glb)|*.glb|glTF ASCII File (*.gltf)|*.gltf|All Files(*.*)|*.*",
|
||||
AddExtension = true,
|
||||
OverwritePrompt = true,
|
||||
CheckPathExists = true
|
||||
};
|
||||
|
||||
if (fileBrowser.ShowDialog() == false || string.IsNullOrEmpty(fileBrowser.FileName)) return;
|
||||
|
||||
var sceneBuilder = new SceneBuilder();
|
||||
var materialExports = new List<MaterialExporter>();
|
||||
foreach (var model in _loadedModels)
|
||||
{
|
||||
var toSave = new CUE4Parse_Conversion.Exporter(model.Export, UserSettings.Default.TextureExportFormat, UserSettings.Default.LodExportFormat, UserSettings.Default.MeshExportFormat);
|
||||
if (toSave.TryWriteToDir(new DirectoryInfo(folderBrowser.SelectedPath), out var savedFileName))
|
||||
switch (model.Export)
|
||||
{
|
||||
Log.Information("Successfully saved {FileName}", savedFileName);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Successfully saved {savedFileName}", Constants.WHITE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("{FileName} could not be saved", savedFileName);
|
||||
FLogger.AppendError();
|
||||
FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true);
|
||||
case UStaticMesh sm:
|
||||
{
|
||||
var mesh = new MeshBuilder<VERTEX, VertexColorXTextureX, VertexEmpty>(sm.Name);
|
||||
if (sm.TryConvert(out var convertedMesh) && convertedMesh.LODs.Count > 0)
|
||||
{
|
||||
var lod = convertedMesh.LODs.First();
|
||||
for (var i = 0; i < lod.Sections.Value.Length; i++)
|
||||
{
|
||||
Gltf.ExportStaticMeshSections(i, lod, lod.Sections.Value[i], materialExports, mesh);
|
||||
}
|
||||
sceneBuilder.AddRigidMesh(mesh, AffineTransform.Identity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USkeletalMesh sk:
|
||||
{
|
||||
var mesh = new MeshBuilder<VERTEX, VertexColorXTextureX, VertexJoints4>(sk.Name);
|
||||
|
||||
if (sk.TryConvert(out var convertedMesh) && convertedMesh.LODs.Count > 0)
|
||||
{
|
||||
var lod = convertedMesh.LODs.First();
|
||||
for (var i = 0; i < lod.Sections.Value.Length; i++)
|
||||
{
|
||||
Gltf.ExportSkelMeshSections(i, lod, lod.Sections.Value[i], materialExports, mesh);
|
||||
}
|
||||
var armatureNodeBuilder = new NodeBuilder(sk.Name+".ao");
|
||||
var armature = Gltf.CreateGltfSkeleton(convertedMesh.RefSkeleton, armatureNodeBuilder);
|
||||
sceneBuilder.AddSkinnedMesh(mesh, Matrix4x4.Identity, armature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scene = sceneBuilder.ToGltf2();
|
||||
var fileName = fileBrowser.FileName;
|
||||
if (fileName.EndsWith(".glb", StringComparison.OrdinalIgnoreCase))
|
||||
scene.SaveGLB(fileName);
|
||||
else if (fileName.EndsWith(".gltf", StringComparison.OrdinalIgnoreCase))
|
||||
scene.SaveGLTF(fileName);
|
||||
else if (fileName.EndsWith(".obj", StringComparison.OrdinalIgnoreCase))
|
||||
scene.SaveAsWavefront(fileName);
|
||||
else
|
||||
throw new ArgumentOutOfRangeException(nameof(fileName),$@"Unknown file format {fileName. SubstringAfterWithLast('.')}");
|
||||
|
||||
if (!CheckIfSaved(fileName)) return;
|
||||
foreach (var materialExport in materialExports)
|
||||
{
|
||||
materialExport.TryWriteToDir(new DirectoryInfo(StringUtils.SubstringBeforeWithLast(fileName, '\\')), out _);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopySelectedMaterialName()
|
||||
{
|
||||
if (SelectedModel is not { } m || m.SelectedGeometry is null)
|
||||
if (SelectedModel is not { } m || m.SelectedGeometry?.Tag is null)
|
||||
return;
|
||||
|
||||
Clipboard.SetText(m.SelectedGeometry.Name.TrimEnd());
|
||||
Clipboard.SetText(m.SelectedGeometry.DisplayName.TrimEnd());
|
||||
}
|
||||
|
||||
public async Task<bool> TryChangeSelectedMaterial(UMaterialInstance materialInstance)
|
||||
public async Task<bool> TryOverwriteMaterial(UMaterialInstance materialInstance)
|
||||
{
|
||||
if (SelectedModel is not { } model || model.SelectedGeometry is null)
|
||||
return false;
|
||||
if (SelectedModel?.SelectedGeometry == null || _loadedModels.Count < 1) return false;
|
||||
|
||||
PBRMaterial m = null;
|
||||
await _threadWorkerView.Begin(_ =>
|
||||
{
|
||||
var (material, _, _) = LoadMaterial(materialInstance);
|
||||
m = material;
|
||||
(m, var _, var _) = LoadMaterial(materialInstance);
|
||||
|
||||
var obj = new ResolvedLoadedObject(materialInstance);
|
||||
switch (_loadedModels[SelectedModel.SelectedGeometry.ExportIndex].Export)
|
||||
{
|
||||
case UStaticMesh { Materials: { } } st:
|
||||
st.Materials[SelectedModel.SelectedGeometry.MaterialIndex] = obj;
|
||||
break;
|
||||
case USkeletalMesh sk:
|
||||
sk.Materials[SelectedModel.SelectedGeometry.MaterialIndex].Material = obj;
|
||||
break;
|
||||
case UMaterialInstance:
|
||||
SelectedModel.SwapExport(materialInstance);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (m == null) return false;
|
||||
model.SelectedGeometry.Material = m;
|
||||
return true;
|
||||
SelectedModel.SelectedGeometry.Material = m;
|
||||
return m != null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool TryLoadMaterialInstance(UMaterialInstance materialInstance, ModelAndCam cam)
|
||||
private void LoadMaterialInstance(UMaterialInstance materialInstance, ModelAndCam cam)
|
||||
{
|
||||
var builder = new MeshBuilder();
|
||||
builder.AddSphere(Vector3.Zero, 10);
|
||||
cam.TriangleCount = 1984; // no need to count
|
||||
builder.AddBox(Vector3.Zero, 10, 10, 10);
|
||||
cam.TriangleCount = 12; // no need to count
|
||||
|
||||
SetupCameraAndAxis(new FBox(new FVector(-11), new FVector(11)), cam);
|
||||
SetupCameraAndAxis(new FBox(new FVector(-8), new FVector(8)), cam);
|
||||
var (m, isRendering, isTransparent) = LoadMaterial(materialInstance);
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
cam.Group3d.Add(new MeshGeometryModel3D
|
||||
cam.Group3d.Add(new CustomMeshGeometryModel3D
|
||||
{
|
||||
Transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1,0,0), -90)),
|
||||
Name = FixName(materialInstance.Name), Geometry = builder.ToMeshGeometry3D(),
|
||||
Material = m, IsTransparent = isTransparent, IsRendering = isRendering
|
||||
Transform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0,1,0), -45)),
|
||||
DisplayName = materialInstance.Name, Geometry = builder.ToMeshGeometry3D(), MaterialIndex = 0,
|
||||
Material = m, IsTransparent = isTransparent, IsRendering = isRendering, ExportIndex = _loadedModels.Count - 1
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryLoadStaticMesh(UStaticMesh mesh, ModelAndCam cam)
|
||||
private void LoadStaticMesh(UStaticMesh mesh, ModelAndCam cam)
|
||||
{
|
||||
if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
SetupCameraAndAxis(convertedMesh.BoundingBox, cam);
|
||||
|
|
@ -290,15 +351,13 @@ namespace FModel.ViewModels
|
|||
PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryLoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam)
|
||||
private void LoadSkeletalMesh(USkeletalMesh mesh, ModelAndCam cam)
|
||||
{
|
||||
if (!mesh.TryConvert(out var convertedMesh) || convertedMesh.LODs.Count <= 0)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
SetupCameraAndAxis(convertedMesh.BoundingBox, cam);
|
||||
|
|
@ -308,16 +367,16 @@ namespace FModel.ViewModels
|
|||
PushLod(lod.Sections.Value, lod.Verts, lod.Indices.Value, cam);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void PushLod(CMeshSection[] sections, CMeshVertex[] verts, FRawStaticIndexBuffer indices, ModelAndCam cam)
|
||||
{
|
||||
foreach (var section in sections) // each section is a mesh part with its own material
|
||||
for (int i = 0; i < sections.Length; i++) // each section is a mesh part with its own material
|
||||
{
|
||||
var section = sections[i];
|
||||
var builder = new MeshBuilder();
|
||||
cam.TriangleCount += section.NumFaces; // NumFaces * 3 (triangle) = next section FirstIndex
|
||||
|
||||
for (var j = 0; j < section.NumFaces; j++) // draw a triangle for each face
|
||||
{
|
||||
foreach (var t in _facesIndex) // triangle face 1 then 0 then 2
|
||||
|
|
@ -327,22 +386,23 @@ namespace FModel.ViewModels
|
|||
var p = new Vector3(vert.Position.X, vert.Position.Z, vert.Position.Y); // up direction is Y
|
||||
var n = new Vector3(vert.Normal.X, vert.Normal.Z, vert.Normal.Y);
|
||||
n.Normalize();
|
||||
var uv = new Vector2(vert.UV.U, vert.UV.V);
|
||||
builder.AddNode(p, n, uv);
|
||||
|
||||
builder.AddNode(p, n, new Vector2(vert.UV.U, vert.UV.V));
|
||||
builder.TriangleIndices.Add(j * 3 + t); // one mesh part is "j * 3 + t" use "id" if you're building the full mesh
|
||||
}
|
||||
}
|
||||
|
||||
if (section.Material == null || !section.Material.TryLoad<UMaterialInterface>(out var unrealMaterial))
|
||||
if (section.Material == null || !section.Material.TryLoad(out var o) || o is not UMaterialInterface material)
|
||||
continue;
|
||||
|
||||
var (m, isRendering, isTransparent) = LoadMaterial(unrealMaterial);
|
||||
var (m, isRendering, isTransparent) = LoadMaterial(material);
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
cam.Group3d.Add(new MeshGeometryModel3D
|
||||
cam.Group3d.Add(new CustomMeshGeometryModel3D
|
||||
{
|
||||
Name = FixName(unrealMaterial.Name), Geometry = builder.ToMeshGeometry3D(),
|
||||
Material = m, IsTransparent = isTransparent, IsRendering = isRendering
|
||||
DisplayName = section.MaterialName ?? material.Name, MaterialIndex = section.MaterialIndex,
|
||||
Geometry = builder.ToMeshGeometry3D(), Material = m, IsTransparent = isTransparent,
|
||||
IsRendering = isRendering, ExportIndex = _loadedModels.Count - 1
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -350,17 +410,37 @@ namespace FModel.ViewModels
|
|||
|
||||
private (PBRMaterial material, bool isRendering, bool isTransparent) LoadMaterial(UMaterialInterface unrealMaterial)
|
||||
{
|
||||
var m = new PBRMaterial { RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true };
|
||||
PBRMaterial m = null; // default
|
||||
Application.Current.Dispatcher.Invoke(() => // tweak this later
|
||||
{
|
||||
m = new PBRMaterial // recreate on ui thread
|
||||
{
|
||||
RenderShadowMap = true, EnableAutoTangent = true, RenderEnvironmentMap = true
|
||||
};
|
||||
});
|
||||
|
||||
var parameters = new CMaterialParams();
|
||||
unrealMaterial.GetParams(parameters);
|
||||
|
||||
var isRendering = !parameters.IsNull;
|
||||
if (isRendering)
|
||||
{
|
||||
if (parameters.Diffuse is UTexture2D diffuse)
|
||||
m.AlbedoMap = new TextureModel(diffuse.Decode()?.Encode().AsStream());
|
||||
if (!parameters.HasTopDiffuseTexture && parameters.DiffuseColor is { A: > 0 } diffuseColor)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() => m.AlbedoColor = new Color4(diffuseColor.R, diffuseColor.G, diffuseColor.B, diffuseColor.A));
|
||||
}
|
||||
else if (parameters.Diffuse is UTexture2D diffuse)
|
||||
{
|
||||
var s = diffuse.Decode()?.Encode().AsStream();
|
||||
Application.Current.Dispatcher.Invoke(() => m.AlbedoMap = new TextureModel(s));
|
||||
}
|
||||
|
||||
if (parameters.Normal is UTexture2D normal)
|
||||
m.NormalMap = new TextureModel(normal.Decode()?.Encode().AsStream());
|
||||
{
|
||||
var s = normal.Decode()?.Encode().AsStream();
|
||||
Application.Current.Dispatcher.Invoke(() => m.NormalMap = new TextureModel(s));
|
||||
}
|
||||
|
||||
if (parameters.Specular is UTexture2D specular)
|
||||
{
|
||||
var mip = specular.GetFirstMip();
|
||||
|
|
@ -379,12 +459,14 @@ namespace FModel.ViewModels
|
|||
{
|
||||
var offset = 0;
|
||||
fixed (byte* d = data)
|
||||
{
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
{
|
||||
d[offset] = 0;
|
||||
(d[offset+1], d[offset+2]) = (d[offset+2], d[offset+1]); // swap G and B
|
||||
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // swap G and B
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
parameters.RoughnessValue = 1;
|
||||
parameters.MetallicValue = 1;
|
||||
|
|
@ -392,20 +474,40 @@ namespace FModel.ViewModels
|
|||
}
|
||||
case FGame.ShooterGame:
|
||||
{
|
||||
// Valorant's Specular Texture Channels
|
||||
// R Metallic
|
||||
// G Specular
|
||||
// B Roughness
|
||||
unsafe
|
||||
var packedPBRType = specular.Name[(specular.Name.LastIndexOf('_') + 1)..];
|
||||
switch (packedPBRType)
|
||||
{
|
||||
var offset = 0;
|
||||
fixed (byte* d = data)
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
case "MRAE": // R: Metallic, G: AO (0-127) & Emissive (128-255), B: Roughness (Character PBR)
|
||||
unsafe
|
||||
{
|
||||
(d[offset], d[offset+2]) = (d[offset+2], d[offset]); // swap R and B
|
||||
(d[offset], d[offset+1]) = (d[offset+1], d[offset]); // swap B and G
|
||||
offset += 4;
|
||||
var offset = 0;
|
||||
fixed (byte* d = data)
|
||||
{
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
{
|
||||
(d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
|
||||
(d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // swap R and G
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "MRAS": // R: Metallic, B: Roughness, B: AO, A: Specular (Legacy PBR)
|
||||
case "MRA": // R: Metallic, B: Roughness, B: AO (Environment PBR)
|
||||
case "MRS": // R: Metallic, G: Roughness, B: Specular (Weapon PBR)
|
||||
unsafe
|
||||
{
|
||||
var offset = 0;
|
||||
fixed (byte* d = data)
|
||||
{
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
{
|
||||
(d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
parameters.RoughnessValue = 1;
|
||||
parameters.MetallicValue = 1;
|
||||
|
|
@ -421,11 +523,13 @@ namespace FModel.ViewModels
|
|||
{
|
||||
var offset = 0;
|
||||
fixed (byte* d = data)
|
||||
{
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
{
|
||||
(d[offset], d[offset+2]) = (d[offset+2], d[offset]); // swap R and B
|
||||
(d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // swap R and B
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -441,15 +545,30 @@ namespace FModel.ViewModels
|
|||
}
|
||||
|
||||
// R -> AO G -> Roughness B -> Metallic
|
||||
m.RoughnessMetallicMap = new TextureModel(bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream());
|
||||
m.RoughnessFactor = parameters.RoughnessValue;
|
||||
m.MetallicFactor = parameters.MetallicValue;
|
||||
m.RenderAmbientOcclusionMap = parameters.SpecularValue > 0;
|
||||
var s = bitmap.Encode(SKEncodedImageFormat.Png, 100).AsStream();
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
m.RoughnessMetallicMap = new TextureModel(s);
|
||||
m.RoughnessFactor = parameters.RoughnessValue;
|
||||
m.MetallicFactor = parameters.MetallicValue;
|
||||
m.RenderAmbientOcclusionMap = parameters.SpecularValue > 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (parameters.HasTopEmissiveTexture && parameters.Emissive is UTexture2D emissive && parameters.EmissiveColor is { A: > 0 } emissiveColor)
|
||||
{
|
||||
var s = emissive.Decode()?.Encode().AsStream();
|
||||
var c = new Color4(emissiveColor.R, emissiveColor.G, emissiveColor.B, emissiveColor.A);
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
m.EmissiveColor = c;
|
||||
m.EmissiveMap = new TextureModel(s);
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m.AlbedoColor = new Color4(1, 0, 0, 1);
|
||||
Application.Current.Dispatcher.Invoke(() => m.AlbedoColor = new Color4(1, 0, 0, 1));
|
||||
}
|
||||
|
||||
return (m, isRendering, parameters.IsTransparent);
|
||||
|
|
@ -474,15 +593,20 @@ namespace FModel.ViewModels
|
|||
cam.LookDirection = new Vector3D(-cam.Position.X + center.X, 0, -cam.Position.Z + center.Y);
|
||||
}
|
||||
|
||||
private string FixName(string input)
|
||||
private bool CheckIfSaved(string path)
|
||||
{
|
||||
if (input.Length < 1)
|
||||
return "Material_Has_No_Name";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
Log.Information("Successfully saved {FileName}", path);
|
||||
FLogger.AppendInformation();
|
||||
FLogger.AppendText($"Successfully saved {path}", Constants.WHITE, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (int.TryParse(input[0].ToString(), out _))
|
||||
input = input[1..];
|
||||
|
||||
return input.Replace('-', '_');
|
||||
Log.Error("{FileName} could not be saved", path);
|
||||
FLogger.AppendError();
|
||||
FLogger.AppendText($"Could not save '{path}'", Constants.WHITE, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
|
|
@ -497,7 +621,7 @@ namespace FModel.ViewModels
|
|||
|
||||
public class ModelAndCam : ViewModel
|
||||
{
|
||||
public UObject Export { get; }
|
||||
public UObject Export { get; private set; }
|
||||
public Point3D Position { get; set; }
|
||||
public Vector3D LookDirection { get; set; }
|
||||
public Geometry3D XAxis { get; set; }
|
||||
|
|
@ -505,8 +629,98 @@ namespace FModel.ViewModels
|
|||
public Geometry3D ZAxis { get; set; }
|
||||
public int TriangleCount { get; set; }
|
||||
|
||||
private MeshGeometryModel3D _selectedGeometry; // selected material
|
||||
public MeshGeometryModel3D SelectedGeometry
|
||||
private bool _isVisible = true;
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => SetProperty(ref _isVisible, value);
|
||||
}
|
||||
|
||||
private bool _renderingToggle;
|
||||
public bool RenderingToggle
|
||||
{
|
||||
get => _renderingToggle;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _renderingToggle, value);
|
||||
foreach (var g in Group3d)
|
||||
{
|
||||
if (g is not CustomMeshGeometryModel3D geometryModel)
|
||||
continue;
|
||||
|
||||
geometryModel.IsRendering = !geometryModel.IsRendering;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _wireframeToggle;
|
||||
public bool WireframeToggle
|
||||
{
|
||||
get => _wireframeToggle;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _wireframeToggle, value);
|
||||
foreach (var g in Group3d)
|
||||
{
|
||||
if (g is not CustomMeshGeometryModel3D geometryModel)
|
||||
continue;
|
||||
|
||||
geometryModel.RenderWireframe = !geometryModel.RenderWireframe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _showMaterialColor;
|
||||
public bool ShowMaterialColor
|
||||
{
|
||||
get => _showMaterialColor;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _showMaterialColor, value);
|
||||
for (int i = 0; i < Group3d.Count; i++)
|
||||
{
|
||||
if (Group3d[i] is not CustomMeshGeometryModel3D { Material: PBRMaterial material } m)
|
||||
continue;
|
||||
|
||||
var index = B(i);
|
||||
material.RenderAlbedoMap = !_showMaterialColor;
|
||||
|
||||
if (_showMaterialColor)
|
||||
{
|
||||
m.Tag = material.AlbedoColor;
|
||||
material.AlbedoColor = new Color4(_table[C(index)] / 255, _table[C(index >> 1)] / 255, _table[C(index >> 2)] / 255, 1);
|
||||
}
|
||||
else material.AlbedoColor = (Color4) m.Tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _diffuseOnlyToggle;
|
||||
public bool DiffuseOnlyToggle
|
||||
{
|
||||
get => _diffuseOnlyToggle;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _diffuseOnlyToggle, value);
|
||||
foreach (var g in Group3d)
|
||||
{
|
||||
if (g is not CustomMeshGeometryModel3D { Material: PBRMaterial material })
|
||||
continue;
|
||||
|
||||
material.RenderAmbientOcclusionMap = !material.RenderAmbientOcclusionMap;
|
||||
material.RenderDisplacementMap = !material.RenderDisplacementMap;
|
||||
// material.RenderEmissiveMap = !material.RenderEmissiveMap;
|
||||
// material.RenderEnvironmentMap = !material.RenderEnvironmentMap;
|
||||
material.RenderIrradianceMap = !material.RenderIrradianceMap;
|
||||
material.RenderRoughnessMetallicMap = !material.RenderRoughnessMetallicMap;
|
||||
material.RenderShadowMap = !material.RenderShadowMap;
|
||||
material.RenderNormalMap = !material.RenderNormalMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CustomMeshGeometryModel3D _selectedGeometry; // selected material
|
||||
public CustomMeshGeometryModel3D SelectedGeometry
|
||||
{
|
||||
get => _selectedGeometry;
|
||||
set => SetProperty(ref _selectedGeometry, value);
|
||||
|
|
@ -519,6 +733,9 @@ namespace FModel.ViewModels
|
|||
set => SetProperty(ref _group3d, value);
|
||||
}
|
||||
|
||||
private readonly float[] _table = { 255 * 0.9f, 25 * 3.0f, 255 * 0.6f, 255 * 0.0f };
|
||||
private readonly int[] _table2 = { 0, 1, 2, 4, 7, 3, 5, 6 };
|
||||
|
||||
public ModelAndCam(UObject export)
|
||||
{
|
||||
Export = export;
|
||||
|
|
@ -526,6 +743,14 @@ namespace FModel.ViewModels
|
|||
Group3d = new ObservableElement3DCollection();
|
||||
}
|
||||
|
||||
private int B(int x) => (x & 0xFFF8) | _table2[x & 7] ^ 7;
|
||||
private int C(int x) => (x & 1) | ((x >> 2) & 2);
|
||||
|
||||
public void SwapExport(UObject e)
|
||||
{
|
||||
Export = e;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
TriangleCount = 0;
|
||||
|
|
@ -537,4 +762,11 @@ namespace FModel.ViewModels
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomMeshGeometryModel3D : MeshGeometryModel3D
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public int MaterialIndex { get; set; }
|
||||
public int ExportIndex { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using CUE4Parse.UE4.Objects.Core.Serialization;
|
||||
|
|
@ -47,13 +46,6 @@ namespace FModel.ViewModels
|
|||
set => SetProperty(ref _selectedUeGame, value);
|
||||
}
|
||||
|
||||
private UE4Version _selectedUeVersion;
|
||||
public UE4Version SelectedUeVersion
|
||||
{
|
||||
get => _selectedUeVersion;
|
||||
set => SetProperty(ref _selectedUeVersion, value);
|
||||
}
|
||||
|
||||
private List<FCustomVersion> _selectedCustomVersions;
|
||||
public List<FCustomVersion> SelectedCustomVersions
|
||||
{
|
||||
|
|
@ -127,7 +119,6 @@ namespace FModel.ViewModels
|
|||
public ReadOnlyObservableCollection<EUpdateMode> UpdateModes { get; private set; }
|
||||
public ObservableCollection<string> Presets { get; private set; }
|
||||
public ReadOnlyObservableCollection<EGame> UeGames { get; private set; }
|
||||
public ReadOnlyObservableCollection<UE4Version> UeVersions { get; private set; }
|
||||
public ReadOnlyObservableCollection<ELanguage> AssetLanguages { get; private set; }
|
||||
public ReadOnlyObservableCollection<EAesReload> AesReloads { get; private set; }
|
||||
public ReadOnlyObservableCollection<EDiscordRpc> DiscordRpcs { get; private set; }
|
||||
|
|
@ -142,11 +133,11 @@ namespace FModel.ViewModels
|
|||
private readonly FGame _game;
|
||||
private Game _gamePreset;
|
||||
private string _outputSnapshot;
|
||||
private string _modelSnapshot;
|
||||
private string _gameSnapshot;
|
||||
private EUpdateMode _updateModeSnapshot;
|
||||
private string _presetSnapshot;
|
||||
private EGame _ueGameSnapshot;
|
||||
private UE4Version _ueVersionSnapshot;
|
||||
private List<FCustomVersion> _customVersionsSnapshot;
|
||||
private Dictionary<string, bool> _optionsSnapshot;
|
||||
private ELanguage _assetLanguageSnapshot;
|
||||
|
|
@ -164,11 +155,11 @@ namespace FModel.ViewModels
|
|||
public void Initialize()
|
||||
{
|
||||
_outputSnapshot = UserSettings.Default.OutputDirectory;
|
||||
_modelSnapshot = UserSettings.Default.ModelDirectory;
|
||||
_gameSnapshot = UserSettings.Default.GameDirectory;
|
||||
_updateModeSnapshot = UserSettings.Default.UpdateMode;
|
||||
_presetSnapshot = UserSettings.Default.Presets[_game];
|
||||
_ueGameSnapshot = UserSettings.Default.OverridedGame[_game];
|
||||
_ueVersionSnapshot = UserSettings.Default.OverridedUEVersion[_game];
|
||||
_customVersionsSnapshot = UserSettings.Default.OverridedCustomVersions[_game];
|
||||
_optionsSnapshot = UserSettings.Default.OverridedOptions[_game];
|
||||
_assetLanguageSnapshot = UserSettings.Default.AssetLanguage;
|
||||
|
|
@ -181,7 +172,6 @@ namespace FModel.ViewModels
|
|||
SelectedUpdateMode = _updateModeSnapshot;
|
||||
SelectedPreset = _presetSnapshot;
|
||||
SelectedUeGame = _ueGameSnapshot;
|
||||
SelectedUeVersion = _ueVersionSnapshot;
|
||||
SelectedCustomVersions = _customVersionsSnapshot;
|
||||
SelectedOptions = _optionsSnapshot;
|
||||
SelectedAssetLanguage = _assetLanguageSnapshot;
|
||||
|
|
@ -196,7 +186,6 @@ namespace FModel.ViewModels
|
|||
UpdateModes = new ReadOnlyObservableCollection<EUpdateMode>(new ObservableCollection<EUpdateMode>(EnumerateUpdateModes()));
|
||||
Presets = new ObservableCollection<string>(EnumeratePresets());
|
||||
UeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(EnumerateUeGames()));
|
||||
UeVersions = new ReadOnlyObservableCollection<UE4Version>(new ObservableCollection<UE4Version>(EnumerateUeVersions()));
|
||||
AssetLanguages = new ReadOnlyObservableCollection<ELanguage>(new ObservableCollection<ELanguage>(EnumerateAssetLanguages()));
|
||||
AesReloads = new ReadOnlyObservableCollection<EAesReload>(new ObservableCollection<EAesReload>(EnumerateAesReloads()));
|
||||
DiscordRpcs = new ReadOnlyObservableCollection<EDiscordRpc>(new ObservableCollection<EDiscordRpc>(EnumerateDiscordRpcs()));
|
||||
|
|
@ -226,7 +215,6 @@ namespace FModel.ViewModels
|
|||
{
|
||||
if (_gamePreset?.Versions == null || !_gamePreset.Versions.TryGetValue(key, out var version)) return;
|
||||
SelectedUeGame = version.GameEnum.ToEnum(EGame.GAME_UE4_LATEST);
|
||||
SelectedUeVersion = (UE4Version)version.UeVer;
|
||||
|
||||
SelectedCustomVersions = new List<FCustomVersion>();
|
||||
foreach (var (guid, v) in version.CustomVersions)
|
||||
|
|
@ -244,7 +232,6 @@ namespace FModel.ViewModels
|
|||
public void ResetPreset()
|
||||
{
|
||||
SelectedUeGame = _ueGameSnapshot;
|
||||
SelectedUeVersion = _ueVersionSnapshot;
|
||||
SelectedCustomVersions = _customVersionsSnapshot;
|
||||
SelectedOptions = _optionsSnapshot;
|
||||
}
|
||||
|
|
@ -253,19 +240,22 @@ namespace FModel.ViewModels
|
|||
{
|
||||
var ret = SettingsOut.Nothing;
|
||||
|
||||
if (_ueGameSnapshot != SelectedUeGame || _ueVersionSnapshot != SelectedUeVersion || // comboboxes
|
||||
if (_ueGameSnapshot != SelectedUeGame || // combobox
|
||||
_customVersionsSnapshot != SelectedCustomVersions || _optionsSnapshot != SelectedOptions ||
|
||||
_outputSnapshot != UserSettings.Default.OutputDirectory || // textbox
|
||||
_modelSnapshot != UserSettings.Default.ModelDirectory || // textbox
|
||||
_gameSnapshot != UserSettings.Default.GameDirectory) // textbox
|
||||
ret = SettingsOut.Restart;
|
||||
|
||||
if (_assetLanguageSnapshot != SelectedAssetLanguage)
|
||||
ret = SettingsOut.ReloadLocres;
|
||||
|
||||
if (_updateModeSnapshot != SelectedUpdateMode)
|
||||
ret = SettingsOut.CheckForUpdates;
|
||||
|
||||
UserSettings.Default.UpdateMode = SelectedUpdateMode;
|
||||
UserSettings.Default.Presets[_game] = SelectedPreset;
|
||||
UserSettings.Default.OverridedGame[_game] = SelectedUeGame;
|
||||
UserSettings.Default.OverridedUEVersion[_game] = SelectedUeVersion;
|
||||
UserSettings.Default.OverridedCustomVersions[_game] = SelectedCustomVersions;
|
||||
UserSettings.Default.OverridedOptions[_game] = SelectedOptions;
|
||||
UserSettings.Default.AssetLanguage = SelectedAssetLanguage;
|
||||
|
|
@ -283,20 +273,19 @@ namespace FModel.ViewModels
|
|||
return ret;
|
||||
}
|
||||
|
||||
private IEnumerable<EUpdateMode> EnumerateUpdateModes() => Enum.GetValues(SelectedUpdateMode.GetType()).Cast<EUpdateMode>();
|
||||
private IEnumerable<EUpdateMode> EnumerateUpdateModes() => Enum.GetValues<EUpdateMode>();
|
||||
private IEnumerable<string> EnumeratePresets()
|
||||
{
|
||||
yield return Constants._NO_PRESET_TRIGGER;
|
||||
}
|
||||
private IEnumerable<EGame> EnumerateUeGames() => Enum.GetValues(SelectedUeGame.GetType()).Cast<EGame>();
|
||||
private IEnumerable<UE4Version> EnumerateUeVersions() => Enum.GetValues(SelectedUeVersion.GetType()).Cast<UE4Version>();
|
||||
private IEnumerable<ELanguage> EnumerateAssetLanguages() => Enum.GetValues(SelectedAssetLanguage.GetType()).Cast<ELanguage>();
|
||||
private IEnumerable<EAesReload> EnumerateAesReloads() => Enum.GetValues(SelectedAesReload.GetType()).Cast<EAesReload>();
|
||||
private IEnumerable<EDiscordRpc> EnumerateDiscordRpcs() => Enum.GetValues(SelectedDiscordRpc.GetType()).Cast<EDiscordRpc>();
|
||||
private IEnumerable<ECompressedAudio> EnumerateCompressedAudios() => Enum.GetValues(SelectedCompressedAudio.GetType()).Cast<ECompressedAudio>();
|
||||
private IEnumerable<EIconStyle> EnumerateCosmeticStyles() => Enum.GetValues(SelectedCosmeticStyle.GetType()).Cast<EIconStyle>();
|
||||
private IEnumerable<EMeshFormat> EnumerateMeshExportFormat() => Enum.GetValues(SelectedMeshExportFormat.GetType()).Cast<EMeshFormat>();
|
||||
private IEnumerable<ELodFormat> EnumerateLodExportFormat() => Enum.GetValues(SelectedLodExportFormat.GetType()).Cast<ELodFormat>();
|
||||
private IEnumerable<ETextureFormat> EnumerateTextureExportFormat() => Enum.GetValues(SelectedTextureExportFormat.GetType()).Cast<ETextureFormat>();
|
||||
private IEnumerable<EGame> EnumerateUeGames() => Enum.GetValues<EGame>();
|
||||
private IEnumerable<ELanguage> EnumerateAssetLanguages() => Enum.GetValues<ELanguage>();
|
||||
private IEnumerable<EAesReload> EnumerateAesReloads() => Enum.GetValues<EAesReload>();
|
||||
private IEnumerable<EDiscordRpc> EnumerateDiscordRpcs() => Enum.GetValues<EDiscordRpc>();
|
||||
private IEnumerable<ECompressedAudio> EnumerateCompressedAudios() => Enum.GetValues<ECompressedAudio>();
|
||||
private IEnumerable<EIconStyle> EnumerateCosmeticStyles() => Enum.GetValues<EIconStyle>();
|
||||
private IEnumerable<EMeshFormat> EnumerateMeshExportFormat() => Enum.GetValues<EMeshFormat>();
|
||||
private IEnumerable<ELodFormat> EnumerateLodExportFormat() => Enum.GetValues<ELodFormat>();
|
||||
private IEnumerable<ETextureFormat> EnumerateTextureExportFormat() => Enum.GetValues<ETextureFormat>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,22 +4,16 @@ using FModel.Framework;
|
|||
using FModel.Settings;
|
||||
using FModel.ViewModels.Commands;
|
||||
using FModel.Views.Resources.Controls;
|
||||
|
||||
using ICSharpCode.AvalonEdit.Document;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Serilog;
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace FModel.ViewModels
|
||||
|
|
|
|||
|
|
@ -22,28 +22,28 @@
|
|||
<TextBlock Text="{Binding Source={x:Static local:Constants.APP_VERSION}, StringFormat={}FModel {0}}" FontSize="15" FontWeight="500" Foreground="#9DA3DD" FontStretch="Expanded" />
|
||||
<TextBlock Text="Made with ♥ by Asval" FontSize="30" FontWeight="700" Foreground="#DAE5F2" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock Text="History" FontSize="15" FontWeight="700" Foreground="#9DA3DD" FontStretch="Expanded" />
|
||||
<TextBlock Text="				" FontSize="25" FontWeight="700" Height="2" Foreground="Transparent" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<TextBlock FontSize="12" Foreground="#727272" TextWrapping="Wrap" Margin="0 0 0 30"
|
||||
Text="Since the release in March 2019, we've continuously added new features and improved old ones. It started as a simple UE4 file explorer to parse assets and, as things progressed, became really popular to datamine games and create items icons. FModel 4 is now the most complete and well-made version so far. It features dozens of settings for you to use to make FModel your own." />
|
||||
|
||||
Text="Since the release in March 2019, we've continuously added new features and improved old ones. It started as a simple UE4 file explorer to parse packages and, as things progressed, became really popular to data-mine games and create items icons. FModel 4 is now the most complete and well-made version so far. It features dozens of settings for you to use to make FModel your own." />
|
||||
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock Text="Contributors" FontSize="15" FontWeight="700" Foreground="#9DA3DD" FontStretch="Expanded" />
|
||||
<TextBlock Text="				" FontSize="25" FontWeight="700" Height="2" Foreground="Transparent" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<TextBlock FontSize="12" Foreground="#727272" TextWrapping="Wrap" Margin="0 0 0 30"
|
||||
Text="With the help of Waddlesworth, Fabian, Maiky, GMatrix, Amr, Officer, Tiger, Mang0e, and a lot more, this project continues to exist. If you're making money off of FModel consider donating to sustain FModel's continued improvements." />
|
||||
|
||||
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock Text="Donators" FontSize="15" FontWeight="700" Foreground="#9DA3DD" FontStretch="Expanded" />
|
||||
<TextBlock Text="				" FontSize="25" FontWeight="700" Height="2" Foreground="Transparent" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<TextBlock FontSize="12" Foreground="#727272" TextWrapping="Wrap" Margin="0 0 0 30"
|
||||
Text="TheGameVlog ♥, Quentin ♥, Maiky ♥, HYPEX ♥, Evan, VenomLeaks, JayKey, Fevers, Netu, Laggy, s0ll, RazTracker, Mikey, kyle, Yanteh, Shiina, SexyNutella, Alexander, Jinx, Tector, imatrix, LamZykoss, Frenzy Leaks, LlamaLeaks, XTigerHyperX, FunGames, WeLoveFortnite." />
|
||||
|
||||
Text="TheGameVlog ♥, Quentin ♥, Maiky ♥, HYPEX ♥, AnimatedAspect, Evan, VenomLeaks, JayKey, Fevers, Netu, Laggy, s0ll, RazTracker, Mikey, kyle, Yanteh, Shiina, SexyNutella, Alexander, Jinx, koba, Tector, imatrix, LamZykoss, Frenzy Leaks, LlamaLeaks, xplore, XTigerHyperX, FunGames, WeLoveFortnite." />
|
||||
|
||||
<StackPanel HorizontalAlignment="Center">
|
||||
<TextBlock Text="Powered by" FontSize="15" FontWeight="700" Foreground="#9DA3DD" FontStretch="Expanded" />
|
||||
<TextBlock Text="				" FontSize="25" FontWeight="700" Height="2" Foreground="Transparent" HorizontalAlignment="Center" />
|
||||
|
|
@ -51,4 +51,4 @@
|
|||
<TextBlock FontSize="12" Foreground="#727272" TextWrapping="Wrap" Margin="0 0 0 30"
|
||||
Text="CUE4Parse, BenBot, Fortnite-Api, AdonisUI, AvalonEdit, CSCore, NVorbis, VgmStream, RestSharp, Serilog, Discord, K4os.Compression.LZ4, Ookii.Dialogs, Newtonsoft.Json, ..." />
|
||||
</StackPanel>
|
||||
</adonisControls:AdonisWindow>
|
||||
</adonisControls:AdonisWindow>
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@
|
|||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="10 5 10 10">
|
||||
<TextBlock Text="What to do?" HorizontalAlignment="Center" FontSize="20" FontWeight="SemiBold" />
|
||||
<TextBlock TextAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Center" MaxWidth="576"
|
||||
Text="In order to decipher files' information, an AES key, in most cases, is needed. Here you can set the key for your static and dynamic files. If you don't know what key to use for your set game, simply Google it. Keys must start with "0x" and contains 64 more characters." />
|
||||
Text="In order to decipher archives' information, an AES key, in most cases, is needed. Here you can set the key for your static and dynamic archives. If you don't know what key to use for your set game, simply Google it. Keys must start with "0x" and contains 64 more characters." />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<GroupBox Grid.Row="1" adonisExtensions:LayerExtension.Layer="2" Margin="10 10 10 18"
|
||||
Padding="{adonisUi:Space 0}" Background="Transparent">
|
||||
<Grid>
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
<ColumnDefinition SharedSizeGroup="Name" Width="Auto" />
|
||||
<ColumnDefinition SharedSizeGroup="Key" Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<ScrollViewer MaxHeight="350"
|
||||
adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode="NeverExpand"
|
||||
adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement="Docked">
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition SharedSizeGroup="Key" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<TextBlock Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right"
|
||||
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBox Grid.Column="2" HorizontalContentAlignment="Left" HorizontalAlignment="Stretch"
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
</ScrollViewer>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
<Border Grid.Row="2"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer1BackgroundBrush}}"
|
||||
adonisExtensions:LayerExtension.IncreaseLayer="True">
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<Button Grid.Column="1" MinWidth="78" Margin="0 0 12 0" IsDefault="True" IsCancel="False"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="OK" Click="OnClick" />
|
||||
<Button Grid.Column="2" MinWidth="78" Margin="0 0 12 0" IsDefault="False" IsCancel="False"
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@
|
|||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" TextAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Text="Because it looks like it's pretty hard to understand, you don't load backups, you load your files and compare them with the backup. Also, by clicking the download button you don't create your own backup you download a pre-made one. Kinda crazy we have to explain this, who will even read anyway..." />
|
||||
|
||||
Text="You can only use backup files when loading new & modified archives. FModel will compare your local archives with the backup file you selected to filter packages and only show what you asked. We provide pre-created backups for some popular games but you can still create your own that will store information about all the game's packages at time T, for later use." />
|
||||
|
||||
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Click="OnCreateBackupClick"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.AccentButton}}" Content="Create" />
|
||||
|
||||
|
||||
<Separator Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" Tag="PRE-CREATED BACKUP FILES" />
|
||||
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" VerticalAlignment="Center"
|
||||
Text="{Binding SelectedBackup.FileSize, Converter={x:Static converters:SizeToStringConverter.Instance}, FallbackValue='Backup', StringFormat={}Backup ({0})}" />
|
||||
<ComboBox Grid.Row="4" Grid.Column="2" ItemsSource="{Binding BackupsView}" SelectedItem="{Binding SelectedBackup, Mode=TwoWay}">
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@
|
|||
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="10 5 10 10">
|
||||
<TextBlock Text="What to do?" HorizontalAlignment="Center" FontSize="20" FontWeight="SemiBold" />
|
||||
<TextBlock TextAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Center"
|
||||
Text="We like to make things as simple as possible. Choose between the detected games or manually select your own directory. FModel will use this information to automatically find files to load and decrypt if needed. Make sure to not skip this step!" />
|
||||
Text="We like to make things as simple as possible. Choose between the detected games or manually select your own directory. FModel will use this information to automatically find archives to load and decrypt if needed. Make sure to not skip this step!" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<GroupBox Grid.Row="1" adonisExtensions:LayerExtension.Layer="2" Margin="10 10 10 18"
|
||||
Padding="{adonisUi:Space 0}" Background="Transparent">
|
||||
<StackPanel>
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<TextBox Grid.Column="0" Text="{Binding SelectedDetectedGame.GameDirectory, Mode=TwoWay}" />
|
||||
<Button Grid.Column="2" Content="..." HorizontalAlignment="Right" Click="OnBrowseDirectories" />
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -33,13 +33,11 @@
|
|||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<CheckBox Content="Upgrade Benches" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrUpgradeBenches}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<CheckBox Content="Phonebooths" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrPhonebooths}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<!-- <CheckBox Content="Phonebooths" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrPhonebooths}" -->
|
||||
<!-- DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" /> -->
|
||||
<CheckBox Content="Weapon-o-matic/Mending Machines" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrVendingMachines}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<CheckBox Content="Fireflies" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrFireflies}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
<CheckBox Content="Cube Movements" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrCubeMovements}"
|
||||
<CheckBox Content="Bounty Boards" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" IsChecked="{Binding MapViewer.BrBountyBoards}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.MapViewer}}}" IsEnabled="{Binding IsReady}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</adonisControls:AdonisWindow.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" MinWidth="350" />
|
||||
<ColumnDefinition Width="350" MinWidth="250" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="4*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
|
@ -44,14 +44,7 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Models" VerticalAlignment="Center" Margin="0 0 0 10" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding ModelViewer.LoadedModelsView, IsAsync=True}"
|
||||
SelectedItem="{Binding ModelViewer.SelectedModel, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Export.Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<ComboBox Grid.Row="0" Grid.Column="2" Style="{StaticResource ModelsComboBox}" IsEnabled="{Binding IsReady}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Triangles" VerticalAlignment="Center" Margin="0 0 0 10" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding ModelViewer.SelectedModel.TriangleCount, FallbackValue=0, StringFormat={}{0:### ### ### ###}}" VerticalAlignment="Center" HorizontalAlignment="Right" />
|
||||
|
|
@ -71,20 +64,21 @@
|
|||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Row="0" Grid.Column="0" Content="Focus" Click="OnFocusClick" />
|
||||
<ToggleButton Grid.Row="0" Grid.Column="2" IsChecked="{Binding ModelViewer.AppendMode}" Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarToggleButton}}">
|
||||
<Button Grid.Row="0" Grid.Column="0" Content="Focus" Click="OnFocusClick" IsEnabled="{Binding IsReady}" />
|
||||
<ToggleButton Grid.Row="0" Grid.Column="2" IsChecked="{Binding ModelViewer.AppendMode}" IsEnabled="{Binding IsReady}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarToggleButton}}">
|
||||
<TextBlock Text="{Binding IsChecked, Converter={x:Static converters:BoolToToggleConverter.Instance},
|
||||
StringFormat={}Append {0}, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToggleButton}}}" />
|
||||
</ToggleButton>
|
||||
|
||||
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Click="Save"
|
||||
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Click="Save" IsEnabled="{Binding IsReady}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.AccentButton}}">
|
||||
<TextBlock Text="{Binding ModelViewer.LoadedModelsView.Count, StringFormat={}Save All Loaded Models ({0})}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Separator DockPanel.Dock="Top" Tag="MATERIALS" Style="{StaticResource CustomSeparator}" />
|
||||
<ListBox DockPanel.Dock="Top" Style="{StaticResource MaterialsListBox}">
|
||||
<ListBox x:Name="MaterialsListName" DockPanel.Dock="Top" Style="{StaticResource MaterialsListBox}" IsEnabled="{Binding IsReady}">
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
|
||||
<MenuItem Header="Copy Name" Click="OnCopyClick">
|
||||
|
|
@ -96,11 +90,11 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Change Material" Click="OnChangeMaterialClick">
|
||||
<MenuItem Header="Overwrite Material" Click="OnOverwriteMaterialClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource SwapIcon}" />
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource OverwriteIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
|
|
@ -114,8 +108,10 @@
|
|||
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="4" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer3BackgroundBrush}}" />
|
||||
|
||||
<TextBlock Grid.Column="2" Text="Model is loading, please wait..." HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<helix:Viewport3DX Grid.Column="2" EffectsManager="{Binding ModelViewer.EffectManager}" Camera="{Binding ModelViewer.Cam}"
|
||||
IsChangeFieldOfViewEnabled="False" IsMoveEnabled="False" UseDefaultGestures="False" ShowViewCube="False"
|
||||
Visibility="{Binding IsReady, Converter={StaticResource BoolToVisibilityConverter}}" ShowViewCube="False"
|
||||
IsChangeFieldOfViewEnabled="False" IsMoveEnabled="False" UseDefaultGestures="False"
|
||||
ShowCameraTarget="False" FXAALevel="Ultra" MSAA="Maximum" BackgroundColor="#2A2B34"
|
||||
EnableSSAO="True" SSAOIntensity="1" EnableSwapChainRendering="True">
|
||||
<helix:Viewport3DX.InputBindings>
|
||||
|
|
@ -133,7 +129,7 @@
|
|||
<helix:LineGeometryModel3D Geometry="{Binding ModelViewer.SelectedModel.YAxis}" Color="#85CB22" />
|
||||
<helix:LineGeometryModel3D Geometry="{Binding ModelViewer.SelectedModel.ZAxis}" Color="#388EED" />
|
||||
|
||||
<helix:GroupModel3D x:Name="MyAntiCrashGroup" ItemsSource="{Binding ModelViewer.SelectedModel.Group3d}" />
|
||||
<helix:GroupModel3D x:Name="MyAntiCrashGroup" ItemsSource="{Binding ModelViewer.SelectedModel.Group3d}" Mouse3DDown="OnMouse3DDown" />
|
||||
</helix:Viewport3DX>
|
||||
</Grid>
|
||||
</adonisControls:AdonisWindow>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using CUE4Parse.UE4.Assets.Exports;
|
|||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using FModel.Services;
|
||||
using FModel.ViewModels;
|
||||
using HelixToolkit.Wpf.SharpDX;
|
||||
using MessageBox = AdonisUI.Controls.MessageBox;
|
||||
using MessageBoxImage = AdonisUI.Controls.MessageBoxImage;
|
||||
|
||||
|
|
@ -23,12 +24,12 @@ namespace FModel.Views
|
|||
}
|
||||
|
||||
public async void Load(UObject export) => await _applicationView.ModelViewer.LoadExport(export);
|
||||
public async void Swap(UMaterialInstance materialInstance)
|
||||
public async void Overwrite(UMaterialInstance materialInstance)
|
||||
{
|
||||
var sucess = await _applicationView.ModelViewer.TryChangeSelectedMaterial(materialInstance);
|
||||
var sucess = await _applicationView.ModelViewer.TryOverwriteMaterial(materialInstance);
|
||||
if (sucess)
|
||||
{
|
||||
_applicationView.CUE4Parse.ModelIsSwappingMaterial = false;
|
||||
_applicationView.CUE4Parse.ModelIsOverwritingMaterial = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -47,11 +48,11 @@ namespace FModel.Views
|
|||
{
|
||||
_applicationView.ModelViewer.Clear();
|
||||
_applicationView.ModelViewer.AppendMode = false;
|
||||
_applicationView.CUE4Parse.ModelIsSwappingMaterial = false;
|
||||
_applicationView.CUE4Parse.ModelIsOverwritingMaterial = false;
|
||||
MyAntiCrashGroup.ItemsSource = null; // <3
|
||||
}
|
||||
|
||||
private void OnWindowKeyDown(object sender, KeyEventArgs e)
|
||||
private async void OnWindowKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
|
|
@ -61,34 +62,49 @@ namespace FModel.Views
|
|||
case Key.H:
|
||||
_applicationView.ModelViewer.RenderingToggle();
|
||||
break;
|
||||
// case Key.D:
|
||||
// _applicationView.ModelViewer.DiffuseOnlyToggle();
|
||||
// break;
|
||||
case Key.D:
|
||||
_applicationView.ModelViewer.DiffuseOnlyToggle();
|
||||
break;
|
||||
case Key.M:
|
||||
_applicationView.ModelViewer.MaterialColorToggle();
|
||||
break;
|
||||
case Key.Decimal:
|
||||
_applicationView.ModelViewer.FocusOnSelectedMesh();
|
||||
break;
|
||||
case Key.S when Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && Keyboard.Modifiers.HasFlag(ModifierKeys.Shift):
|
||||
_applicationView.ModelViewer.SaveAsScene();
|
||||
break;
|
||||
case Key.S when Keyboard.Modifiers.HasFlag(ModifierKeys.Control):
|
||||
await _applicationView.ModelViewer.SaveLoadedModels();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouse3DDown(object sender, MouseDown3DEventArgs e)
|
||||
{
|
||||
if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Shift) || e.HitTestResult.ModelHit is not CustomMeshGeometryModel3D m) return;
|
||||
_applicationView.ModelViewer.SelectedModel.SelectedGeometry = m;
|
||||
MaterialsListName.ScrollIntoView(m);
|
||||
}
|
||||
|
||||
private void OnFocusClick(object sender, RoutedEventArgs e)
|
||||
=> _applicationView.ModelViewer.FocusOnSelectedMesh();
|
||||
|
||||
private void OnCopyClick(object sender, RoutedEventArgs e)
|
||||
=> _applicationView.ModelViewer.CopySelectedMaterialName();
|
||||
|
||||
private void Save(object sender, RoutedEventArgs e)
|
||||
=> _applicationView.ModelViewer.SaveLoadedModels();
|
||||
private async void Save(object sender, RoutedEventArgs e)
|
||||
=> await _applicationView.ModelViewer.SaveLoadedModels();
|
||||
|
||||
private void OnChangeMaterialClick(object sender, RoutedEventArgs e)
|
||||
private void OnOverwriteMaterialClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_applicationView.CUE4Parse.ModelIsSwappingMaterial = true;
|
||||
|
||||
_applicationView.CUE4Parse.ModelIsOverwritingMaterial = true;
|
||||
if (!_messageShown)
|
||||
{
|
||||
MessageBox.Show(new MessageBoxModel
|
||||
{
|
||||
Text = "Simply extract a material once FModel will be brought to the foreground. This message will be shown once per Model Viewer's lifetime, close it to begin.",
|
||||
Caption = "How To Change Material?",
|
||||
Caption = "How To Overwrite Material?",
|
||||
Icon = MessageBoxImage.Information,
|
||||
IsSoundEnabled = false
|
||||
});
|
||||
|
|
|
|||
|
|
@ -32,13 +32,7 @@ namespace FModel.Views.Resources.Controls
|
|||
return base.CreateTextRun(startVisualColumn, context);
|
||||
}
|
||||
|
||||
private bool GamePathIsClickable()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_gamePath))
|
||||
return false;
|
||||
|
||||
return (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
|
||||
}
|
||||
private bool GamePathIsClickable() => !string.IsNullOrEmpty(_gamePath) && Keyboard.Modifiers == ModifierKeys.None;
|
||||
|
||||
protected override void OnQueryCursor(QueryCursorEventArgs e)
|
||||
{
|
||||
|
|
@ -49,7 +43,7 @@ namespace FModel.Views.Resources.Controls
|
|||
|
||||
protected override void OnMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ChangedButton != MouseButton.Right && (e.ChangedButton != MouseButton.Left || !GamePathIsClickable()))
|
||||
if (e.ChangedButton != MouseButton.Left || !GamePathIsClickable())
|
||||
return;
|
||||
if (e.Handled || OnGamePathClicked == null)
|
||||
return;
|
||||
|
|
@ -82,4 +76,4 @@ namespace FModel.Views.Resources.Controls
|
|||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@
|
|||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
|
||||
<avalonEdit:TextEditor x:Name="MyAvalonEditor" Grid.Row="0" Grid.RowSpan="2" SyntaxHighlighting="{Binding Highlighter}" Document="{Binding Document}"
|
||||
FontFamily="Consolas" FontSize="{Binding FontSize}" IsReadOnly="True" ShowLineNumbers="True" Foreground="#DAE5F2"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer3BackgroundBrush}}" PreviewMouseWheel="OnPreviewMouseWheel"
|
||||
|
|
|
|||
|
|
@ -27,13 +27,9 @@ namespace FModel.Views.Resources.Controls
|
|||
private readonly Dictionary<string, NavigationList<int>> _savedCarets = new();
|
||||
private NavigationList<int> _caretsOffsets
|
||||
{
|
||||
get
|
||||
{
|
||||
if (MyAvalonEditor.Document != null)
|
||||
return _savedCarets.GetOrAdd(MyAvalonEditor.Document.FileName, () => new NavigationList<int>());
|
||||
else
|
||||
return new NavigationList<int>();
|
||||
}
|
||||
get => MyAvalonEditor.Document != null
|
||||
? _savedCarets.GetOrAdd(MyAvalonEditor.Document.FileName, () => new NavigationList<int>())
|
||||
: new NavigationList<int>();
|
||||
}
|
||||
private bool _ignoreCaret = true;
|
||||
|
||||
|
|
@ -223,8 +219,9 @@ namespace FModel.Views.Resources.Controls
|
|||
|
||||
private void OnTabClose(object sender, EventArgs eventArgs)
|
||||
{
|
||||
if (sender is not TabControlViewModel tab|| eventArgs is not TabControlViewModel.TabEventArgs e)
|
||||
if (eventArgs is not TabControlViewModel.TabEventArgs e || e.TabToRemove.Document == null)
|
||||
return;
|
||||
|
||||
var fileName = e.TabToRemove.Document.FileName;
|
||||
if (_savedCarets.ContainsKey(fileName))
|
||||
_savedCarets.Remove(fileName);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace FModel.Views.Resources.Converters
|
|||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value != null ? $"{value.ToString()?.ToUpper()} ASSETS" : null;
|
||||
return value != null ? $"{value.ToString()?.ToUpper()} PACKAGES" : null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
|
|
@ -18,4 +18,4 @@ namespace FModel.Views.Resources.Converters
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace FModel.Views.Resources.Converters
|
|||
"MinecraftDungeons" => "Minecraft Dungeons",
|
||||
"shoebill" => "Star Wars: Jedi Fallen Order",
|
||||
"a99769d95d8f400baad1f67ab5dfe508" => "Core",
|
||||
381210 => "Dead By Daylight",
|
||||
578080 => "PLAYERUNKNOWN'S BATTLEGROUNDS",
|
||||
677620 => "Splitgate",
|
||||
_ => value,
|
||||
|
|
|
|||
28
FModel/Views/Resources/Converters/TagToColorConverter.cs
Normal file
28
FModel/Views/Resources/Converters/TagToColorConverter.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using HelixToolkit.Wpf.SharpDX;
|
||||
|
||||
namespace FModel.Views.Resources.Converters
|
||||
{
|
||||
public class TagToColorConverter : IValueConverter
|
||||
{
|
||||
public static readonly TagToColorConverter Instance = new();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is not PBRMaterial material)
|
||||
return new SolidColorBrush(Colors.Red);
|
||||
|
||||
return new SolidColorBrush(Color.FromScRgb(
|
||||
material.AlbedoColor.Alpha, material.AlbedoColor.Red,
|
||||
material.AlbedoColor.Green, material.AlbedoColor.Blue));
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
<Geometry x:Key="NotVisibleIcon">M12 6.5c2.76 0 5 2.24 5 5 0 .51-.1 1-.24 1.46l3.06 3.06c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 0-2.49.2-3.64.57l2.17 2.17c.47-.14.96-.24 1.47-.24zM2.71 3.16c-.39.39-.39 1.02 0 1.41l1.97 1.97C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.97-.3 4.31-.82l2.72 2.72c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L4.13 3.16c-.39-.39-1.03-.39-1.42 0zM12 16.5c-2.76 0-5-2.24-5-5 0-.77.18-1.5.49-2.14l1.57 1.57c-.03.18-.06.37-.06.57 0 1.66 1.34 3 3 3 .2 0 .38-.03.57-.07L14.14 16c-.65.32-1.37.5-2.14.5zm2.97-5.33c-.15-1.4-1.25-2.49-2.64-2.64l2.64 2.64z</Geometry>
|
||||
<Geometry x:Key="WireframeIcon">M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM8 17h8c.55 0 1-.45 1-1V8c0-.55-.45-1-1-1H8c-.55 0-1 .45-1 1v8c0 .55.45 1 1 1zm1-8h6v6H9V9z</Geometry>
|
||||
<Geometry x:Key="NotWireframeIcon">M3,13h2v-2H3V13z M7,21h2v-2H7V21z M13,3h-2v2h2V3z M19,3v2h2C21,3.9,20.1,3,19,3z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,17h2 v-2H3V17z M11,21h2v-2h-2V21z M19,13h2v-2h-2V13z M19,9h2V7h-2V9z M15,5h2V3h-2V5z M7.83,5L7,4.17V3h2v2H7.83z M19.83,17L19,16.17 V15h2v2H19.83z M9,15v-3.17L12.17,15H9z M2.1,3.51c-0.39,0.39-0.39,1.02,0,1.41L4.17,7H3v2h2V7.83l2,2V16c0,0.55,0.45,1,1,1h6.17 l2,2H15v2h2v-1.17l2.07,2.07c0.39,0.39,1.02,0.39,1.41,0c0.39-0.39,0.39-1.02,0-1.41L3.51,3.51C3.12,3.12,2.49,3.12,2.1,3.51z M17,8c0-0.55-0.45-1-1-1H9.83l2,2H15v3.17l2,2V8z</Geometry>
|
||||
<Geometry x:Key="SwapIcon">M16 17.01V11c0-.55-.45-1-1-1s-1 .45-1 1v6.01h-1.79c-.45 0-.67.54-.35.85l2.79 2.78c.2.19.51.19.71 0l2.79-2.78c.32-.31.09-.85-.35-.85H16zM8.65 3.35L5.86 6.14c-.32.31-.1.85.35.85H8V13c0 .55.45 1 1 1s1-.45 1-1V6.99h1.79c.45 0 .67-.54.35-.85L9.35 3.35c-.19-.19-.51-.19-.7 0z</Geometry>
|
||||
<Geometry x:Key="OverwriteIcon">M16 17.01V11c0-.55-.45-1-1-1s-1 .45-1 1v6.01h-1.79c-.45 0-.67.54-.35.85l2.79 2.78c.2.19.51.19.71 0l2.79-2.78c.32-.31.09-.85-.35-.85H16zM8.65 3.35L5.86 6.14c-.32.31-.1.85.35.85H8V13c0 .55.45 1 1 1s1-.45 1-1V6.99h1.79c.45 0 .67-.54.35-.85L9.35 3.35c-.19-.19-.51-.19-.7 0z</Geometry>
|
||||
|
||||
<Style x:Key="TabItemFillSpace" TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
|
||||
<Setter Property="Width">
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<TextBlock Text="No files found in given directory yet" FontWeight="SemiBold" TextAlignment="Center"
|
||||
<TextBlock Text="No archives found in given directory yet" FontWeight="SemiBold" TextAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
|
@ -240,7 +240,7 @@
|
|||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<TextBlock Text="No audio to play yet" FontWeight="SemiBold" TextAlignment="Center"
|
||||
<TextBlock Text="No audio to play at the moment" FontWeight="SemiBold" TextAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
|
@ -273,7 +273,7 @@
|
|||
<ToolTip>
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0} has {1} folders and {2} files">
|
||||
<MultiBinding StringFormat="{}{0} has {1} folders and {2} packages">
|
||||
<Binding Path="Header" />
|
||||
<Binding Path="FoldersView.Count" />
|
||||
<Binding Path="AssetsList.Assets.Count" />
|
||||
|
|
@ -547,7 +547,7 @@
|
|||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<TextBlock Text="No folder found in packages, make sure you loaded one" FontWeight="SemiBold" TextAlignment="Center"
|
||||
<TextBlock Text="No folder found in archives, make sure you loaded at least one" FontWeight="SemiBold" TextAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
|
@ -608,7 +608,7 @@
|
|||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<TextBlock Text="No asset found in folder" FontWeight="SemiBold" TextAlignment="Center"
|
||||
<TextBlock Text="No package found in folder" FontWeight="SemiBold" TextAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
|
@ -618,6 +618,25 @@
|
|||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ModelsComboBox" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding ModelViewer.LoadedModelsView, IsAsync=True}" />
|
||||
<Setter Property="SelectedItem" Value="{Binding ModelViewer.SelectedModel, Mode=TwoWay}" />
|
||||
<Setter Property="ItemTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Export.Name}" />
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="{x:Type ComboBoxItem}" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
|
||||
<Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MaterialsListBox" TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding ModelViewer.SelectedModel.Group3d, IsAsync=True}" />
|
||||
<Setter Property="SelectedItem" Value="{Binding ModelViewer.SelectedModel.SelectedGeometry}" />
|
||||
|
|
@ -634,10 +653,11 @@
|
|||
<ColumnDefinition Width="25" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image Grid.Column="0" Source="/FModel;component/Resources/materialicon.png" Width="16" Height="16" Margin="5 0" HorizontalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Name}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding DisplayName}" TextTrimming="CharacterEllipsis" />
|
||||
<ToggleButton Grid.Column="3" IsChecked="{Binding IsRendering}" Padding="3" Style="{DynamicResource {x:Static adonisUi:Styles.ToolbarToggleButton}}">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -652,6 +672,10 @@
|
|||
</Canvas>
|
||||
</Viewbox>
|
||||
</ToggleButton>
|
||||
<Rectangle Grid.Column="5" Width="19" Height="22" Fill="{Binding Material, Converter={x:Static converters:TagToColorConverter.Instance}}"
|
||||
Visibility="{Binding DataContext.ModelViewer.SelectedModel.ShowMaterialColor,
|
||||
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:Views.ModelViewer}},
|
||||
Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding IsRendering}" Value="True">
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<Grid Grid.Row="0" Margin="0 0 0 5" ZIndex="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<Grid Grid.Column="0" ZIndex="1" HorizontalAlignment="Left" Margin="5 2 0 0">
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -80,10 +80,10 @@
|
|||
</Viewbox>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CUE4Parse.SearchVm.ResultsCount, FallbackValue=0, StringFormat={}{0:### ### ###} Loaded Assets}"
|
||||
<TextBlock Grid.Column="2" Text="{Binding CUE4Parse.SearchVm.ResultsCount, FallbackValue=0, StringFormat={}{0:### ### ###} Loaded Packages}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Right" FontStyle="Italic"/>
|
||||
</Grid>
|
||||
|
||||
|
||||
<ListView Grid.Row="1" x:Name="SearchListView" VirtualizingPanel.IsVirtualizing="True" ItemsSource="{Binding CUE4Parse.SearchVm.SearchResultsView, IsAsync=True}">
|
||||
<ListView.Resources>
|
||||
<Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListViewItem}}">
|
||||
|
|
@ -124,7 +124,7 @@
|
|||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<TextBlock Text="No folder found in packages, make sure you loaded one" FontWeight="SemiBold" TextAlignment="Center"
|
||||
<TextBlock Text="No folder found in archives, make sure you loaded at least one" FontWeight="SemiBold" TextAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}" Margin="0 10 0 0" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
|
@ -154,7 +154,7 @@
|
|||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="File Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Path" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path" />
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Name" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Name" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name" />
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Path w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Path w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Path_No_Extension" />
|
||||
|
|
@ -186,7 +186,7 @@
|
|||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
</MenuItem>
|
||||
<MenuItem Header="File Name w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem Header="Package Name w/o Extension" Command="{Binding DataContext.CopyCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="File_Name_No_Extension" />
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
|
@ -65,7 +66,7 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Assets Language" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Language used and shown when parsing assets" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Packages Language" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Language used and shown when parsing packages" />
|
||||
<ComboBox Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.AssetLanguages}" SelectedItem="{Binding SettingsView.SelectedAssetLanguage, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
|
|
@ -75,9 +76,9 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Discord Rich Presence" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Discord Rich Presence" VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.DiscordRpcs}" SelectedItem="{Binding SettingsView.SelectedDiscordRpc, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
|
|
@ -92,7 +93,7 @@
|
|||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" SelectionChanged="OnSelectionChanged" Margin="0 0 0 5">
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" Text="UE4 Versions *" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Override the UE4 version to use when parsing assets" />
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" Text="UE Versions *" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Override the UE version to use when parsing packages" />
|
||||
<ComboBox Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.UeGames}" SelectedItem="{Binding SettingsView.SelectedUeGame, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" IsEnabled="{Binding SettingsView.EnableElements}"
|
||||
Margin="0 0 0 5">
|
||||
|
|
@ -103,19 +104,8 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="UE4 Object Versions *" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Override the UE4 object version to use when parsing assets" />
|
||||
<ComboBox Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.UeVersions}" SelectedItem="{Binding SettingsView.SelectedUeVersion, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" IsEnabled="{Binding SettingsView.EnableElements}"
|
||||
Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Versioning Configuration *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<Grid Grid.Row="9" Grid.Column="2" Grid.ColumnSpan="3" Margin="0 0 0 5">
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Versioning Configuration *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<Grid Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="3" Margin="0 0 0 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="5" />
|
||||
|
|
@ -126,13 +116,8 @@
|
|||
<Button Grid.Column="2" Content="Options" Click="OpenOptions" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="Keep Directory Structure" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Auto Export & Save assets inside their game directory" />
|
||||
<CheckBox Grid.Row="10" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding KeepDirectoryStructure, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" Margin="0 5 0 10"/>
|
||||
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" Text="Compressed Audio" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="What to do when encountering a compressed audio file" />
|
||||
<ComboBox Grid.Row="11" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.CompressedAudios}" SelectedItem="{Binding SettingsView.SelectedCompressedAudio, Mode=TwoWay}"
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Compressed Audio" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="What to do when encountering a compressed audio file" />
|
||||
<ComboBox Grid.Row="9" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.CompressedAudios}" SelectedItem="{Binding SettingsView.SelectedCompressedAudio, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
|
@ -141,7 +126,7 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="AES Reload at Launch" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="AES Reload at Launch" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
||||
|
|
@ -154,7 +139,7 @@
|
|||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<ComboBox Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.AesReloads}" SelectedItem="{Binding SettingsView.SelectedAesReload, Mode=TwoWay}"
|
||||
<ComboBox Grid.Row="10" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.AesReloads}" SelectedItem="{Binding SettingsView.SelectedAesReload, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.Style>
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
|
|
@ -172,6 +157,45 @@
|
|||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" Text="Keep Directory Structure" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Auto-save packages following their game directory" />
|
||||
<CheckBox Grid.Row="11" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding KeepDirectoryStructure, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"/>
|
||||
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="Overwrite Mapping File" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CUE4Parse.Game}" Value="{x:Static local:FGame.FortniteGame}">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<CheckBox Grid.Row="12" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding OverwriteMapping, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" Margin="0 5 0 10"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}">
|
||||
<CheckBox.Style>
|
||||
<Style TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding CUE4Parse.Game}" Value="{x:Static local:FGame.FortniteGame}">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</CheckBox.Style>
|
||||
</CheckBox>
|
||||
|
||||
<TextBlock Grid.Row="13" Grid.Column="0" Text="Mapping File Path" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
Visibility="{Binding OverwriteMapping, Source={x:Static local:Settings.UserSettings.Default}, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBox Grid.Row="13" Grid.Column="2" Text="{Binding MappingFilePath, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0 0 0 5"
|
||||
Visibility="{Binding OverwriteMapping, Source={x:Static local:Settings.UserSettings.Default}, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<Button Grid.Row="13" Grid.Column="4" Content="..." HorizontalAlignment="Right" Click="OnBrowseMappings" Margin="0 0 0 5"
|
||||
Visibility="{Binding OverwriteMapping, Source={x:Static local:Settings.UserSettings.Default}, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="CreatorTemplate">
|
||||
|
|
@ -251,17 +275,22 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Mesh Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="0" Grid.Column="2" ItemsSource="{Binding SettingsView.MeshExportFormats}" SelectedItem="{Binding SettingsView.SelectedMeshExportFormat, Mode=TwoWay}"
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Model Export Directory *" VerticalAlignment="Center" Margin="0 0 0 5"
|
||||
ToolTip="This will be the directory where Meshes, Materials and Animations will be exported" />
|
||||
<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding ModelDirectory, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0 0 0 5" />
|
||||
<Button Grid.Row="0" Grid.Column="4" Content="..." HorizontalAlignment="Right" Click="OnBrowseModels" Margin="0 0 0 5" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Mesh Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.MeshExportFormats}" SelectedItem="{Binding SettingsView.SelectedMeshExportFormat, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
|
@ -270,8 +299,8 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Level Of Detail Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="2" ItemsSource="{Binding SettingsView.LodExportFormats}" SelectedItem="{Binding SettingsView.SelectedLodExportFormat, Mode=TwoWay}"
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Level Of Detail Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.LodExportFormats}" SelectedItem="{Binding SettingsView.SelectedLodExportFormat, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
|
@ -280,15 +309,40 @@
|
|||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Save Skeletons as Empty Meshes" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<CheckBox Grid.Row="2" Grid.Column="2" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Preview in Model Viewer" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<UniformGrid Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" Rows="1" Columns="3" Margin="0 5 0 10">
|
||||
<CheckBox Content="Static Meshes" HorizontalAlignment="Left"
|
||||
IsChecked="{Binding PreviewStaticMeshes, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
<CheckBox Content="Skeletal Meshes" HorizontalAlignment="Center"
|
||||
IsChecked="{Binding PreviewSkeletalMeshes, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
<CheckBox Content="Materials" HorizontalAlignment="Right"
|
||||
IsChecked="{Binding PreviewMaterials, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
</UniformGrid>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Auto-Export without Previewing" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<UniformGrid Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" Rows="1" Columns="3" Margin="0 5 0 10">
|
||||
<CheckBox Content="Static Meshes" HorizontalAlignment="Left"
|
||||
IsChecked="{Binding SaveStaticMeshes, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<CheckBox Content="Skeletal Meshes" HorizontalAlignment="Center"
|
||||
IsChecked="{Binding SaveSkeletalMeshes, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
<CheckBox Content="Materials" HorizontalAlignment="Right"
|
||||
IsChecked="{Binding SaveMaterials, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"/>
|
||||
</UniformGrid>
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="Auto-Export Animations" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<CheckBox Grid.Row="5" Grid.Column="2" Grid.ColumnSpan="3" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding SaveAnimations, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" Margin="0 5 0 5"/>
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="Export Skeletons as Empty Meshes" VerticalAlignment="Center" />
|
||||
<CheckBox Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="3" Content="{Binding IsChecked, RelativeSource={RelativeSource Self}, Converter={x:Static converters:BoolToToggleConverter.Instance}}"
|
||||
IsChecked="{Binding SaveSkeletonAsMesh, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" Margin="0 5 0 10"/>
|
||||
Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" Margin="0 5 0 0"/>
|
||||
|
||||
<Separator Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
<Separator Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="5" Style="{StaticResource CustomSeparator}" />
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Texture Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="4" Grid.Column="2" ItemsSource="{Binding SettingsView.TextureExportFormats}" SelectedItem="{Binding SettingsView.SelectedTextureExportFormat, Mode=TwoWay}"
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Texture Format" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="8" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.TextureExportFormats}" SelectedItem="{Binding SettingsView.SelectedTextureExportFormat, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
|
@ -317,9 +371,6 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
|
@ -351,38 +402,29 @@
|
|||
|
||||
<Separator Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Auto Export Data *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Auto Save Properties *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="8" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding AutoExportData, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Auto Save Properties *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="9" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding AutoSaveProps, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="Auto Save Textures *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="10" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Auto Save Textures *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="9" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding AutoSaveTextures, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" Text="Auto Save Animations *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="11" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding AutoSaveAnimations, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="Auto Open Sounds *" VerticalAlignment="Center" />
|
||||
<controls:HotkeyTextBox Grid.Row="12" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}"
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="Auto Open Sounds *" VerticalAlignment="Center" />
|
||||
<controls:HotkeyTextBox Grid.Row="10" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}"
|
||||
HotKey="{Binding AutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="13" Grid.Column="0" Text="Auto Open Meshes & Materials *" VerticalAlignment="Center" />
|
||||
<controls:HotkeyTextBox Grid.Row="13" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}"
|
||||
HotKey="{Binding AutoOpenMeshes, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
|
||||
<Separator Grid.Row="14" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
<Separator Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
|
||||
<TextBlock Grid.Row="15" Grid.Column="0" Text="Add Audio File" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="15" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="12" Grid.Column="0" Text="Add Audio File" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="12" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding AddAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="16" Grid.Column="0" Text="Play / Pause Current Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="16" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="13" Grid.Column="0" Text="Play / Pause Current Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="13" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding PlayPauseAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="17" Grid.Column="0" Text="Previous Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="17" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="14" Grid.Column="0" Text="Previous Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="14" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding PreviousAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Row="18" Grid.Column="0" Text="Next Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="18" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
<TextBlock Grid.Row="15" Grid.Column="0" Text="Next Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="15" Grid.Column="2" Style="{StaticResource TextBoxDefaultStyle}" Margin="0 0 0 5"
|
||||
HotKey="{Binding NextAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using Microsoft.Win32;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace FModel.Views
|
||||
|
|
@ -41,22 +43,44 @@ namespace FModel.Views
|
|||
|
||||
Close();
|
||||
|
||||
if (whatShouldIDo == SettingsOut.ReloadLocres)
|
||||
switch (whatShouldIDo)
|
||||
{
|
||||
_applicationView.CUE4Parse.LocalizedResourcesCount = 0;
|
||||
await _applicationView.CUE4Parse.LoadLocalizedResources();
|
||||
case SettingsOut.ReloadLocres:
|
||||
_applicationView.CUE4Parse.LocalizedResourcesCount = 0;
|
||||
await _applicationView.CUE4Parse.LoadLocalizedResources();
|
||||
break;
|
||||
case SettingsOut.CheckForUpdates:
|
||||
ApplicationService.ApiEndpointView.FModelApi.CheckForUpdates(UserSettings.Default.UpdateMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBrowseDirectories(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TryBrowse(out var path)) UserSettings.Default.GameDirectory = path;
|
||||
}
|
||||
|
||||
private void OnBrowseOutput(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TryBrowse(out var path)) UserSettings.Default.OutputDirectory = path;
|
||||
}
|
||||
private void OnBrowseDirectories(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TryBrowse(out var path)) UserSettings.Default.GameDirectory = path;
|
||||
}
|
||||
private void OnBrowseModels(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (TryBrowse(out var path)) UserSettings.Default.ModelDirectory = path;
|
||||
}
|
||||
private async void OnBrowseMappings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var openFileDialog = new OpenFileDialog
|
||||
{
|
||||
Title = "Select a mapping file",
|
||||
InitialDirectory = Path.Combine(UserSettings.Default.OutputDirectory, ".data"),
|
||||
Filter = "USMAP Files (*.usmap)|*.usmap|All Files (*.*)|*.*"
|
||||
};
|
||||
|
||||
if (!(bool) openFileDialog.ShowDialog()) return;
|
||||
|
||||
UserSettings.Default.MappingFilePath = openFileDialog.FileName;
|
||||
await _applicationView.CUE4Parse.InitBenMappings();
|
||||
}
|
||||
|
||||
private bool TryBrowse(out string path)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user