Skip to content

Commit

Permalink
ui now deals with GameFile instead of a bad replica
Browse files Browse the repository at this point in the history
that means loose files are now supported, or should be
Export Raw Data shows the correct extension
  • Loading branch information
4sval committed Feb 6, 2025
1 parent 3d0bdf0 commit dbf618e
Show file tree
Hide file tree
Showing 20 changed files with 246 additions and 336 deletions.
27 changes: 27 additions & 0 deletions FModel/Framework/FakeCUE4Parse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using CUE4Parse.Compression;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.UE4.Readers;

namespace FModel.Framework;

public class FakeGameFile : GameFile
{
public FakeGameFile(string path) : base(path, 0)
{

}

public override bool IsEncrypted => false;
public override CompressionMethod CompressionMethod => CompressionMethod.None;

public override byte[] Read()
{
throw new NotImplementedException();
}

public override FArchive CreateReader()
{
throw new NotImplementedException();
}
}
13 changes: 10 additions & 3 deletions FModel/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,14 @@
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Export Raw Data (.uasset)" Command="{Binding DataContext.RightClickMenuCommand}">
<MenuItem Command="{Binding DataContext.RightClickMenuCommand}">
<MenuItem.Header>
<TextBlock
Text="{Binding DataContext.SelectedItem.Extension,
FallbackValue='uasset',
StringFormat='Export Raw Data (.{0})',
RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
</MenuItem.Header>
<MenuItem.CommandParameter>
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
<Binding Source="Assets_Export_Data" />
Expand Down Expand Up @@ -649,11 +656,11 @@
<TextBlock Grid.Row="0" Grid.Column="1" Text="Offset" VerticalAlignment="Center" HorizontalAlignment="Right" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding SelectedItem.Size, ElementName=AssetsListName, FallbackValue=0, Converter={x:Static converters:SizeToStringConverter.Instance}}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="Size" VerticalAlignment="Center" HorizontalAlignment="Right" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.Compression, ElementName=AssetsListName, FallbackValue='Unknown'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding SelectedItem.CompressionMethod, ElementName=AssetsListName, FallbackValue='Unknown'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Grid.Row="2" Grid.Column="1" Text="Compression Method" VerticalAlignment="Center" HorizontalAlignment="Right" />
<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.Archive, ElementName=AssetsListName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Grid.Row="4" Grid.Column="0" Text="{Binding SelectedItem.Vfs.Name, ElementName=AssetsListName, FallbackValue='None'}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock Grid.Row="4" Grid.Column="1" Text="Included In Archive" VerticalAlignment="Center" HorizontalAlignment="Right" />
</Grid>
</StackPanel>
Expand Down
9 changes: 5 additions & 4 deletions FModel/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Windows.Controls;
using System.Windows.Input;
using AdonisUI.Controls;
using CUE4Parse.FileProvider.Objects;
using FModel.Services;
using FModel.Settings;
using FModel.ViewModels;
Expand Down Expand Up @@ -84,7 +85,7 @@ await Task.WhenAll(
#if DEBUG
// await _threadWorkerView.Begin(cancellationToken =>
// _applicationView.CUE4Parse.Extract(cancellationToken,
// "MyProject/Content/FirstPerson/Meshes/FirstPersonProjectileMesh.uasset"));
// "Marvel/Content/Marvel/Characters/1016/1016501/Meshes/SK_1016_1016501.uasset"));
// await _threadWorkerView.Begin(cancellationToken =>
// _applicationView.CUE4Parse.Extract(cancellationToken,
// "RED/Content/Chara/ABA/Costume01/Animation/Charaselect/body/stand_body01.uasset"));
Expand Down Expand Up @@ -162,7 +163,7 @@ private async void OnAssetsListMouseDoubleClick(object sender, MouseButtonEventA
{
if (sender is not ListBox listBox) return;

var selectedItems = listBox.SelectedItems.Cast<AssetItem>().ToList();
var selectedItems = listBox.SelectedItems.Cast<GameFile>().ToList();
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
}

Expand Down Expand Up @@ -266,7 +267,7 @@ private void OnFilterTextChanged(object sender, TextChangedEventArgs e)
return;

var filters = textBox.Text.Trim().Split(' ');
folder.AssetsList.AssetsView.Filter = o => { return o is AssetItem assetItem && filters.All(x => assetItem.FileName.Contains(x, StringComparison.OrdinalIgnoreCase)); };
folder.AssetsList.AssetsView.Filter = o => { return o is GameFile entry && filters.All(x => entry.Name.Contains(x, StringComparison.OrdinalIgnoreCase)); };
}

private void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
Expand All @@ -283,7 +284,7 @@ private async void OnPreviewKeyDown(object sender, KeyEventArgs e)
switch (e.Key)
{
case Key.Enter:
var selectedItems = listBox.SelectedItems.Cast<AssetItem>().ToList();
var selectedItems = listBox.SelectedItems.Cast<GameFile>().ToList();
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExtractSelected(cancellationToken, selectedItems); });
break;
}
Expand Down
70 changes: 34 additions & 36 deletions FModel/ViewModels/AssetsFolderViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Text;
using System.Windows;
using System.Windows.Data;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.UE4.Versions;
using CUE4Parse.UE4.VirtualFileSystem;
using FModel.Framework;
Expand Down Expand Up @@ -60,12 +61,15 @@ public FPackageFileVersion Version
public RangeObservableCollection<TreeItem> Folders { get; }
public ICollectionView FoldersView { get; }

