kinda cleaned the big mess

This commit is contained in:
4sval 2022-12-27 19:26:41 +01:00
parent 16dd4236eb
commit b068e446d0
35 changed files with 262 additions and 171 deletions

@ -1 +1 @@
Subproject commit 7fc7ef6361ce8bace402e177fb817f0bf5a16d2b
Subproject commit 1f4724d633d72f9b97c25de1ac8a75ea895a4afe

View File

@ -218,7 +218,6 @@
<Resource Include="Resources\delete.png" />
<Resource Include="Resources\edit.png" />
<Resource Include="Resources\go_to_directory.png" />
<Resource Include="Resources\approaching_storm_cubemap.dds" />
<Resource Include="Resources\npcleftside.png" />
<Resource Include="Resources\nx.png" />
<Resource Include="Resources\ny.png" />

View File

@ -8,6 +8,7 @@ using CUE4Parse.UE4.Objects.Core.Serialization;
using CUE4Parse.UE4.Versions;
using CUE4Parse_Conversion.Meshes;
using CUE4Parse_Conversion.Textures;
using CUE4Parse.UE4.Assets.Exports.Material;
using FModel.Framework;
using FModel.ViewModels;
using FModel.ViewModels.ApiEndpoints.Models;
@ -571,6 +572,20 @@ namespace FModel.Settings
set => SetProperty(ref _meshExportFormat, value);
}
private EMaterialFormat _materialExportFormat = EMaterialFormat.FirstLayer;
public EMaterialFormat MaterialExportFormat
{
get => _materialExportFormat;
set => SetProperty(ref _materialExportFormat, value);
}
private ETextureFormat _textureExportFormat = ETextureFormat.Png;
public ETextureFormat TextureExportFormat
{
get => _textureExportFormat;
set => SetProperty(ref _textureExportFormat, value);
}
private ESocketFormat _socketExportFormat = ESocketFormat.Bone;
public ESocketFormat SocketExportFormat
{
@ -640,12 +655,5 @@ namespace FModel.Settings
get => _saveSkeletonAsMesh;
set => SetProperty(ref _saveSkeletonAsMesh, value);
}
private ETextureFormat _textureExportFormat = ETextureFormat.Png;
public ETextureFormat TextureExportFormat
{
get => _textureExportFormat;
set => SetProperty(ref _textureExportFormat, value);
}
}
}

View File

