mirror of
https://github.com/4sval/FModel.git
synced 2026-06-22 07:50:10 -05:00
Merge remote-tracking branch 'Krowe/dev' into feature/new-exporter
# Conflicts: # CUE4Parse # FModel/Settings/UserSettings.cs # FModel/ViewModels/SettingsViewModel.cs # FModel/Views/Resources/Icons.xaml # FModel/Views/Snooper/Models/SkeletalModel.cs
This commit is contained in:
commit
ba4913c971
|
|
@ -1 +1 @@
|
|||
Subproject commit 3b2a686787bb08c28940271709897957b759a6f4
|
||||
Subproject commit 22dbf59c942fbc8d544fc2ee51bb96577fae247b
|
||||
|
|
@ -1,11 +1,19 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml;
|
||||
using FModel.Extensions.Themes;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
|
||||
|
||||
namespace FModel.Extensions;
|
||||
|
||||
public sealed record HighlightColor
|
||||
(
|
||||
string Foreground,
|
||||
bool Bold = false,
|
||||
bool Italic = false
|
||||
);
|
||||
|
||||
public static class AvalonExtensions
|
||||
{
|
||||
private static readonly IHighlightingDefinition _jsonHighlighter = LoadHighlighter("Json.xshd");
|
||||
|
|
@ -53,6 +61,7 @@ public static class AvalonExtensions
|
|||
case "po":
|
||||
return null;
|
||||
default:
|
||||
_jsonHighlighter.ApplyJsonTheme(Settings.UserSettings.Default.JsonHighlightTheme);
|
||||
return _jsonHighlighter;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
FModel/Extensions/Themes/HighlightingThemeExtensions.cs
Normal file
34
FModel/Extensions/Themes/HighlightingThemeExtensions.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
using static FModel.Extensions.AvalonExtensions;
|
||||
using static FModel.Extensions.Themes.JsonHighlightThemes;
|
||||
|
||||
namespace FModel.Extensions.Themes;
|
||||
|
||||
public static class HighlightingThemeExtensions
|
||||
{
|
||||
public static void ApplyJsonTheme(this IHighlightingDefinition highlighter, EJsonHighlightTheme theme)
|
||||
{
|
||||
var palette = Get(theme);
|
||||
|
||||
Apply(highlighter, "FieldName", palette.FieldName);
|
||||
Apply(highlighter, "String", palette.String);
|
||||
Apply(highlighter, "Number", palette.Number);
|
||||
Apply(highlighter, "Bool", palette.Bool);
|
||||
Apply(highlighter, "Null", palette.Null);
|
||||
Apply(highlighter, "Punctuation", palette.Punctuation);
|
||||
Apply(highlighter, "Escape", palette.Escape);
|
||||
}
|
||||
|
||||
private static void Apply(IHighlightingDefinition highlighter, string name, HighlightColor color)
|
||||
{
|
||||
var namedColor = highlighter.GetNamedColor(name);
|
||||
if (namedColor is null)
|
||||
return;
|
||||
|
||||
namedColor.Foreground = new SimpleHighlightingBrush((Color) ColorConverter.ConvertFromString(color.Foreground));
|
||||
namedColor.FontWeight = color.Bold ? FontWeights.Bold : null;
|
||||
namedColor.FontStyle = color.Italic ? FontStyles.Italic : null;
|
||||
}
|
||||
}
|
||||
203
FModel/Extensions/Themes/JsonHighlightThemes.cs
Normal file
203
FModel/Extensions/Themes/JsonHighlightThemes.cs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
using System.ComponentModel;
|
||||
|
||||
namespace FModel.Extensions.Themes;
|
||||
|
||||
public enum EJsonHighlightTheme
|
||||
{
|
||||
[Description("Default")]
|
||||
Default,
|
||||
[Description("Mint Lavender")]
|
||||
MintLavender,
|
||||
[Description("Soft Blue")]
|
||||
SoftBlueGreen,
|
||||
[Description("Purple Cyan")]
|
||||
PurpleCyan,
|
||||
[Description("Neutral Warm")]
|
||||
NeutralWarm,
|
||||
[Description("Nord")]
|
||||
Nord,
|
||||
[Description("Mocha")]
|
||||
Mocha,
|
||||
[Description("Tokyo Night")]
|
||||
TokyoNight,
|
||||
[Description("One Dark")]
|
||||
OneDark,
|
||||
[Description("Gruvbox Dark")]
|
||||
GruvboxDark,
|
||||
[Description("Rosé Pine")]
|
||||
RosePine,
|
||||
[Description("Monokai")]
|
||||
Monokai,
|
||||
[Description("Oceanic")]
|
||||
Oceanic,
|
||||
[Description("Forest")]
|
||||
Forest,
|
||||
[Description("Amber")]
|
||||
Amber,
|
||||
[Description("Iceberg")]
|
||||
Iceberg
|
||||
}
|
||||
|
||||
public static class JsonHighlightThemes
|
||||
{
|
||||
public sealed record JsonHighlightPalette(
|
||||
HighlightColor FieldName,
|
||||
HighlightColor String,
|
||||
HighlightColor Number,
|
||||
HighlightColor Bool,
|
||||
HighlightColor Null,
|
||||
HighlightColor Punctuation,
|
||||
HighlightColor Escape
|
||||
);
|
||||
|
||||
public static JsonHighlightPalette Get(EJsonHighlightTheme theme) => theme switch
|
||||
{
|
||||
EJsonHighlightTheme.MintLavender => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#CBA6F7"),
|
||||
String: new HighlightColor("#8FE3CF"),
|
||||
Number: new HighlightColor("#FFD166"),
|
||||
Bool: new HighlightColor("#FF9CAC", Bold: true),
|
||||
Null: new HighlightColor("#A7B0C0", Italic: true),
|
||||
Punctuation: new HighlightColor("#D7DEE9"),
|
||||
Escape: new HighlightColor("#5DD9C1", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.SoftBlueGreen => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#7CC7FF"),
|
||||
String: new HighlightColor("#A6E3A1"),
|
||||
Number: new HighlightColor("#FFA36C"),
|
||||
Bool: new HighlightColor("#FF6B8A", Bold: true),
|
||||
Null: new HighlightColor("#8FA3BF", Italic: true),
|
||||
Punctuation: new HighlightColor("#C7D0DD"),
|
||||
Escape: new HighlightColor("#66E3D4", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.PurpleCyan => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#BD93F9"),
|
||||
String: new HighlightColor("#7EE7F2"),
|
||||
Number: new HighlightColor("#FFB86C"),
|
||||
Bool: new HighlightColor("#FF6B8B", Bold: true),
|
||||
Null: new HighlightColor("#9AA7B8", Italic: true),
|
||||
Punctuation: new HighlightColor("#CBD5E1"),
|
||||
Escape: new HighlightColor("#5DE4C7", Bold: true)
|
||||
),
|
||||
|
||||
EJsonHighlightTheme.NeutralWarm => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#F8C291"),
|
||||
String: new HighlightColor("#A3E635"),
|
||||
Number: new HighlightColor("#FB923C"),
|
||||
Bool: new HighlightColor("#F87171", Bold: true),
|
||||
Null: new HighlightColor("#9CA3AF", Italic: true),
|
||||
Punctuation: new HighlightColor("#D1D5DB"),
|
||||
Escape: new HighlightColor("#67E8F9", Bold: true)
|
||||
),
|
||||
|
||||
EJsonHighlightTheme.Nord => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#88C0D0"),
|
||||
String: new HighlightColor("#A3BE8C"),
|
||||
Number: new HighlightColor("#D08770"),
|
||||
Bool: new HighlightColor("#BF616A", Bold: true),
|
||||
Null: new HighlightColor("#81A1C1", Italic: true),
|
||||
Punctuation: new HighlightColor("#D8DEE9"),
|
||||
Escape: new HighlightColor("#8FBCBB", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Default => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#FFCB6B"),
|
||||
String: new HighlightColor("#C3E88D"),
|
||||
Number: new HighlightColor("#F78C6C"),
|
||||
Bool: new HighlightColor("#61AFEF", Bold: true),
|
||||
Null: new HighlightColor("#7F848E", Italic: true),
|
||||
Punctuation: new HighlightColor("#89DDFF"),
|
||||
Escape: new HighlightColor("#4DD0E1", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Mocha => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#CBA6F7"),
|
||||
String: new HighlightColor("#A6E3A1"),
|
||||
Number: new HighlightColor("#FAB387"),
|
||||
Bool: new HighlightColor("#F38BA8", Bold: true),
|
||||
Null: new HighlightColor("#9399B2", Italic: true),
|
||||
Punctuation: new HighlightColor("#CDD6F4"),
|
||||
Escape: new HighlightColor("#94E2D5", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.TokyoNight => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#7AA2F7"),
|
||||
String: new HighlightColor("#9ECE6A"),
|
||||
Number: new HighlightColor("#FF9E64"),
|
||||
Bool: new HighlightColor("#F7768E", Bold: true),
|
||||
Null: new HighlightColor("#565F89", Italic: true),
|
||||
Punctuation: new HighlightColor("#A9B1D6"),
|
||||
Escape: new HighlightColor("#7DCFFF", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.OneDark => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#E5C07B"),
|
||||
String: new HighlightColor("#98C379"),
|
||||
Number: new HighlightColor("#D19A66"),
|
||||
Bool: new HighlightColor("#61AFEF", Bold: true),
|
||||
Null: new HighlightColor("#5C6370", Italic: true),
|
||||
Punctuation: new HighlightColor("#ABB2BF"),
|
||||
Escape: new HighlightColor("#56B6C2", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.GruvboxDark => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#FABD2F"),
|
||||
String: new HighlightColor("#B8BB26"),
|
||||
Number: new HighlightColor("#FE8019"),
|
||||
Bool: new HighlightColor("#FB4934", Bold: true),
|
||||
Null: new HighlightColor("#928374", Italic: true),
|
||||
Punctuation: new HighlightColor("#EBDBB2"),
|
||||
Escape: new HighlightColor("#8EC07C", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.RosePine => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#C4A7E7"),
|
||||
String: new HighlightColor("#9CCFD8"),
|
||||
Number: new HighlightColor("#F6C177"),
|
||||
Bool: new HighlightColor("#EB6F92", Bold: true),
|
||||
Null: new HighlightColor("#6E6A86", Italic: true),
|
||||
Punctuation: new HighlightColor("#E0DEF4"),
|
||||
Escape: new HighlightColor("#31748F", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Monokai => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#A6E22E"),
|
||||
String: new HighlightColor("#E6DB74"),
|
||||
Number: new HighlightColor("#AE81FF"),
|
||||
Bool: new HighlightColor("#F92672", Bold: true),
|
||||
Null: new HighlightColor("#75715E", Italic: true),
|
||||
Punctuation: new HighlightColor("#F8F8F2"),
|
||||
Escape: new HighlightColor("#66D9EF", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Oceanic => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#5FB3B3"),
|
||||
String: new HighlightColor("#99C794"),
|
||||
Number: new HighlightColor("#F99157"),
|
||||
Bool: new HighlightColor("#EC5F67", Bold: true),
|
||||
Null: new HighlightColor("#65737E", Italic: true),
|
||||
Punctuation: new HighlightColor("#D8DEE9"),
|
||||
Escape: new HighlightColor("#6699CC", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Forest => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#86EFAC"),
|
||||
String: new HighlightColor("#B4D455"),
|
||||
Number: new HighlightColor("#FACC15"),
|
||||
Bool: new HighlightColor("#FB7185", Bold: true),
|
||||
Null: new HighlightColor("#6B7280", Italic: true),
|
||||
Punctuation: new HighlightColor("#D1FAE5"),
|
||||
Escape: new HighlightColor("#34D399", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Amber => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#FBBF24"),
|
||||
String: new HighlightColor("#D9F99D"),
|
||||
Number: new HighlightColor("#FDBA74"),
|
||||
Bool: new HighlightColor("#F87171", Bold: true),
|
||||
Null: new HighlightColor("#A8A29E", Italic: true),
|
||||
Punctuation: new HighlightColor("#FDE68A"),
|
||||
Escape: new HighlightColor("#67E8F9", Bold: true)
|
||||
),
|
||||
EJsonHighlightTheme.Iceberg => new JsonHighlightPalette(
|
||||
FieldName: new HighlightColor("#84A0C6"),
|
||||
String: new HighlightColor("#B4BE82"),
|
||||
Number: new HighlightColor("#E2A478"),
|
||||
Bool: new HighlightColor("#E27878", Bold: true),
|
||||
Null: new HighlightColor("#6B7089", Italic: true),
|
||||
Punctuation: new HighlightColor("#D2D4DE"),
|
||||
Escape: new HighlightColor("#89B8C2", Bold: true)
|
||||
),
|
||||
_ => Get(EJsonHighlightTheme.Default)
|
||||
};
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ using CUE4Parse.UE4.Versions;
|
|||
using CUE4Parse_Conversion.Options;
|
||||
using CUE4Parse_Conversion.Writers.UEFormat.Enums;
|
||||
using CUE4Parse.UE4.Lua.unluac;
|
||||
using FModel.Extensions.Themes;
|
||||
using FModel.Framework;
|
||||
using FModel.ViewModels;
|
||||
using FModel.ViewModels.ApiEndpoints.Models;
|
||||
|
|
@ -304,6 +305,13 @@ namespace FModel.Settings
|
|||
}
|
||||
}
|
||||
|
||||
private EJsonHighlightTheme _jsonHighlightTheme;
|
||||
public EJsonHighlightTheme JsonHighlightTheme
|
||||
{
|
||||
get => _jsonHighlightTheme;
|
||||
set => SetProperty(ref _jsonHighlightTheme, value);
|
||||
}
|
||||
|
||||
private IDictionary<string, DirectorySettings> _perDirectory = new Dictionary<string, DirectorySettings>();
|
||||
public IDictionary<string, DirectorySettings> PerDirectory
|
||||
{
|
||||
|
|
|
|||
|
|
@ -218,6 +218,17 @@ public class AssetsFolderViewModel
|
|||
var treeItems = new RangeObservableCollection<TreeItem>();
|
||||
treeItems.SetSuppressionState(true);
|
||||
|
||||
static TreeItem FindByHeaderOrNull(IReadOnlyList<TreeItem> list, string header)
|
||||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].Header == header)
|
||||
return list[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
TreeItem lastNode = null;
|
||||
|
|
@ -226,23 +237,31 @@ public class AssetsFolderViewModel
|
|||
var builder = new StringBuilder(64);
|
||||
var parentNode = treeItems;
|
||||
|
||||
if (folders.Length <= 1)
|
||||
{
|
||||
var rootNode = FindByHeaderOrNull(treeItems, "Content");
|
||||
if (rootNode == null)
|
||||
{
|
||||
rootNode = new TreeItem("Content", entry, "Content")
|
||||
{
|
||||
Parent = null
|
||||
};
|
||||
|
||||
rootNode.Folders.SetSuppressionState(true);
|
||||
rootNode.AssetsList.Assets.SetSuppressionState(true);
|
||||
treeItems.Add(rootNode);
|
||||
}
|
||||
|
||||
rootNode.AssetsList.Add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < folders.Length - 1; i++)
|
||||
{
|
||||
var folder = folders[i];
|
||||
builder.Append(folder).Append('/');
|
||||
lastNode = FindByHeaderOrNull(parentNode, folder);
|
||||
|
||||
static TreeItem FindByHeaderOrNull(IReadOnlyList<TreeItem> list, string header)
|
||||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (list[i].Header == header)
|
||||
return list[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lastNode == null)
|
||||
{
|
||||
var nodePath = builder.ToString();
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
Provider.ReadScriptData = UserSettings.Default.ReadScriptData;
|
||||
Provider.ReadShaderMaps = UserSettings.Default.ReadShaderMaps;
|
||||
Provider.ReadNaniteData = true;
|
||||
PropertyUtil.SearchPropertyInTemplate = true; // search template properties when looking for a prop via GetOrDefault and cie
|
||||
|
||||
GameDirectory = new GameDirectoryViewModel();
|
||||
AssetsFolder = new AssetsFolderViewModel();
|
||||
|
|
@ -335,6 +336,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
}
|
||||
|
||||
Provider.Initialize();
|
||||
GameDirectory.AddLooseFiles(Provider.LooseFileCount);
|
||||
_wwiseProviderLazy = new Lazy<WwiseProvider>(() => new WwiseProvider(Provider, UserSettings.Default.GameDirectory));
|
||||
_fmodProviderLazy = new Lazy<FModProvider>(() => new FModProvider(Provider, UserSettings.Default.GameDirectory));
|
||||
_criWareProviderLazy = new Lazy<CriWareProvider>(() => new CriWareProvider(Provider, UserSettings.Default.GameDirectory));
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
|
|||
private void FilterDirectoryFilesToDisplay(CancellationToken cancellationToken, IEnumerable<FileItem> directoryFiles)
|
||||
{
|
||||
HashSet<string> filter;
|
||||
var includeLooseFiles = false;
|
||||
if (directoryFiles == null) filter = null;
|
||||
else
|
||||
{
|
||||
|
|
@ -120,11 +121,17 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
|
|||
foreach (var directoryFile in directoryFiles)
|
||||
{
|
||||
if (!directoryFile.IsEnabled) continue;
|
||||
if (directoryFile.IsLooseFilesContainer)
|
||||
{
|
||||
includeLooseFiles = true;
|
||||
continue;
|
||||
}
|
||||
filter.Add(directoryFile.Name);
|
||||
}
|
||||
}
|
||||
|
||||
var hasFilter = filter != null && filter.Count != 0;
|
||||
var hasSelection = hasFilter || includeLooseFiles;
|
||||
var entries = new List<GameFile>();
|
||||
|
||||
foreach (var asset in _applicationView.CUE4Parse.Provider.Files.Values)
|
||||
|
|
@ -132,12 +139,16 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
|
|||
cancellationToken.ThrowIfCancellationRequested(); // cancel if needed
|
||||
if (asset.IsUePackagePayload) continue;
|
||||
|
||||
if (hasFilter)
|
||||
if (hasSelection)
|
||||
{
|
||||
if (asset is VfsEntry entry && filter.Contains(entry.Vfs.Name))
|
||||
{
|
||||
entries.Add(asset);
|
||||
}
|
||||
else if (includeLooseFiles && asset is OsGameFile)
|
||||
{
|
||||
entries.Add(asset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ public class FileItem : ViewModel
|
|||
set => SetProperty(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
private bool _isLooseFilesContainer;
|
||||
public bool IsLooseFilesContainer
|
||||
{
|
||||
get => _isLooseFilesContainer;
|
||||
set => SetProperty(ref _isLooseFilesContainer, value);
|
||||
}
|
||||
|
||||
private string _key;
|
||||
public string Key
|
||||
{
|
||||
|
|
@ -83,6 +90,18 @@ public class FileItem : ViewModel
|
|||
Length = length;
|
||||
}
|
||||
|
||||
public FileItem(string name, int fileCount, long length, bool isLooseFile)
|
||||
{
|
||||
Name = name;
|
||||
Length = length;
|
||||
FileCount = fileCount;
|
||||
IsLooseFilesContainer = isLooseFile;
|
||||
IsEnabled = true;
|
||||
Key = string.Empty;
|
||||
MountPoint = string.Empty;
|
||||
CompressionMethods = [];
|
||||
}
|
||||
|
||||
public FileItem(IAesVfsReader reader)
|
||||
{
|
||||
Name = reader.Name;
|
||||
|
|
@ -90,6 +109,7 @@ public class FileItem : ViewModel
|
|||
Guid = reader.EncryptionKeyGuid;
|
||||
IsEncrypted = reader.IsEncrypted;
|
||||
IsEnabled = false;
|
||||
IsLooseFilesContainer = false;
|
||||
Key = string.Empty;
|
||||
FileCount = reader is IoStoreReader storeReader ? (int) storeReader.TocResource.Header.TocEntryCount - 1 : 0;
|
||||
CompressionMethods = reader.CompressionMethods;
|
||||
|
|
@ -101,19 +121,25 @@ public class FileItem : ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
public class GameDirectoryViewModel : ViewModel
|
||||
public partial class GameDirectoryViewModel : ViewModel
|
||||
{
|
||||
public bool HasNoFile => DirectoryFiles.Count < 1;
|
||||
public readonly ObservableCollection<FileItem> DirectoryFiles;
|
||||
|
||||
public ICollectionView DirectoryFilesView { get; }
|
||||
|
||||
private readonly Regex _hiddenArchives = new(@"^(?!global|pakchunk.+(optional|ondemand)\-).+(pak|utoc)$", // should be universal
|
||||
RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
private readonly Regex _hiddenArchives = ArchivesRegex();
|
||||
|
||||
public GameDirectoryViewModel()
|
||||
{
|
||||
DirectoryFiles = new ObservableCollection<FileItem>();
|
||||
DirectoryFilesView = new ListCollectionView(DirectoryFiles) { SortDescriptions = { new SortDescription("Name", ListSortDirection.Ascending) } };
|
||||
DirectoryFiles = [];
|
||||
DirectoryFilesView = new ListCollectionView(DirectoryFiles)
|
||||
{
|
||||
SortDescriptions =
|
||||
{
|
||||
new SortDescription(nameof(FileItem.IsLooseFilesContainer), ListSortDirection.Ascending),
|
||||
new SortDescription(nameof(FileItem.Name), ListSortDirection.Ascending)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void Add(IAesVfsReader reader)
|
||||
|
|
@ -124,6 +150,25 @@ public class GameDirectoryViewModel : ViewModel
|
|||
Application.Current.Dispatcher.Invoke(() => DirectoryFiles.Add(fileItem));
|
||||
}
|
||||
|
||||
public void AddLooseFiles(int fileCount)
|
||||
{
|
||||
if (fileCount < 1)
|
||||
return;
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var looseFilesContainer = DirectoryFiles.FirstOrDefault(x => x.IsLooseFilesContainer);
|
||||
if (looseFilesContainer is not null)
|
||||
{
|
||||
looseFilesContainer.FileCount += fileCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
DirectoryFiles.Add(new FileItem("Loose Files", fileCount, 0, true));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Verify(IAesVfsReader reader)
|
||||
{
|
||||
if (DirectoryFiles.FirstOrDefault(x => x.Name == reader.Name) is not { } file) return;
|
||||
|
|
@ -138,4 +183,7 @@ public class GameDirectoryViewModel : ViewModel
|
|||
if (DirectoryFiles.FirstOrDefault(x => x.Name == reader.Name) is not { } file) return;
|
||||
file.IsEnabled = false;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"^(?!global|pakchunk.+(optional|ondemand)\-).+(pak|utoc)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.CultureInvariant)]
|
||||
private static partial Regex ArchivesRegex();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using CUE4Parse.UE4.Versions;
|
|||
using CUE4Parse_Conversion.Options;
|
||||
using CUE4Parse_Conversion.Writers.UEFormat.Enums;
|
||||
using CUE4Parse.UE4.Assets.Exports.Material;
|
||||
using FModel.Extensions.Themes;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
|
|
@ -102,6 +103,13 @@ public class SettingsViewModel : ViewModel
|
|||
set => SetProperty(ref _selectedCosmeticStyle, value);
|
||||
}
|
||||
|
||||
private EJsonHighlightTheme _selectedJsonHighlightTheme;
|
||||
public EJsonHighlightTheme SelectedJsonHighlightTheme
|
||||
{
|
||||
get => _selectedJsonHighlightTheme;
|
||||
set => SetProperty(ref _selectedJsonHighlightTheme, value);
|
||||
}
|
||||
|
||||
private ulong _criwareDecryptionKey;
|
||||
public ulong CriwareDecryptionKey
|
||||
{
|
||||
|
|
@ -124,6 +132,7 @@ public class SettingsViewModel : ViewModel
|
|||
public ReadOnlyObservableCollection<EDiscordRpc> DiscordRpcs { get; private set; }
|
||||
public ReadOnlyObservableCollection<ECompressedAudio> CompressedAudios { get; private set; }
|
||||
public ReadOnlyObservableCollection<EIconStyle> CosmeticStyles { get; private set; }
|
||||
public ReadOnlyObservableCollection<EJsonHighlightTheme> JsonHighlightThemes { get; private set; }
|
||||
|
||||
private string _outputSnapshot;
|
||||
private string _rawDataSnapshot;
|
||||
|
|
@ -140,6 +149,7 @@ public class SettingsViewModel : ViewModel
|
|||
private ELanguage _assetLanguageSnapshot;
|
||||
private ECompressedAudio _compressedAudioSnapshot;
|
||||
private EIconStyle _cosmeticStyleSnapshot;
|
||||
private EJsonHighlightTheme _jsonHighlightThemeSnapshot;
|
||||
|
||||
private bool _mappingsUpdate = false;
|
||||
|
||||
|
|
@ -176,6 +186,7 @@ public class SettingsViewModel : ViewModel
|
|||
_assetLanguageSnapshot = UserSettings.Default.AssetLanguage;
|
||||
_compressedAudioSnapshot = UserSettings.Default.CompressedAudioMode;
|
||||
_cosmeticStyleSnapshot = UserSettings.Default.CosmeticStyle;
|
||||
_jsonHighlightThemeSnapshot = UserSettings.Default.JsonHighlightTheme;
|
||||
|
||||
SelectedUeGame = _ueGameSnapshot;
|
||||
SelectedCustomVersions = _customVersionsSnapshot;
|
||||
|
|
@ -186,6 +197,7 @@ public class SettingsViewModel : ViewModel
|
|||
SelectedCosmeticStyle = _cosmeticStyleSnapshot;
|
||||
CriwareDecryptionKey = _criwareDecryptionKey;
|
||||
UnluacOpcodeMap = _unluacOpcodeMap;
|
||||
SelectedJsonHighlightTheme = _jsonHighlightThemeSnapshot;
|
||||
SelectedAesReload = UserSettings.Default.AesReload;
|
||||
SelectedDiscordRpc = UserSettings.Default.DiscordRpc;
|
||||
|
||||
|
|
@ -195,6 +207,7 @@ public class SettingsViewModel : ViewModel
|
|||
DiscordRpcs = new ReadOnlyObservableCollection<EDiscordRpc>(new ObservableCollection<EDiscordRpc>(EnumerateDiscordRpcs()));
|
||||
CompressedAudios = new ReadOnlyObservableCollection<ECompressedAudio>(new ObservableCollection<ECompressedAudio>(EnumerateCompressedAudios()));
|
||||
CosmeticStyles = new ReadOnlyObservableCollection<EIconStyle>(new ObservableCollection<EIconStyle>(EnumerateCosmeticStyles()));
|
||||
JsonHighlightThemes = new ReadOnlyObservableCollection<EJsonHighlightTheme>(new ObservableCollection<EJsonHighlightTheme>(EnumerateJsonHighlightThemes()));
|
||||
}
|
||||
|
||||
public bool Save(out List<SettingsOut> whatShouldIDo)
|
||||
|
|
@ -225,6 +238,7 @@ public class SettingsViewModel : ViewModel
|
|||
UserSettings.Default.CosmeticStyle = SelectedCosmeticStyle;
|
||||
UserSettings.Default.AesReload = SelectedAesReload;
|
||||
UserSettings.Default.DiscordRpc = SelectedDiscordRpc;
|
||||
UserSettings.Default.JsonHighlightTheme = SelectedJsonHighlightTheme;
|
||||
|
||||
Options.SaveAsUserDefaults();
|
||||
|
||||
|
|
@ -244,4 +258,5 @@ public class SettingsViewModel : ViewModel
|
|||
private IEnumerable<EDiscordRpc> EnumerateDiscordRpcs() => Enum.GetValues<EDiscordRpc>();
|
||||
private IEnumerable<ECompressedAudio> EnumerateCompressedAudios() => Enum.GetValues<ECompressedAudio>();
|
||||
private IEnumerable<EIconStyle> EnumerateCosmeticStyles() => Enum.GetValues<EIconStyle>();
|
||||
private IEnumerable<EJsonHighlightTheme> EnumerateJsonHighlightThemes() => Enum.GetValues<EJsonHighlightTheme>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@
|
|||
<Geometry x:Key="World3">M3.6 15h16.8</Geometry>
|
||||
<Geometry x:Key="World4">M11.5 3a17 17 0 0 0 0 18</Geometry>
|
||||
<Geometry x:Key="World5">M12.5 3a17 17 0 0 1 0 18</Geometry>
|
||||
<Geometry x:Key="ThemeIcon">M17.5,12A1.5,1.5 0 0,1 16,10.5A1.5,1.5 0 0,1 17.5,9A1.5,1.5 0 0,1 19,10.5A1.5,1.5 0 0,1 17.5,12M14.5,8A1.5,1.5 0 0,1 13,6.5A1.5,1.5 0 0,1 14.5,5A1.5,1.5 0 0,1 16,6.5A1.5,1.5 0 0,1 14.5,8M9.5,8A1.5,1.5 0 0,1 8,6.5A1.5,1.5 0 0,1 9.5,5A1.5,1.5 0 0,1 11,6.5A1.5,1.5 0 0,1 9.5,8M6.5,12A1.5,1.5 0 0,1 5,10.5A1.5,1.5 0 0,1 6.5,9A1.5,1.5 0 0,1 8,10.5A1.5,1.5 0 0,1 6.5,12M12,3A9,9 0 0,0 3,12A9,9 0 0,0 12,21A1.5,1.5 0 0,0 13.5,19.5C13.5,19.11 13.35,18.76 13.11,18.5C12.88,18.23 12.73,17.88 12.73,17.5A1.5,1.5 0 0,1 14.23,16H16A5,5 0 0,0 21,11C21,6.58 16.97,3 12,3Z</Geometry>
|
||||
|
||||
<!-- For specific games-->
|
||||
<Geometry x:Key="BorderlandsIcon">M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6 ZM12,11A3,3 0 1,0 12,17A3,3 0 0,0 12,11 ZM12,12.5L14,16H13L12,14.5L11,16H10L12,12.5Z</Geometry>
|
||||
|
|
|
|||
|
|
@ -101,14 +101,17 @@
|
|||
<Style x:Key="DirectoryFilesListBox" TargetType="ListBox" BasedOn="{StaticResource {x:Type ListBox}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.GameDirectory.DirectoryFilesView, IsAsync=True}" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode" Value="NeverExpand"/>
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement" Value="Docked"/>
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode" Value="NeverExpand" />
|
||||
<Setter Property="adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement" Value="Docked" />
|
||||
<Setter Property="ItemContainerStyle">
|
||||
<Setter.Value>
|
||||
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
|
||||
<Setter Property="Padding" Value="5 3" />
|
||||
<Setter Property="Margin" Value="0 1" />
|
||||
<Setter Property="Padding" Value="7 5" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
|
@ -119,14 +122,26 @@
|
|||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="25" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="95" />
|
||||
<ColumnDefinition Width="85" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image x:Name="ListImage" Source="/FModel;component/Resources/archive.png"
|
||||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 3 0" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Name}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="3" HorizontalAlignment="Right" Text="{Binding Length, Converter={x:Static converters:SizeToStringConverter.Instance}}" />
|
||||
Width="16" Height="16" HorizontalAlignment="Center" Margin="0 0 4 0"
|
||||
VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" />
|
||||
<TextBlock Grid.Column="1" HorizontalAlignment="Left" Text="{Binding Name}" TextTrimming="CharacterEllipsis"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2"
|
||||
Margin="12 0 8 0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Foreground="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}"
|
||||
Opacity="0.75"
|
||||
Text="{Binding FileCount, StringFormat={}{0:N0} files}" />
|
||||
<TextBlock x:Name="LengthText"
|
||||
Grid.Column="3" HorizontalAlignment="Right" Text="{Binding Length, Converter={x:Static converters:SizeToStringConverter.Instance}}"
|
||||
Margin="8 0 0 0"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding IsEnabled}" Value="True">
|
||||
|
|
@ -135,6 +150,10 @@
|
|||
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
|
||||
<Setter TargetName="ListImage" Property="Source" Value="/FModel;component/Resources/archive_disabled.png" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsLooseFilesContainer}" Value="True">
|
||||
<Setter TargetName="LengthText" Property="Visibility" Value="Collapsed" />
|
||||
<Setter TargetName="ListImage" Property="Source" Value="/FModel;component/Resources/asset.png" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||
xmlns:adonisExtensions="clr-namespace:AdonisUI.Extensions;assembly=AdonisUI"
|
||||
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||
WindowStartupLocation="CenterScreen" ResizeMode="NoResize" IconVisibility="Collapsed" SizeToContent="Height"
|
||||
MinHeight="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}, Converter={converters:RatioConverter}, ConverterParameter='0.10'}"
|
||||
Width="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenWidth}, Converter={converters:RatioConverter}, ConverterParameter='0.45'}"
|
||||
|
|
@ -470,7 +471,7 @@
|
|||
HotKey="{Binding RemoveAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="unluacTemplate">
|
||||
<DataTemplate x:Key="UnluacTemplate">
|
||||
<Grid adonisExtensions:LayerExtension.Layer="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
|
|
@ -562,6 +563,65 @@
|
|||
ToolTip="Paste a custom opcode map." />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="ThemesTemplate">
|
||||
<Grid adonisExtensions:LayerExtension.Layer="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="10" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="10" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Text="JSON Highlight Theme"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
ItemsSource="{Binding SettingsView.JsonHighlightThemes}"
|
||||
SelectedItem="{Binding SettingsView.SelectedJsonHighlightTheme, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
Margin="0 0 0 5"
|
||||
SelectionChanged="OnJsonHighlightThemeChanged"
|
||||
Tag="{Binding ElementName=JsonThemePreviewEditor}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Separator Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Style="{StaticResource CustomSeparator}"
|
||||
Tag="PREVIEW" />
|
||||
<Border Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Padding="1"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer1BackgroundBrush}}">
|
||||
<avalonEdit:TextEditor x:Name="JsonThemePreviewEditor"
|
||||
Height="520"
|
||||
FontFamily="Cascadia Mono, Consolas"
|
||||
FontSize="13"
|
||||
Padding="12"
|
||||
ShowLineNumbers="True"
|
||||
IsReadOnly="True"
|
||||
WordWrap="False"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Background="{DynamicResource {x:Static adonisUi:Brushes.Layer3BackgroundBrush}}"
|
||||
Foreground="#DCDDE4"
|
||||
Loaded="OnJsonThemePreviewLoaded" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
</adonisControls:AdonisWindow.Resources>
|
||||
<Grid>
|
||||
|
|
@ -652,7 +712,7 @@
|
|||
</StackPanel>
|
||||
</TreeViewItem.Header>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Tag="unluacTemplate">
|
||||
<TreeViewItem Tag="UnluacTemplate">
|
||||
<TreeViewItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="16" Height="16" HorizontalAlignment="Center" Margin="-20 4 7.5 4">
|
||||
|
|
@ -660,7 +720,7 @@
|
|||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource LuaIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Text="unluac" HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
<TextBlock Text="Unluac" HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem.Header>
|
||||
<TreeViewItem.Style>
|
||||
|
|
@ -674,6 +734,25 @@
|
|||
</Style>
|
||||
</TreeViewItem.Style>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Tag="ThemesTemplate">
|
||||
<TreeViewItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Width="16"
|
||||
Height="16"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="-20 4 7.5 4">
|
||||
<Canvas Width="24"
|
||||
Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}"
|
||||
Data="{StaticResource ThemeIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Text="Themes"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem.Header>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
|
||||
<Grid Grid.Row="0" Grid.Column="1" Margin="{adonisUi:Space 1, 0.5}" HorizontalAlignment="Stretch">
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using CUE4Parse.UE4.Lua.unluac;
|
||||
using FModel.Extensions;
|
||||
using FModel.Extensions.Themes;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
using FModel.Settings;
|
||||
using FModel.ViewModels;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using ICSharpCode.AvalonEdit;
|
||||
using Microsoft.Win32;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
|
|
@ -19,6 +23,7 @@ namespace FModel.Views;
|
|||
public partial class SettingsView
|
||||
{
|
||||
private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
|
||||
private SettingsViewModel _settingsView => _applicationView.SettingsView;
|
||||
|
||||
public SettingsView()
|
||||
{
|
||||
|
|
@ -294,4 +299,64 @@ public partial class SettingsView
|
|||
|
||||
UserSettings.Default.UnluacFlags = isChecked ? (current | flag) : (current & ~flag);
|
||||
}
|
||||
|
||||
private const string JsonThemePreviewText =
|
||||
"""
|
||||
{
|
||||
"title": "This is an example JSON",
|
||||
"environment": "production",
|
||||
"enabled": true,
|
||||
"version": 4,
|
||||
"scale": 0.92,
|
||||
"features": {
|
||||
"previewAssets": true,
|
||||
"autoSave": false,
|
||||
"maxRecentFiles": 12
|
||||
},
|
||||
"export": {
|
||||
"rootDirectory": "C:\\Exports\\Assets",
|
||||
"keepDirectoryStructure": true,
|
||||
"formats": [
|
||||
"json",
|
||||
"png",
|
||||
"wav"
|
||||
]
|
||||
},
|
||||
"paths": [
|
||||
"/Game/Characters/Hero",
|
||||
"/Game/UI/Widgets",
|
||||
"/Game/Audio/Music"
|
||||
],
|
||||
"metadata": {
|
||||
"lastOpened": "2026-06-20T14:30:00Z",
|
||||
"experimental": false,
|
||||
"fallbackTheme": null,
|
||||
"escapeExample": "Line one\nLine two\tTabbed",
|
||||
"accentColor": "#FFC857"
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
private void OnJsonThemePreviewLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not TextEditor editor)
|
||||
return;
|
||||
|
||||
editor.SyntaxHighlighting = AvalonExtensions.HighlighterSelector("json");
|
||||
editor.Text = JsonThemePreviewText;
|
||||
ApplyJsonThemePreview(editor);
|
||||
}
|
||||
|
||||
private void OnJsonHighlightThemeChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is FrameworkElement { Tag: TextEditor editor })
|
||||
Dispatcher.BeginInvoke(() => ApplyJsonThemePreview(editor));
|
||||
}
|
||||
|
||||
private void ApplyJsonThemePreview(TextEditor editor)
|
||||
{
|
||||
editor.SyntaxHighlighting ??= AvalonExtensions.HighlighterSelector("json");
|
||||
editor.SyntaxHighlighting.ApplyJsonTheme(_applicationView.SettingsView.SelectedJsonHighlightTheme);
|
||||
editor.TextArea.TextView.Redraw();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public class SkeletalModel : UModel<SkinnedMeshVertex>
|
|||
|
||||
foreach (var morph in export.MorphTargets)
|
||||
{
|
||||
if (!morph.TryLoad(out UMorphTarget morphTarget) || morphTarget.MorphLODModels.Length < 1 ||
|
||||
if (!morph.TryLoad(out UMorphTarget morphTarget) || morphTarget.MorphLODModels.Length <= skeletalMesh.LODs[LodLevel].SourceLodIndex ||
|
||||
morphTarget.MorphLODModels[skeletalMesh.LODs[LodLevel].SourceLodIndex].Vertices.Length < 1)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ public class Options
|
|||
{
|
||||
return _game switch
|
||||
{
|
||||
"LIESOFP" or "CODEVEIN2" or "HIGHONLIFE2" => true,
|
||||
"LIESOFP" or "CODEVEIN2" or "HIGHONLIFE2" or "MORTALSHELL2" => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user