public TreeItem(string header, string archive, string mountPoint, FPackageFileVersion version, string pathHere)
public TreeItem(string header, GameFile entry, string pathHere)
{
Header = header;
Archive = archive;
MountPoint = mountPoint;
Version = version;
if (entry is VfsEntry vfsEntry)
{
Archive = vfsEntry.Vfs.Name;
MountPoint = vfsEntry.Vfs.MountPoint;
Version = vfsEntry.Vfs.Ver;
}
PathAtThisPoint = pathHere;
AssetsList = new AssetsListViewModel();
Folders = new RangeObservableCollection<TreeItem>();
Expand All @@ -86,7 +90,7 @@ public AssetsFolderViewModel()
FoldersView = new ListCollectionView(Folders) { SortDescriptions = { new SortDescription("Header", ListSortDirection.Ascending) } };
}

public void BulkPopulate(IReadOnlyCollection<VfsEntry> entries)
public void BulkPopulate(IReadOnlyCollection<GameFile> entries)
{
if (entries == null || entries.Count == 0)
return;
Expand All @@ -95,54 +99,48 @@ public void BulkPopulate(IReadOnlyCollection<VfsEntry> entries)
{
var treeItems = new RangeObservableCollection<TreeItem>();
treeItems.SetSuppressionState(true);
var items = new List<AssetItem>(entries.Count);

foreach (var entry in entries)
{
var item = new AssetItem(entry.Path, entry.IsEncrypted, entry.Offset, entry.Size, entry.Vfs.Name, entry.CompressionMethod);
items.Add(item);
TreeItem lastNode = null;
var folders = entry.Path.Split('/', StringSplitOptions.RemoveEmptyEntries);
var builder = new StringBuilder(64);
var parentNode = treeItems;

for (var i = 0; i < folders.Length - 1; i++)
{
TreeItem lastNode = null;
var folders = item.FullPath.Split('/', StringSplitOptions.RemoveEmptyEntries);
var builder = new StringBuilder(64);
var parentNode = treeItems;
var folder = folders[i];
builder.Append(folder).Append('/');
lastNode = FindByHeaderOrNull(parentNode, folder);

for (var i = 0; i < folders.Length - 1; i++)
static TreeItem FindByHeaderOrNull(IReadOnlyList<TreeItem> list, string header)
{
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++)
{
for (var i = 0; i < list.Count; i++)
{
if (list[i].Header == header)
return list[i];
}

return null;
if (list[i].Header == header)
return list[i];
}

if (lastNode == null)
{
var nodePath = builder.ToString();
lastNode = new TreeItem(folder, item.Archive, entry.Vfs.MountPoint, entry.Vfs.Ver, nodePath[..^1]);
lastNode.Folders.SetSuppressionState(true);
lastNode.AssetsList.Assets.SetSuppressionState(true);
parentNode.Add(lastNode);
}
return null;
}

parentNode = lastNode.Folders;
if (lastNode == null)
{
var nodePath = builder.ToString();
lastNode = new TreeItem(folder, entry, nodePath[..^1]);
lastNode.Folders.SetSuppressionState(true);
lastNode.AssetsList.Assets.SetSuppressionState(true);
parentNode.Add(lastNode);
}

lastNode?.AssetsList.Assets.Add(item);
parentNode = lastNode.Folders;
}

lastNode?.AssetsList.Assets.Add(entry);
}

Folders.AddRange(treeItems);
ApplicationService.ApplicationView.CUE4Parse.SearchVm.SearchResults.AddRange(items);
ApplicationService.ApplicationView.CUE4Parse.SearchVm.SearchResults.AddRange(entries);

foreach (var folder in Folders)
InvokeOnCollectionChanged(folder);
Expand Down
96 changes: 4 additions & 92 deletions FModel/ViewModels/AssetsListViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,109 +1,21 @@
using System.ComponentModel;
using System.Windows.Data;
using CUE4Parse.Compression;
using CUE4Parse.Utils;
using CUE4Parse.FileProvider.Objects;
using FModel.Framework;

namespace FModel.ViewModels;

public class AssetItem : ViewModel
{
private string _fullPath;
public string FullPath
{
get => _fullPath;
private set => SetProperty(ref _fullPath, value);
}

private bool _isEncrypted;
public bool IsEncrypted
{
get => _isEncrypted;
private set => SetProperty(ref _isEncrypted, value);
}

private long _offset;
public long Offset
{
get => _offset;
private set => SetProperty(ref _offset, value);
}

private long _size;
public long Size
{
get => _size;
private set => SetProperty(ref _size, value);
}

private string _archive;
public string Archive
{
get => _archive;
private set => SetProperty(ref _archive, value);
}

private CompressionMethod _compression;
public CompressionMethod Compression
{
get => _compression;
private set => SetProperty(ref _compression, value);
}

private string _directory;
public string Directory
{
get => _directory;
private set => SetProperty(ref _directory, value);
}

private string _fileName;
public string FileName
{
get => _fileName;
private set => SetProperty(ref _fileName, value);
}

private string _extension;
public string Extension
{
get => _extension;
private set => SetProperty(ref _extension, value);
}

public AssetItem(string titleExtra, AssetItem asset) : this(asset.FullPath, asset.IsEncrypted, asset.Offset, asset.Size, asset.Archive, asset.Compression)
{
FullPath += titleExtra;
}

public AssetItem(string fullPath, bool isEncrypted = false, long offset = 0, long size = 0, string archive = "", CompressionMethod compression = CompressionMethod.None)
{
FullPath = fullPath;
IsEncrypted = isEncrypted;
Offset = offset;
Size = size;
Archive = archive;
Compression = compression;

Directory = FullPath.SubstringBeforeLast('/');
FileName = FullPath.SubstringAfterLast('/');
Extension = FullPath.SubstringAfterLast('.').ToLowerInvariant();
}

public override string ToString() => FullPath;
}

public class AssetsListViewModel
{
public RangeObservableCollection<AssetItem> Assets { get; }
public RangeObservableCollection<GameFile> Assets { get; }
public ICollectionView AssetsView { get; }

public AssetsListViewModel()
{
Assets = new RangeObservableCollection<AssetItem>();
Assets = new RangeObservableCollection<GameFile>();
AssetsView = new ListCollectionView(Assets)
{
SortDescriptions = { new SortDescription("FullPath", ListSortDirection.Ascending) }
SortDescriptions = { new SortDescription("Path", ListSortDirection.Ascending) }
};
}
}
Loading

0 comments on commit dbf618e

Please sign in to comment.