@ -369,7 +369,10 @@ public class CUE4ParseViewModel : ViewModel
public async Task InitMappings()
{
if (!UserSettings.IsEndpointValid(Game, EEndpointType.Mapping, out var endpoint))
{
Provider.MappingsContainer = null;
return;
}
await _threadWorkerView.Begin(cancellationToken =>
{
@ -861,9 +864,10 @@ public class CUE4ParseViewModel : ViewModel
{
var exportOptions = new ExporterOptions
{
TextureFormat = UserSettings.Default.TextureExportFormat,
LodFormat = UserSettings.Default.LodExportFormat,
MeshFormat = UserSettings.Default.MeshExportFormat,
MaterialFormat = UserSettings.Default.MaterialExportFormat,
TextureFormat = UserSettings.Default.TextureExportFormat,
SocketFormat = UserSettings.Default.SocketExportFormat,
Platform = UserSettings.Default.OverridedPlatform,
ExportMorphTargets = UserSettings.Default.SaveMorphTargets

View File

@ -8,6 +8,7 @@ using CUE4Parse.UE4.Objects.Core.Serialization;
using CUE4Parse.UE4.Versions;
using CUE4Parse_Conversion.Meshes;
using CUE4Parse_Conversion.Textures;
using CUE4Parse.UE4.Assets.Exports.Material;
using FModel.Extensions;
using FModel.Framework;
using FModel.Services;
@ -145,6 +146,13 @@ public class SettingsViewModel : ViewModel
set => SetProperty(ref _selectedLodExportFormat, value);
}
private EMaterialFormat _selectedMaterialExportFormat;
public EMaterialFormat SelectedMaterialExportFormat
{
get => _selectedMaterialExportFormat;
set => SetProperty(ref _selectedMaterialExportFormat, value);
}
private ETextureFormat _selectedTextureExportFormat;
public ETextureFormat SelectedTextureExportFormat
{
@ -163,6 +171,7 @@ public class SettingsViewModel : ViewModel
public ReadOnlyObservableCollection<EMeshFormat> MeshExportFormats { get; private set; }
public ReadOnlyObservableCollection<ESocketFormat> SocketExportFormats { get; private set; }
public ReadOnlyObservableCollection<ELodFormat> LodExportFormats { get; private set; }
public ReadOnlyObservableCollection<EMaterialFormat> MaterialExportFormats { get; private set; }
public ReadOnlyObservableCollection<ETextureFormat> TextureExportFormats { get; private set; }
public ReadOnlyObservableCollection<ETexturePlatform> Platforms { get; private set; }
@ -189,6 +198,7 @@ public class SettingsViewModel : ViewModel
private EMeshFormat _meshExportFormatSnapshot;
private ESocketFormat _socketExportFormatSnapshot;
private ELodFormat _lodExportFormatSnapshot;
private EMaterialFormat _materialExportFormatSnapshot;
private ETextureFormat _textureExportFormatSnapshot;
private bool _mappingsUpdate = false;
@ -240,6 +250,7 @@ public class SettingsViewModel : ViewModel
_meshExportFormatSnapshot = UserSettings.Default.MeshExportFormat;
_socketExportFormatSnapshot = UserSettings.Default.SocketExportFormat;
_lodExportFormatSnapshot = UserSettings.Default.LodExportFormat;
_materialExportFormatSnapshot = UserSettings.Default.MaterialExportFormat;
_textureExportFormatSnapshot = UserSettings.Default.TextureExportFormat;
SelectedUpdateMode = _updateModeSnapshot;
@ -254,6 +265,7 @@ public class SettingsViewModel : ViewModel
SelectedMeshExportFormat = _meshExportFormatSnapshot;
SelectedSocketExportFormat = _socketExportFormatSnapshot;
SelectedLodExportFormat = _lodExportFormatSnapshot;
SelectedMaterialExportFormat = _materialExportFormatSnapshot;
SelectedTextureExportFormat = _textureExportFormatSnapshot;
SelectedAesReload = UserSettings.Default.AesReload;
SelectedDiscordRpc = UserSettings.Default.DiscordRpc;
@ -269,6 +281,7 @@ public class SettingsViewModel : ViewModel
MeshExportFormats = new ReadOnlyObservableCollection<EMeshFormat>(new ObservableCollection<EMeshFormat>(EnumerateMeshExportFormat()));
SocketExportFormats = new ReadOnlyObservableCollection<ESocketFormat>(new ObservableCollection<ESocketFormat>(EnumerateSocketExportFormat()));
LodExportFormats = new ReadOnlyObservableCollection<ELodFormat>(new ObservableCollection<ELodFormat>(EnumerateLodExportFormat()));
MaterialExportFormats = new ReadOnlyObservableCollection<EMaterialFormat>(new ObservableCollection<EMaterialFormat>(EnumerateMaterialExportFormat()));
TextureExportFormats = new ReadOnlyObservableCollection<ETextureFormat>(new ObservableCollection<ETextureFormat>(EnumerateTextureExportFormat()));
Platforms = new ReadOnlyObservableCollection<ETexturePlatform>(new ObservableCollection<ETexturePlatform>(EnumerateUePlatforms()));
}
@ -358,6 +371,7 @@ public class SettingsViewModel : ViewModel
UserSettings.Default.MeshExportFormat = SelectedMeshExportFormat;
UserSettings.Default.SocketExportFormat = SelectedSocketExportFormat;
UserSettings.Default.LodExportFormat = SelectedLodExportFormat;
UserSettings.Default.MaterialExportFormat = SelectedMaterialExportFormat;
UserSettings.Default.TextureExportFormat = SelectedTextureExportFormat;
UserSettings.Default.AesReload = SelectedAesReload;
UserSettings.Default.DiscordRpc = SelectedDiscordRpc;
@ -382,6 +396,7 @@ public class SettingsViewModel : ViewModel
private IEnumerable<EMeshFormat> EnumerateMeshExportFormat() => Enum.GetValues<EMeshFormat>();
private IEnumerable<ESocketFormat> EnumerateSocketExportFormat() => Enum.GetValues<ESocketFormat>();
private IEnumerable<ELodFormat> EnumerateLodExportFormat() => Enum.GetValues<ELodFormat>();
private IEnumerable<EMaterialFormat> EnumerateMaterialExportFormat() => Enum.GetValues<EMaterialFormat>();
private IEnumerable<ETextureFormat> EnumerateTextureExportFormat() => Enum.GetValues<ETextureFormat>();
private IEnumerable<ETexturePlatform> EnumerateUePlatforms() => Enum.GetValues<ETexturePlatform>();
}

View File

@ -21,7 +21,7 @@
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<avalonEdit:TextEditor x:Name="MyAvalonEditor" Grid.Row="0" Background="{DynamicResource {x:Static adonisUi:Brushes.Layer3BackgroundBrush}}"
FontFamily="Consolas" FontSize="8pt" IsReadOnly="True" ShowLineNumbers="True" Foreground="#DAE5F2" />
@ -33,15 +33,18 @@
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="HeBrokeIt" Grid.Column="0" Text="IF YOU DON'T KNOW WHAT THIS DOES, DON'T TOUCH IT, EVER!"
<TextBlock x:Name="HeBrokeIt" Grid.Column="0" Text="IF YOU DON'T KNOW WHAT THIS DOES, DON'T TOUCH IT!"
HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="11" Margin="0 0 10 0" FontWeight="DemiBold"
Foreground="{DynamicResource {x:Static adonisUi:Brushes.Layer1InteractionForegroundBrush}}" />
<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="True"
<Button Grid.Column="2" MinWidth="78" Margin="0 0 12 0" IsDefault="False" IsCancel="False"
HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="Reset" Click="OnReset" />
<Button Grid.Column="3" MinWidth="78" Margin="0 0 12 0" IsDefault="False" IsCancel="True"
HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="Cancel" />
</Grid>
</Border>

View File

@ -64,12 +64,14 @@ public partial class DictionaryEditor
{
case "Versioning Configuration (Custom Versions)":
CustomVersions = JsonConvert.DeserializeObject<List<FCustomVersion>>(MyAvalonEditor.Document.Text);
DialogResult = !CustomVersions.SequenceEqual(_defaultCustomVersions);
// DialogResult = !CustomVersions.SequenceEqual(_defaultCustomVersions);
DialogResult = true;
Close();
break;
case "Versioning Configuration (Options)":
Options = JsonConvert.DeserializeObject<Dictionary<string, bool>>(MyAvalonEditor.Document.Text);
DialogResult = !Options.SequenceEqual(_defaultOptions);
// DialogResult = !Options.SequenceEqual(_defaultOptions);
DialogResult = true;
Close();
break;
default:
@ -78,8 +80,27 @@ public partial class DictionaryEditor
}
catch
{
HeBrokeIt.Text = "GG YOU BROKE THE FORMAT, FIX THE JSON OR CANCEL THE CHANGES!";
HeBrokeIt.Text = "GG YOU BROKE THE FORMAT, FIX THE JSON OR RESET THE CHANGES!";
HeBrokeIt.Foreground = new SolidColorBrush((Color) ColorConverter.ConvertFromString(Constants.RED));
}
}
}
private void OnReset(object sender, RoutedEventArgs e)
{
if (!_enableElements)
return;
MyAvalonEditor.Document = Title switch
{
"Versioning Configuration (Custom Versions)" => new TextDocument
{
Text = JsonConvert.SerializeObject(_defaultCustomVersions, Formatting.Indented)
},
"Versioning Configuration (Options)" => new TextDocument
{
Text = JsonConvert.SerializeObject(_defaultOptions, Formatting.Indented)
},
_ => throw new NotImplementedException()
};
}
}

View File

@ -67,12 +67,6 @@
<Geometry x:Key="UnfoldIcon">M12 5.83l2.46 2.46c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L12.7 3.7c-.39-.39-1.02-.39-1.41 0L8.12 6.88c-.39.39-.39 1.02 0 1.41.39.39 1.02.39 1.41 0L12 5.83zm0 12.34l-2.46-2.46c-.39-.39-1.02-.39-1.41 0-.39.39-.39 1.02 0 1.41l3.17 3.18c.39.39 1.02.39 1.41 0l3.17-3.17c.39-.39.39-1.02 0-1.41-.39-.39-1.02-.39-1.41 0L12 18.17z</Geometry>
<Geometry x:Key="LocateMeIcon">M11.71,17.99C8.53,17.84,6,15.22,6,12c0-3.31,2.69-6,6-6c3.22,0,5.84,2.53,5.99,5.71l-2.1-0.63C15.48,9.31,13.89,8,12,8 c-2.21,0-4,1.79-4,4c0,1.89,1.31,3.48,3.08,3.89L11.71,17.99z M22,12c0,0.3-0.01,0.6-0.04,0.9l-1.97-0.59C20,12.21,20,12.1,20,12 c0-4.42-3.58-8-8-8s-8,3.58-8,8s3.58,8,8,8c0.1,0,0.21,0,0.31-0.01l0.59,1.97C12.6,21.99,12.3,22,12,22C6.48,22,2,17.52,2,12 C2,6.48,6.48,2,12,2S22,6.48,22,12z M18.23,16.26l2.27-0.76c0.46-0.15,0.45-0.81-0.01-0.95l-7.6-2.28 c-0.38-0.11-0.74,0.24-0.62,0.62l2.28,7.6c0.14,0.47,0.8,0.48,0.95,0.01l0.76-2.27l3.91,3.91c0.2,0.2,0.51,0.2,0.71,0l1.27-1.27 c0.2-0.2,0.2-0.51,0-0.71L18.23,16.26z</Geometry>
<Geometry x:Key="MeshIcon">M1.8 6q-.525 0-.887-.35Q.55 5.3.55 4.8V4q0-1.425 1.012-2.438Q2.575.55 4 .55h.8q.5 0 .85.362.35.363.35.888 0 .5-.35.85T4.8 3H4q-.425 0-.712.287Q3 3.575 3 4v.8q0 .5-.35.85T1.8 6ZM4 23.45q-1.425 0-2.438-1.012Q.55 21.425.55 20v-.8q0-.5.363-.85.362-.35.887-.35.5 0 .85.35t.35.85v.8q0 .425.288.712Q3.575 21 4 21h.8q.5 0 .85.35t.35.85q0 .525-.35.887-.35.363-.85.363Zm15.2 0q-.5 0-.85-.363-.35-.362-.35-.887 0-.5.35-.85t.85-.35h.8q.425 0 .712-.288Q21 20.425 21 20v-.8q0-.5.35-.85t.85-.35q.525 0 .888.35.362.35.362.85v.8q0 1.425-1.012 2.438Q21.425 23.45 20 23.45ZM22.2 6q-.5 0-.85-.35T21 4.8V4q0-.425-.288-.713Q20.425 3 20 3h-.8q-.5 0-.85-.35T18 1.8q0-.525.35-.888.35-.362.85-.362h.8q1.425 0 2.438 1.012Q23.45 2.575 23.45 4v.8q0 .5-.362.85-.363.35-.888.35ZM12 17.35l1-.575v-4.1l3.55-2.075V9.425l-1-.575L12 10.925 8.45 8.85l-1 .575V10.6L11 12.675v4.1Zm-1.325 2.325-4.55-2.65q-.625-.35-.975-.963-.35-.612-.35-1.337V9.45q0-.725.35-1.337.35-.613.975-.963l4.55-2.65Q11.3 4.15 12 4.15t1.325.35l4.55 2.65q.625.35.975.963.35.612.35 1.337v5.275q0 .725-.35 1.337-.35.613-.975.963l-4.55 2.65q-.625.35-1.325.35t-1.325-.35Z</Geometry>
<Geometry x:Key="MaterialIcon">M11 9h2v2h-2V9zm-2 2h2v2H9v-2zm4 0h2v2h-2v-2zm2-2h2v2h-2V9zM7 9h2v2H7V9zm12-6H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 18H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm2-7h-2v2h2v2h-2v-2h-2v2h-2v-2h-2v2H9v-2H7v2H5v-2h2v-2H5V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v5z</Geometry>
<Geometry x:Key="VisibleIcon">M12 4C7 4 2.73 7.11 1 11.5 2.73 15.89 7 19 12 19s9.27-3.11 11-7.5C21.27 7.11 17 4 12 4zm0 12.5c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z</Geometry>
<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="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">
@ -620,25 +614,6 @@
</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="GameFilesTabControl" TargetType="TabControl" BasedOn="{StaticResource {x:Type TabControl}}">
<Setter Property="ItemsSource" Value="{Binding CUE4Parse.TabControl.TabsItems, IsAsync=True}" />
<Setter Property="SelectedItem" Value="{Binding CUE4Parse.TabControl.SelectedTab}" />

View File

@ -309,6 +309,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -387,8 +388,18 @@
<Separator Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="5" Style="{StaticResource CustomSeparator}" />
<TextBlock Grid.Row="12" Grid.Column="0" Text="Texture Format" VerticalAlignment="Center" Margin="0 0 0 5" />
<ComboBox Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.TextureExportFormats}" SelectedItem="{Binding SettingsView.SelectedTextureExportFormat, Mode=TwoWay}"
<TextBlock Grid.Row="12" Grid.Column="0" Text="Material Format" VerticalAlignment="Center" Margin="0 0 0 5" />
<ComboBox Grid.Row="12" Grid.Column="2" Grid.ColumnSpan="3" ItemsSource="{Binding SettingsView.MaterialExportFormats}" SelectedItem="{Binding SettingsView.SelectedMaterialExportFormat, Mode=TwoWay}"
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}" Margin="0 0 0 5">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Row="13" Grid.Column="0" Text="Texture Format" VerticalAlignment="Center" Margin="0 0 0 5" />
<ComboBox Grid.Row="13" 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>

View File

@ -1,7 +1,7 @@
using System;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Buffers;
public class BufferObject<TDataType> : IDisposable where TDataType : unmanaged
{

View File

@ -1,7 +1,8 @@
using System;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Buffers;
public class FramebufferObject : IDisposable
{

View File

@ -3,8 +3,10 @@ using System.Collections.Generic;
using CUE4Parse.UE4.Objects.Core.Misc;
using OpenTK.Graphics.OpenGL4;
using System.Numerics;
using FModel.Views.Snooper.Models;
using FModel.Views.Snooper.Shading;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Buffers;
public class PickingTexture : IDisposable
{

View File

@ -1,7 +1,7 @@
using System;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Buffers;
public class RenderbufferObject : IDisposable
{

View File

@ -2,7 +2,7 @@
using System.Numerics;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Buffers;
public class VertexArrayObject<TVertexType, TIndexType> : IDisposable where TVertexType : unmanaged where TIndexType : unmanaged
{

View File

@ -3,10 +3,12 @@ using System.Numerics;
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Shading;
using ImGuiNET;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Lights;
public abstract class Light : IDisposable
{

View File

@ -2,9 +2,10 @@
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Views.Snooper.Shading;
using ImGuiNET;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Lights;
public class PointLight : Light
{

View File

@ -1,9 +1,10 @@
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Views.Snooper.Shading;
using ImGuiNET;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Lights;
public class SpotLight : Light
{

View File

@ -3,7 +3,7 @@ using System.Numerics;
using CUE4Parse_Conversion.Animations;
using CUE4Parse.UE4.Objects.Core.Math;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models.Animations;
public class Animation : IDisposable
{

View File

@ -5,8 +5,9 @@ using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.UObject;
using FModel.Views.Snooper.Shading;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models.Animations;
public class Skeleton : IDisposable
{

View File

@ -1,6 +1,7 @@
using CUE4Parse.UE4.Assets.Exports.Material;
using FModel.Views.Snooper.Shading;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Cube : Model
{

View File

@ -1,8 +1,10 @@
using System;
using System.Numerics;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Grid : IDisposable
{

View File

@ -14,9 +14,12 @@ using CUE4Parse.UE4.Assets.Exports.StaticMesh;
using FModel.Extensions;
using FModel.Services;
using FModel.Settings;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Models.Animations;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Model : IDisposable
{
@ -319,9 +322,11 @@ public class Model : IDisposable
{
var exportOptions = new ExporterOptions
{
TextureFormat = UserSettings.Default.TextureExportFormat,
LodFormat = UserSettings.Default.LodExportFormat,
MeshFormat = UserSettings.Default.MeshExportFormat,
MaterialFormat = UserSettings.Default.MaterialExportFormat,
TextureFormat = UserSettings.Default.TextureExportFormat,
SocketFormat = UserSettings.Default.SocketExportFormat,
Platform = UserSettings.Default.OverridedPlatform,
ExportMorphTargets = UserSettings.Default.SaveMorphTargets
};

View File

@ -3,7 +3,7 @@ using CUE4Parse.UE4.Assets.Exports.Animation;
using CUE4Parse.UE4.Objects.Core.Math;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Morph : IDisposable
{

View File

@ -1,7 +1,8 @@
using System;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Section : IDisposable
{

View File

@ -1,8 +1,10 @@
using System;
using System.Numerics;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Skybox : IDisposable
{

View File

@ -3,7 +3,7 @@ using System.Numerics;
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
using CUE4Parse.UE4.Objects.Core.Math;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Models;
public class Socket : IDisposable
{

View File

@ -4,6 +4,9 @@ using CUE4Parse_Conversion.Textures;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Settings;
using FModel.Views.Snooper.Lights;
using FModel.Views.Snooper.Models;
using FModel.Views.Snooper.Shading;
namespace FModel.Views.Snooper;
@ -20,7 +23,6 @@ public class Options
public readonly Dictionary<string, Texture> Icons;
private ETexturePlatform _platform;
private readonly string _game;
public Options()
{
@ -37,7 +39,6 @@ public class Options
};
_platform = UserSettings.Default.OverridedPlatform;
_game = Services.ApplicationService.ApplicationView.CUE4Parse.Provider.GameName;
SelectModel(Guid.Empty);
}
@ -93,7 +94,7 @@ public class Options
if (!Textures.TryGetValue(guid, out texture) && o.GetFirstMip() is { } mip)
{
TextureDecoder.DecodeTexture(mip, o.Format, o.isNormalMap, _platform, out var data, out _);
if (fix) FixChannels(o, mip, ref data);
if (fix) TextureHelper.FixChannels(o, mip, ref data);
texture = new Texture(data, mip.SizeX, mip.SizeY, o);
Textures[guid] = texture;
@ -101,97 +102,6 @@ public class Options
return texture != null;
}
/// <summary>
/// Red : Specular (if possible)
/// Blue : Roughness
/// Green : Metallic
/// </summary>
private void FixChannels(UTexture2D o, FTexture2DMipMap mip, ref byte[] data)
{
// only if it makes a big difference pls
switch (_game)
{
case "hk_project":
case "gameface":
case "divineknockout":
{
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // RBG
offset += 4;
}
}
}
break;
}
// R: Roughness
// G: Metallic
// B: Whatever (AO / S / E / ...)
case "ccff7r":
{
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // RBG
(d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // BRG
offset += 4;
}
}
}
break;
}
case "shootergame":
{
var packedPBRType = o.Name[(o.Name.LastIndexOf('_') + 1)..];
switch (packedPBRType)
{
case "MRAE": // R: Metallic, G: Roughness, B: AO (0-127) & Emissive (128-255) (Character PBR)
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // RMAE
// (d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // AEMR
offset += 4;
}
}
}
break;
case "MRAS": // R: Metallic, G: Roughness, B: AO, A: Specular (Legacy PBR)
case "MRA": // R: Metallic, G: 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]); // SRM
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // SMR
offset += 4;
}
}
}
break;
}
break;
}
}
}
public bool TryGetModel(out Model model) => Models.TryGetValue(SelectedModel, out model);
public bool TryGetModel(FGuid guid, out Model model) => Models.TryGetValue(guid, out model);

View File

@ -15,6 +15,11 @@ using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.Engine;
using CUE4Parse.UE4.Objects.UObject;
using FModel.Settings;
using FModel.Views.Snooper.Buffers;
using FModel.Views.Snooper.Lights;
using FModel.Views.Snooper.Models;
using FModel.Views.Snooper.Models.Animations;
using FModel.Views.Snooper.Shading;
namespace FModel.Views.Snooper;

View File

@ -6,10 +6,11 @@ using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Objects.Core.Math;
using CUE4Parse.UE4.Objects.Core.Misc;
using FModel.Views.Snooper.Models;
using ImGuiNET;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Shading;
public class Material : IDisposable
{
@ -62,7 +63,7 @@ public class Material : IDisposable
public void SwapMaterial(UMaterialInterface unrealMaterial)
{
Name = unrealMaterial.Name;
unrealMaterial.GetParams(Parameters);
unrealMaterial.GetParams(Parameters, EMaterialFormat.AllLayers);
}
public void Setup(Options options, int uvCount)
@ -92,7 +93,7 @@ public class Material : IDisposable
EmissiveColor = FillColors(uvCount, Emissive, CMaterialParams2.EmissiveColors, Vector4.One);
}
{ // scalars
{ // ambient occlusion + color boost
if (Parameters.TryGetTexture2d(out var original, "M", "AEM", "AO") &&
!original.Name.Equals("T_BlackMask") && options.TryGetTexture(original, false, out var transformed))
{
@ -105,6 +106,7 @@ public class Material : IDisposable
}
}
// scalars
if (Parameters.TryGetScalar(out var specular, "Specular", "Specular Intensity", "Spec"))
Specular = specular;
@ -119,15 +121,15 @@ public class Material : IDisposable
else if (Parameters.TryGetLinearColor(out var emissiveMultColor, "Emissive Multiplier", "EmissiveMultiplier"))
EmissiveMult = emissiveMultColor.R;
if (Parameters.TryGetScalar(out var uvScale, "UV Scale"))
UVScale = uvScale;
if (Parameters.TryGetLinearColor(out var EmissiveUVs,
"EmissiveUVs_RG_UpperLeftCorner_BA_LowerRightCorner",
"Emissive Texture UVs RG_TopLeft BA_BottomRight",
"Emissive 2 UV Positioning (RG)UpperLeft (BA)LowerRight",
"EmissiveUVPositioning (RG)UpperLeft (BA)LowerRight"))
EmissiveRegion = new Vector4(EmissiveUVs.R, EmissiveUVs.G, EmissiveUVs.B, EmissiveUVs.A);
if (Parameters.TryGetScalar(out var uvScale, "UV Scale"))
UVScale = uvScale;
}
}
}

View File

@ -5,7 +5,7 @@ using System.Numerics;
using System.Reflection;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Shading;
public class Shader : IDisposable
{

View File

@ -7,7 +7,7 @@ using OpenTK.Graphics.OpenGL4;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace FModel.Views.Snooper;
namespace FModel.Views.Snooper.Shading;
public class Texture : IDisposable
{

View File

@ -0,0 +1,99 @@
using CUE4Parse.UE4.Assets.Exports.Texture;
namespace FModel.Views.Snooper.Shading;
public static class TextureHelper
{
private static readonly string _game = Services.ApplicationService.ApplicationView.CUE4Parse.Provider.GameName;
/// <summary>
/// Red : Specular (if possible)
/// Blue : Roughness
/// Green : Metallic
/// </summary>
public static void FixChannels(UTexture2D o, FTexture2DMipMap mip, ref byte[] data)
{
// only if it makes a big difference pls
switch (_game)
{
case "hk_project":
case "gameface":
case "divineknockout":
{
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // RBG
offset += 4;
}
}
}
break;
}
// R: Roughness
// G: Metallic
// B: Whatever (AO / S / E / ...)
case "ccff7r":
{
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // RBG
(d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // BRG
offset += 4;
}
}
}
break;
}
case "shootergame":
{
var packedPBRType = o.Name[(o.Name.LastIndexOf('_') + 1)..];
switch (packedPBRType)
{
case "MRAE": // R: Metallic, G: Roughness, B: AO (0-127) & Emissive (128-255) (Character PBR)
unsafe
{
var offset = 0;
fixed (byte* d = data)
{
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
{
(d[offset], d[offset + 1]) = (d[offset + 1], d[offset]); // RMAE
// (d[offset], d[offset + 2]) = (d[offset + 2], d[offset]); // AEMR
offset += 4;
}
}
}
break;
case "MRAS": // R: Metallic, G: Roughness, B: AO, A: Specular (Legacy PBR)
case "MRA": // R: Metallic, G: 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]); // SRM
(d[offset + 1], d[offset + 2]) = (d[offset + 2], d[offset + 1]); // SMR
offset += 4;
}
}
}
break;
}
break;
}
}
}
}

View File

@ -8,6 +8,8 @@ using OpenTK.Windowing.Common;
using System.Numerics;
using System.Text;
using FModel.Settings;
using FModel.Views.Snooper.Models;
using FModel.Views.Snooper.Shading;
using OpenTK.Graphics.OpenGL4;
namespace FModel.Views.Snooper;
@ -269,13 +271,9 @@ public class SnimGui
Modal("About Snooper", ImGui.MenuItem("About"), () =>
{
ImGui.TextWrapped(
@"WROTE AT 3AM FOR THE SAKE OF TESTING AN ABOUT MODAL
@"Snooper, an ""OpenGL x ImGui"" based 3D viewer, is the result of months of work in order to improve our last one and open up the capabilities data-mining offers. For too long, softwares including FModel were only focused on a bare minimum level of detail showed to the end-user. This is the first step of a long and painful transition to make FModel a viable open-source tool to deep dive into Unreal Engine, its structure, and show how things work internally.
Snooper, an ""OpenGL x ImGui"" based 3D viewer, is the result of months of work in order to improve our last one and open up the capabilities data-mining offers. For too long, softwares including FModel were only focused on a bare minimum level of detail showed to the end-user. This is the first step of a long and painful transition to make FModel a viable open-source tool to deep dive into Unreal Engine, its structure, and show how things work internally.
Snooper aims to give an accurate preview of models, materials, animations, particles, levels, and sequences (oof) while keeping it compatible with most UE games. This is not an easy task AT ALL, in fact, I don't really know if everything will make out, but what I can say is that we have ideas and a vision for the future of FModel.
hello world!
Snooper aims to give an accurate preview of models, materials, skeletal animations, particles, levels, and level animations (oof) while keeping it compatible with most UE games. This is not an easy task AT ALL, in fact, I don't really know if everything will make out, but what I can say is that we have ideas and a vision for the future of FModel.
");
ImGui.Separator();

View File

@ -1,14 +1,19 @@
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using CUE4Parse.UE4.Assets.Exports;
using FModel.Views.Snooper.Buffers;
using ImGuiNET;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Common.Input;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
namespace FModel.Views.Snooper;
@ -75,6 +80,22 @@ public class Snooper : GameWindow
});
}
private unsafe void LoadWindowIcon()
{
var info = Application.GetResourceStream(new Uri($"/FModel;component/Resources/engine.png", UriKind.Relative));
using var img = SixLabors.ImageSharp.Image.Load<Rgba32>(info.Stream);
var memoryGroup = img.GetPixelMemoryGroup();
Memory<byte> array = new byte[memoryGroup.TotalLength * sizeof(Rgba32)];
var block = MemoryMarshal.Cast<byte, Rgba32>(array.Span);
foreach (var memory in memoryGroup)
{
memory.Span.CopyTo(block);
block = block[memory.Length..];
}
Icon = new WindowIcon(new OpenTK.Windowing.Common.Input.Image(img.Width, img.Height, array.ToArray()));
}
protected override void OnLoad()
{
if (_init)
@ -85,6 +106,7 @@ public class Snooper : GameWindow
base.OnLoad();
CenterWindow();
LoadWindowIcon();
GL.ClearColor(OpenTK.Mathematics.Color4.Black);
GL.Enable(EnableCap.Blend);