mirror of
https://github.com/4sval/FModel.git
synced 2026-04-16 06:26:40 -05:00
Merge branch 'dev' of https://github.com/4sval/FModel into dev
This commit is contained in:
commit
cdc987b984
|
|
@ -101,20 +101,8 @@ public class BaseCommunity : BaseIcon
|
|||
{
|
||||
if (!bShort) return base.GetCosmeticSeason(seasonNumber);
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var number = int.Parse(s);
|
||||
|
||||
switch (number)
|
||||
{
|
||||
case 10:
|
||||
s = "X";
|
||||
break;
|
||||
case > 18:
|
||||
number += 2;
|
||||
s = number.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
return $"C{number / 10 + 1} S{s[^1..]}";
|
||||
(int chapterIdx, int seasonIdx) = GetInternalSID(int.Parse(s));
|
||||
return $"C{chapterIdx} S{seasonIdx}";
|
||||
}
|
||||
|
||||
private new void DrawBackground(SKCanvas c)
|
||||
|
|
|
|||
|
|
@ -193,15 +193,18 @@ public class BaseIcon : UCreator
|
|||
return string.Format(format, name);
|
||||
}
|
||||
|
||||
protected string GetCosmeticSeason(string seasonNumber)
|
||||
protected (int, int) GetInternalSID(int number)
|
||||
{
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var initial = int.Parse(s);
|
||||
var number = initial;
|
||||
static int GetSeasonsInChapter(int chapter) => chapter switch
|
||||
{
|
||||
1 => 10,
|
||||
2 => 8,
|
||||
3 => 4,
|
||||
_ => 10
|
||||
};
|
||||
|
||||
var chapterIdx = 0;
|
||||
var seasonIdx = 0;
|
||||
|
||||
while (number > 0)
|
||||
{
|
||||
var seasonsInChapter = GetSeasonsInChapter(++chapterIdx);
|
||||
|
|
@ -213,14 +216,14 @@ public class BaseIcon : UCreator
|
|||
number = 0;
|
||||
}
|
||||
}
|
||||
return (chapterIdx, seasonIdx);
|
||||
}
|
||||
|
||||
static int GetSeasonsInChapter(int chapter) => chapter switch
|
||||
{
|
||||
1 => 10,
|
||||
2 => 8,
|
||||
3 => 4,
|
||||
_ => 10
|
||||
};
|
||||
protected string GetCosmeticSeason(string seasonNumber)
|
||||
{
|
||||
var s = seasonNumber["Cosmetics.Filter.Season.".Length..];
|
||||
var initial = int.Parse(s);
|
||||
(int chapterIdx, int seasonIdx) = GetInternalSID(initial);
|
||||
|
||||
var season = Utils.GetLocalizedResource("AthenaSeasonItemDefinitionInternal", "SeasonTextFormat", "Season {0}");
|
||||
var introduced = Utils.GetLocalizedResource("Fort.Cosmetics", "CosmeticItemDescription_Season", "\nIntroduced in <SeasonText>{0}</>.");
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public class CreatorPackage : IDisposable
|
|||
case "FortPlaysetPropItemDefinition":
|
||||
case "FortHomebaseNodeItemDefinition":
|
||||
case "FortNeverPersistItemDefinition":
|
||||
case "FortPlayerAugmentItemDefinition":
|
||||
case "RadioContentSourceItemDefinition":
|
||||
case "FortPlaysetGrenadeItemDefinition":
|
||||
case "FortPersonalVehicleItemDefinition":
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Export Raw Data" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem Header="Export Raw Data (.uasset)" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Export_Data" />
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Property" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem Header="Save Property (.json)" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Properties" />
|
||||
|
|
@ -124,10 +124,10 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Texture" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem Header="Save Texture (.png)" Command="{Binding RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Texture" />
|
||||
<Binding Source="Assets_Save_Textures" />
|
||||
<Binding Path="SelectedItems" ElementName="AssetsListName" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
|
|
@ -139,24 +139,8 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Auto">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.AccentForegroundBrush}}" Data="{StaticResource StatusBarIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
<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="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>
|
||||
<MenuItem Header="Auto Open Sounds" IsCheckable="True" StaysOpenOnClick="True"
|
||||
IsChecked="{Binding IsAutoOpenSounds, Source={x:Static local:Settings.UserSettings.Default}}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Views">
|
||||
<MenuItem Header="3D Viewer" Command="{Binding MenuCommand}" CommandParameter="Views_3dViewer">
|
||||
|
|
@ -400,7 +384,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Export Folder's Packages Raw Data" Click="OnFolderExportClick">
|
||||
<MenuItem Header="Export Folder's Packages Raw Data (.uasset)" Click="OnFolderExportClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -409,7 +393,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Properties" Click="OnFolderSaveClick">
|
||||
<MenuItem Header="Save Folder's Packages Properties (.json)" Click="OnFolderSaveClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
|
|
@ -418,6 +402,15 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Folder's Packages Textures (.png)" Click="OnFolderTextureClick">
|
||||
<MenuItem.Icon>
|
||||
<Viewbox Width="16" Height="16">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Path Fill="{DynamicResource {x:Static adonisUi:Brushes.ForegroundBrush}}" Data="{StaticResource TextureIcon}" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Save Directory" Click="OnSaveDirectoryClick">
|
||||
<MenuItem.Icon>
|
||||
|
|
@ -528,7 +521,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Export Raw Data" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem Header="Export Raw Data (.uasset)" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Export_Data" />
|
||||
|
|
@ -543,7 +536,7 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Properties" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem Header="Save Properties (.json)" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Properties" />
|
||||
|
|
@ -558,10 +551,10 @@
|
|||
</Viewbox>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Save Texture" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem Header="Save Texture (.png)" Command="{Binding DataContext.RightClickMenuCommand}">
|
||||
<MenuItem.CommandParameter>
|
||||
<MultiBinding Converter="{x:Static converters:MultiParameterConverter.Instance}">
|
||||
<Binding Source="Assets_Save_Texture" />
|
||||
<Binding Source="Assets_Save_Textures" />
|
||||
<Binding Path="SelectedItems" />
|
||||
</MultiBinding>
|
||||
</MenuItem.CommandParameter>
|
||||
|
|
@ -803,32 +796,6 @@
|
|||
</Viewbox>
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Save Properties Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoSaveProps, 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="PRP" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Save Textures Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAutoSaveTextures, 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="TEX" />
|
||||
</StatusBarItem>
|
||||
|
||||
<StatusBarItem Width="30" HorizontalContentAlignment="Stretch" ToolTip="Auto Open Sounds Enabled">
|
||||
<StatusBarItem.Style>
|
||||
<Style TargetType="StatusBarItem">
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@ public partial class MainWindow
|
|||
|
||||
public MainWindow()
|
||||
{
|
||||
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("AutoOpenSounds", typeof(MainWindow), new InputGestureCollection { new KeyGesture(UserSettings.Default.AutoOpenSounds.Key, UserSettings.Default.AutoOpenSounds.Modifiers) }), OnAutoTriggerExecuted));
|
||||
CommandBindings.Add(new CommandBinding(new RoutedCommand("ReloadMappings", typeof(MainWindow), new InputGestureCollection { new KeyGesture(Key.F12) }), OnMappingsReload));
|
||||
CommandBindings.Add(new CommandBinding(ApplicationCommands.Find, (_, _) => OnOpenAvalonFinder()));
|
||||
|
||||
|
|
@ -143,22 +140,6 @@ public partial class MainWindow
|
|||
await _applicationView.CUE4Parse.InitMappings();
|
||||
}
|
||||
|
||||
private void OnAutoTriggerExecuted(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
switch ((e.Command as RoutedCommand)?.Name)
|
||||
{
|
||||
case "AutoSaveProps":
|
||||
UserSettings.Default.IsAutoSaveProps = !UserSettings.Default.IsAutoSaveProps;
|
||||
break;
|
||||
case "AutoSaveTextures":
|
||||
UserSettings.Default.IsAutoSaveTextures = !UserSettings.Default.IsAutoSaveTextures;
|
||||
break;
|
||||
case "AutoOpenSounds":
|
||||
UserSettings.Default.IsAutoOpenSounds = !UserSettings.Default.IsAutoOpenSounds;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOpenAvalonFinder()
|
||||
{
|
||||
_applicationView.CUE4Parse.TabControl.SelectedTab.HasSearchOpen = true;
|
||||
|
|
@ -205,6 +186,14 @@ public partial class MainWindow
|
|||
}
|
||||
}
|
||||
|
||||
private async void OnFolderTextureClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is TreeItem folder)
|
||||
{
|
||||
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.TextureFolder(cancellationToken, folder); });
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSaveDirectoryClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct Parameters
|
|||
AoParams Ao;
|
||||
bool HasAo;
|
||||
|
||||
float Specular;
|
||||
float Roughness;
|
||||
float EmissiveMult;
|
||||
float UVScale;
|
||||
|
|
@ -66,6 +67,7 @@ uniform Parameters uParameters;
|
|||
uniform Light uLights[MAX_LIGHT_COUNT];
|
||||
uniform int uNumLights;
|
||||
uniform int uNumTexCoords;
|
||||
uniform bool uHasVertexColors;
|
||||
uniform vec3 uViewPos;
|
||||
uniform vec3 uViewDir;
|
||||
uniform bool bVertexColors[6];
|
||||
|
|
@ -74,7 +76,7 @@ out vec4 FragColor;
|
|||
|
||||
int LayerToIndex()
|
||||
{
|
||||
return min(int(fTexLayer), uNumTexCoords - 1);
|
||||
return clamp(int(fTexLayer), 0, uNumTexCoords - 1);
|
||||
}
|
||||
|
||||
vec4 SamplerToVector(sampler2D s)
|
||||
|
|
@ -94,54 +96,54 @@ vec3 ComputeNormals(int layer)
|
|||
return normalize(tbn * normal);
|
||||
}
|
||||
|
||||
vec3 schlickFresnel(int layer, float vDotH)
|
||||
vec3 schlickFresnel(vec3 fLambert, float metallic, float hDotv)
|
||||
{
|
||||
vec3 f0 = vec3(0.04f);
|
||||
return f0 + (1.0f - f0) * pow(clamp(1.0f - vDotH, 0.0f, 1.0f), 5);
|
||||
vec3 f0 = vec3(0.04);
|
||||
f0 = mix(f0, fLambert, metallic);
|
||||
return f0 + (1.0 - f0) * pow(clamp(1.0 - hDotv, 0.0, 1.0), 5);
|
||||
}
|
||||
|
||||
float ggxDistribution(float roughness, float nDoth)
|
||||
{
|
||||
float alpha2 = roughness * roughness * roughness * roughness;
|
||||
float d = nDoth * nDoth * (alpha2- 1.0f) + 1.0f;
|
||||
float d = nDoth * nDoth * (alpha2- 1.0) + 1.0;
|
||||
return alpha2 / (PI * d * d);
|
||||
}
|
||||
|
||||
float geomSmith(float roughness, float dp)
|
||||
{
|
||||
float k = (roughness + 1.0f) * (roughness + 1.0f) / 8.0f;
|
||||
float denom = dp * (1.0f - k) + k;
|
||||
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
|
||||
float denom = dp * (1.0 - k) + k;
|
||||
return dp / denom;
|
||||
}
|
||||
|
||||
vec3 CalcCameraLight(int layer, vec3 normals)
|
||||
{
|
||||
vec3 fLambert = SamplerToVector(uParameters.Diffuse[layer].Sampler).rgb * uParameters.Diffuse[layer].Color.rgb;
|
||||
vec3 specular_masks = SamplerToVector(uParameters.SpecularMasks[layer].Sampler).rgb;
|
||||
float roughness = max(0.0f, mix(specular_masks.r, specular_masks.b, uParameters.Roughness));
|
||||
float roughness = max(0.0f, specular_masks.b * uParameters.Roughness);
|
||||
|
||||
vec3 intensity = vec3(1.0f) * 1.0f;
|
||||
vec3 intensity = vec3(1.0f) * 1.0;
|
||||
vec3 l = -uViewDir;
|
||||
|
||||
vec3 n = normals;
|
||||
vec3 v = normalize(uViewPos - fPos);
|
||||
vec3 h = normalize(v + l);
|
||||
|
||||
float nDotH = max(dot(n, h), 0.0f);
|
||||
float vDotH = max(dot(v, h), 0.0f);
|
||||
float nDotL = max(dot(n, l), 0.0f);
|
||||
float nDotV = max(dot(n, v), 0.0f);
|
||||
float nDotH = max(dot(n, h), 0.0);
|
||||
float hDotv = max(dot(h, v), 0.0);
|
||||
float nDotL = max(dot(n, l), 0.0);
|
||||
float nDotV = max(dot(n, v), 0.0);
|
||||
|
||||
vec3 f = schlickFresnel(layer, vDotH);
|
||||
vec3 f = schlickFresnel(fLambert, specular_masks.g, hDotv);
|
||||
|
||||
vec3 kS = f;
|
||||
vec3 kD = 1.0 - kS;
|
||||
kD *= max(0.0f, dot(v, reflect(-v, normals)) * specular_masks.g);
|
||||
kD *= 1.0 - specular_masks.g;
|
||||
|
||||
vec3 specBrdfNom = ggxDistribution(roughness, nDotH) * f * geomSmith(roughness, nDotL) * geomSmith(roughness, nDotV);
|
||||
float specBrdfDenom = 4.0f * nDotV * nDotL + 0.0001f;
|
||||
vec3 specBrdf = specBrdfNom / specBrdfDenom;
|
||||
|
||||
vec3 fLambert = SamplerToVector(uParameters.Diffuse[layer].Sampler).rgb * uParameters.Diffuse[layer].Color.rgb;
|
||||
vec3 specBrdfNom = ggxDistribution(roughness, nDotH) * geomSmith(roughness, nDotL) * geomSmith(roughness, nDotV) * f;
|
||||
float specBrdfDenom = 4.0 * nDotV * nDotL + 0.0001;
|
||||
vec3 specBrdf = uParameters.Specular * specular_masks.r * specBrdfNom / specBrdfDenom;
|
||||
|
||||
vec3 diffuseBrdf = kD * fLambert / PI;
|
||||
return (diffuseBrdf + specBrdf) * intensity * nDotL;
|
||||
|
|
@ -149,7 +151,7 @@ vec3 CalcCameraLight(int layer, vec3 normals)
|
|||
|
||||
void main()
|
||||
{
|
||||
if (bVertexColors[2])
|
||||
if (bVertexColors[2] && uHasVertexColors)
|
||||
{
|
||||
FragColor = fColor;
|
||||
}
|
||||
|
|
@ -215,7 +217,7 @@ void main()
|
|||
result *= lights; // use * to darken the scene, + to lighten it
|
||||
}
|
||||
|
||||
result = result / (result + vec3(1.0f));
|
||||
FragColor = vec4(pow(result, vec3(1.0f / 2.2f)), 1.0f);
|
||||
result = result / (result + vec3(1.0));
|
||||
FragColor = vec4(pow(result, vec3(1.0 / 2.2)), 1.0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,20 +112,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _lastOpenedSettingTab, value);
|
||||
}
|
||||
|
||||
private bool _isAutoSaveProps;
|
||||
public bool IsAutoSaveProps
|
||||
{
|
||||
get => _isAutoSaveProps;
|
||||
set => SetProperty(ref _isAutoSaveProps, value);
|
||||
}
|
||||
|
||||
private bool _isAutoSaveTextures;
|
||||
public bool IsAutoSaveTextures
|
||||
{
|
||||
get => _isAutoSaveTextures;
|
||||
set => SetProperty(ref _isAutoSaveTextures, value);
|
||||
}
|
||||
|
||||
private bool _isAutoOpenSounds = true;
|
||||
public bool IsAutoOpenSounds
|
||||
{
|
||||
|
|
@ -557,27 +543,6 @@ namespace FModel.Settings
|
|||
set => SetProperty(ref _assetRemoveTab, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoSaveProps = new(Key.F1);
|
||||
public Hotkey AutoSaveProps
|
||||
{
|
||||
get => _autoSaveProps;
|
||||
set => SetProperty(ref _autoSaveProps, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoSaveTextures = new(Key.F2);
|
||||
public Hotkey AutoSaveTextures
|
||||
{
|
||||
get => _autoSaveTextures;
|
||||
set => SetProperty(ref _autoSaveTextures, value);
|
||||
}
|
||||
|
||||
private Hotkey _autoOpenSounds = new(Key.F3);
|
||||
public Hotkey AutoOpenSounds
|
||||
{
|
||||
get => _autoOpenSounds;
|
||||
set => SetProperty(ref _autoOpenSounds, value);
|
||||
}
|
||||
|
||||
private Hotkey _addAudio = new(Key.N, ModifierKeys.Control);
|
||||
public Hotkey AddAudio
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ public class EpicApiEndpoint : AbstractApiProvider
|
|||
if (string.IsNullOrEmpty(UserSettings.Default.LastAuthResponse.AccessToken)) return true;
|
||||
var request = new FRestRequest("https://account-public-service-prod.ol.epicgames.com/account/api/oauth/verify");
|
||||
request.AddHeader("Authorization", $"bearer {UserSettings.Default.LastAuthResponse.AccessToken}");
|
||||
var response = await _client.ExecuteAsync(request).ConfigureAwait(false);
|
||||
return response.StatusCode != HttpStatusCode.OK;
|
||||
var response = await _client.ExecuteGetAsync(request).ConfigureAwait(false);
|
||||
return !response.IsSuccessful;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -488,56 +488,6 @@ public class CUE4ParseViewModel : ViewModel
|
|||
});
|
||||
}
|
||||
|
||||
public void ExtractFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
{
|
||||
foreach (var asset in folder.AssetsList.Assets)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in folder.Folders) ExtractFolder(cancellationToken, f);
|
||||
}
|
||||
|
||||
public void ExportFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
{
|
||||
foreach (var asset in folder.AssetsList.Assets)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ExportData(asset.FullPath);
|
||||
}
|
||||
|
||||
foreach (var f in folder.Folders) ExportFolder(cancellationToken, f);
|
||||
}
|
||||
|
||||
public void SaveFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
{
|
||||
foreach (var asset in folder.AssetsList.Assets)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in folder.Folders) SaveFolder(cancellationToken, f);
|
||||
}
|
||||
|
||||
public void ExtractSelected(CancellationToken cancellationToken, IEnumerable<AssetItem> assetItems)
|
||||
{
|
||||
foreach (var asset in assetItems)
|
||||
|
|
@ -548,7 +498,41 @@ public class CUE4ParseViewModel : ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
public void Extract(CancellationToken cancellationToken, string fullPath, bool addNewTab = false, bool bulkSave = false)
|
||||
private void BulkFolder(CancellationToken cancellationToken, TreeItem folder, Action<AssetItem> action)
|
||||
{
|
||||
foreach (var asset in folder.AssetsList.Assets)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
action(asset);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in folder.Folders) BulkFolder(cancellationToken, f, action);
|
||||
}
|
||||
|
||||
public void ExportFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
=> BulkFolder(cancellationToken, folder, asset => ExportData(asset.FullPath));
|
||||
|
||||
public void ExtractFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs));
|
||||
|
||||
public void SaveFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
=> BulkFolder(cancellationToken, folder, asset => Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs, true));
|
||||
|
||||
public void TextureFolder(CancellationToken cancellationToken, TreeItem folder)
|
||||
=> BulkFolder(cancellationToken, folder, asset =>
|
||||
{
|
||||
Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs, false, true);
|
||||
});
|
||||
|
||||
public void Extract(CancellationToken cancellationToken, string fullPath, bool addNewTab = false, bool bulkSave = false, bool bulkTexture = false)
|
||||
{
|
||||
Log.Information("User DOUBLE-CLICKED to extract '{FullPath}'", fullPath);
|
||||
|
||||
|
|
@ -581,7 +565,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
|
||||
foreach (var e in exports)
|
||||
{
|
||||
if (CheckExport(cancellationToken, e))
|
||||
if (CheckExport(cancellationToken, e, bulkTexture))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -691,7 +675,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
if (Provider.TrySaveAsset(fullPath, out var data))
|
||||
{
|
||||
using var stream = new MemoryStream(data) { Position = 0 };
|
||||
TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, SKBitmap.Decode(stream));
|
||||
TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, SKBitmap.Decode(stream), bulkTexture);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -711,7 +695,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
canvas.DrawPicture(svg.Picture, paint);
|
||||
}
|
||||
|
||||
TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, bitmap);
|
||||
TabControl.SelectedTab.AddImage(fileName.SubstringBeforeLast("."), false, bitmap, bulkTexture);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -759,11 +743,11 @@ public class CUE4ParseViewModel : ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
private bool CheckExport(CancellationToken cancellationToken, UObject export) // return true once you wanna stop searching for exports
|
||||
private bool CheckExport(CancellationToken cancellationToken, UObject export, bool bulkTexture = false) // return true once you wanna stop searching for exports
|
||||
{
|
||||
switch (export)
|
||||
{
|
||||
case USolarisDigest solarisDigest:
|
||||
case USolarisDigest solarisDigest when !bulkTexture:
|
||||
{
|
||||
if (!TabControl.CanAddTabs) return false;
|
||||
|
||||
|
|
@ -774,11 +758,11 @@ public class CUE4ParseViewModel : ViewModel
|
|||
}
|
||||
case UTexture2D texture:
|
||||
{
|
||||
TabControl.SelectedTab.AddImage(texture);
|
||||
TabControl.SelectedTab.AddImage(texture, bulkTexture);
|
||||
return false;
|
||||
}
|
||||
case UAkMediaAssetData:
|
||||
case USoundWave:
|
||||
case UAkMediaAssetData when !bulkTexture:
|
||||
case USoundWave when !bulkTexture:
|
||||
{
|
||||
var shouldDecompress = UserSettings.Default.CompressedAudioMode == ECompressedAudio.PlayDecompressed;
|
||||
export.Decode(shouldDecompress, out var audioFormat, out var data);
|
||||
|
|
@ -788,10 +772,10 @@ public class CUE4ParseViewModel : ViewModel
|
|||
SaveAndPlaySound(Path.Combine(TabControl.SelectedTab.Directory, TabControl.SelectedTab.Header.SubstringBeforeLast('.')).Replace('\\', '/'), audioFormat, data);
|
||||
return false;
|
||||
}
|
||||
case UWorld when UserSettings.Default.PreviewWorlds:
|
||||
case UStaticMesh when UserSettings.Default.PreviewStaticMeshes:
|
||||
case USkeletalMesh when UserSettings.Default.PreviewSkeletalMeshes:
|
||||
case UMaterialInstance when UserSettings.Default.PreviewMaterials && !ModelIsOverwritingMaterial &&
|
||||
case UWorld when !bulkTexture && UserSettings.Default.PreviewWorlds:
|
||||
case UStaticMesh when !bulkTexture && UserSettings.Default.PreviewStaticMeshes:
|
||||
case USkeletalMesh when !bulkTexture && UserSettings.Default.PreviewSkeletalMeshes:
|
||||
case UMaterialInstance when !bulkTexture && 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))):
|
||||
|
|
@ -800,23 +784,23 @@ public class CUE4ParseViewModel : ViewModel
|
|||
SnooperViewer.Run();
|
||||
return true;
|
||||
}
|
||||
case UMaterialInstance m when ModelIsOverwritingMaterial:
|
||||
case UMaterialInstance m when !bulkTexture && ModelIsOverwritingMaterial:
|
||||
{
|
||||
SnooperViewer.Renderer.Swap(m);
|
||||
SnooperViewer.Run();
|
||||
return true;
|
||||
}
|
||||
case UAnimSequence a when ModelIsWaitingAnimation:
|
||||
case UAnimSequence a when !bulkTexture && ModelIsWaitingAnimation:
|
||||
{
|
||||
SnooperViewer.Renderer.Animate(a);
|
||||
SnooperViewer.Run();
|
||||
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.SaveAnimations:
|
||||
case UStaticMesh when !bulkTexture && UserSettings.Default.SaveStaticMeshes:
|
||||
case USkeletalMesh when !bulkTexture && UserSettings.Default.SaveSkeletalMeshes:
|
||||
case UMaterialInstance when !bulkTexture && UserSettings.Default.SaveMaterials:
|
||||
case USkeleton when !bulkTexture && UserSettings.Default.SaveSkeletonAsMesh:
|
||||
case UAnimSequence when !bulkTexture && UserSettings.Default.SaveAnimations:
|
||||
{
|
||||
SaveExport(export);
|
||||
return true;
|
||||
|
|
@ -827,7 +811,7 @@ public class CUE4ParseViewModel : ViewModel
|
|||
if (!package.TryConstructCreator(out var creator)) return false;
|
||||
|
||||
creator.ParseForInfo();
|
||||
TabControl.SelectedTab.AddImage(export.Name, false, creator.Draw());
|
||||
TabControl.SelectedTab.AddImage(export.Name, false, creator.Draw(), bulkTexture);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,12 +50,12 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
}
|
||||
|
||||
break;
|
||||
case "Assets_Save_Texture":
|
||||
case "Assets_Save_Textures":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath);
|
||||
contextViewModel.CUE4Parse.TabControl.SelectedTab.SaveImage(false);
|
||||
contextViewModel.CUE4Parse.TabControl.SelectedTab.SaveImages(false);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ public class GameSelectorViewModel : ViewModel
|
|||
yield return GetUnrealEngineGame("a99769d95d8f400baad1f67ab5dfe508");
|
||||
yield return GetUnrealEngineGame("Nebula");
|
||||
yield return GetUnrealEngineGame("711c5e95dc094ca58e5f16bd48e751d6");
|
||||
yield return GetUnrealEngineGame("9361c8c6d2f34b42b5f2f61093eedf48");
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ using System.Windows;
|
|||
using System.Windows.Media.Imaging;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace FModel.ViewModels;
|
||||
|
||||
|
|
@ -227,19 +228,20 @@ public class TabItem : ViewModel
|
|||
});
|
||||
}
|
||||
|
||||
public void AddImage(UTexture2D texture) => AddImage(texture.Name, texture.bRenderNearestNeighbor, texture.Decode(UserSettings.Default.OverridedPlatform));
|
||||
public void AddImage(UTexture2D texture, bool bulkTexture)
|
||||
=> AddImage(texture.Name, texture.bRenderNearestNeighbor, texture.Decode(UserSettings.Default.OverridedPlatform), bulkTexture);
|
||||
|
||||
public void AddImage(string name, bool rnn, SKBitmap[] img)
|
||||
public void AddImage(string name, bool rnn, SKBitmap[] img, bool bulkTexture)
|
||||
{
|
||||
foreach (var i in img) AddImage(name, rnn, i);
|
||||
foreach (var i in img) AddImage(name, rnn, i, bulkTexture);
|
||||
}
|
||||
|
||||
public void AddImage(string name, bool rnn, SKBitmap img)
|
||||
public void AddImage(string name, bool rnn, SKBitmap img, bool bulkTexture)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var t = new TabImage(name, rnn, img);
|
||||
if (UserSettings.Default.IsAutoSaveTextures)
|
||||
if (bulkTexture)
|
||||
SaveImage(t, true);
|
||||
|
||||
_images.Add(t);
|
||||
|
|
@ -259,7 +261,7 @@ public class TabItem : ViewModel
|
|||
Document ??= new TextDocument();
|
||||
Document.Text = text;
|
||||
|
||||
if (UserSettings.Default.IsAutoSaveProps || bulkSave)
|
||||
if (bulkSave)
|
||||
SaveProperty(true);
|
||||
});
|
||||
}
|
||||
|
|
@ -273,16 +275,43 @@ public class TabItem : ViewModel
|
|||
});
|
||||
}
|
||||
|
||||
public void SaveImage(bool autoSave) => SaveImage(SelectedImage, autoSave);
|
||||
public void SaveImages(bool bulkTexture)
|
||||
{
|
||||
if (_images.Count == 1)
|
||||
{
|
||||
SaveImage(bulkTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
private void SaveImage(TabImage image, bool autoSave)
|
||||
var directory = Path.Combine(UserSettings.Default.TextureDirectory,
|
||||
UserSettings.Default.KeepDirectoryStructure ? Directory : "").Replace('\\', '/');
|
||||
|
||||
if (!bulkTexture)
|
||||
{
|
||||
var folderBrowser = new VistaFolderBrowserDialog();
|
||||
if (folderBrowser.ShowDialog() == true)
|
||||
directory = folderBrowser.SelectedPath;
|
||||
else return;
|
||||
}
|
||||
else System.IO.Directory.CreateDirectory(directory);
|
||||
|
||||
foreach (var image in _images)
|
||||
{
|
||||
if (image == null) return;
|
||||
var fileName = $"{image.ExportName}.png";
|
||||
SaveImage(image, Path.Combine(directory, fileName), fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveImage(bool bulkTexture) => SaveImage(SelectedImage, bulkTexture);
|
||||
private void SaveImage(TabImage image, bool bulkTexture)
|
||||
{
|
||||
if (image == null) return;
|
||||
var fileName = $"{image.ExportName}.png";
|
||||
var directory = Path.Combine(UserSettings.Default.TextureDirectory,
|
||||
var path = Path.Combine(UserSettings.Default.TextureDirectory,
|
||||
UserSettings.Default.KeepDirectoryStructure ? Directory : "", fileName!).Replace('\\', '/');
|
||||
|
||||
if (!autoSave)
|
||||
if (!bulkTexture)
|
||||
{
|
||||
var saveFileDialog = new SaveFileDialog
|
||||
{
|
||||
|
|
@ -293,19 +322,23 @@ public class TabItem : ViewModel
|
|||
};
|
||||
var result = saveFileDialog.ShowDialog();
|
||||
if (!result.HasValue || !result.Value) return;
|
||||
directory = saveFileDialog.FileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(directory.SubstringBeforeLast('/'));
|
||||
path = saveFileDialog.FileName;
|
||||
}
|
||||
else System.IO.Directory.CreateDirectory(path.SubstringBeforeLast('/'));
|
||||
|
||||
using (var fs = new FileStream(directory, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
fs.Write(image.ImageBuffer, 0, image.ImageBuffer.Length);
|
||||
}
|
||||
SaveImage(image, path, fileName);
|
||||
}
|
||||
|
||||
SaveCheck(directory, fileName);
|
||||
private void SaveImage(TabImage image, string path, string fileName)
|
||||
{
|
||||
SaveImage(image, path);
|
||||
SaveCheck(path, fileName);
|
||||
}
|
||||
|
||||
private void SaveImage(TabImage image, string path)
|
||||
{
|
||||
using var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
fs.Write(image.ImageBuffer, 0, image.ImageBuffer.Length);
|
||||
}
|
||||
|
||||
public void SaveProperty(bool autoSave)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public class StringToGameConverter : IValueConverter
|
|||
"shoebill" => FGame.SwGame,
|
||||
"a99769d95d8f400baad1f67ab5dfe508" => FGame.Platform,
|
||||
"711c5e95dc094ca58e5f16bd48e751d6" => FGame.PandaGame,
|
||||
"9361c8c6d2f34b42b5f2f61093eedf48" => FGame.TslGame,
|
||||
381210 => FGame.DeadByDaylight,
|
||||
578080 => FGame.TslGame,
|
||||
677620 => FGame.PortalWars,
|
||||
|
|
|
|||
|
|
@ -420,10 +420,6 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<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" />
|
||||
|
|
@ -455,29 +451,17 @@
|
|||
|
||||
<Separator Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Auto Save Properties *" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<TextBlock Grid.Row="8" Grid.Column="0" Text="Add Audio File" 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 AutoSaveProps, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<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="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}" />
|
||||
|
||||
<Separator Grid.Row="11" Grid.Column="0" Grid.ColumnSpan="3" Style="{StaticResource CustomSeparator}" />
|
||||
|
||||
<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="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"
|
||||
<TextBlock Grid.Row="9" Grid.Column="0" Text="Play / Pause Current Audio" 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 PlayPauseAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
<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"
|
||||
<TextBlock Grid.Row="10" Grid.Column="0" Text="Previous Audio" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<controls:HotkeyTextBox Grid.Row="10" 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="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"
|
||||
<TextBlock Grid.Row="11" Grid.Column="0" Text="Next Audio" 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 NextAudio, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Numerics;
|
|||
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 ImGuiNET;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ public class Material : IDisposable
|
|||
public AoParams Ao;
|
||||
public bool HasAo;
|
||||
|
||||
public float Specular = 1f;
|
||||
public float Roughness = 0.5f;
|
||||
public float EmissiveMult = 1f;
|
||||
public float UVScale = 1f;
|
||||
|
|
@ -89,7 +91,7 @@ public class Material : IDisposable
|
|||
}
|
||||
|
||||
{ // scalars
|
||||
if (Parameters.TryGetTexture2d(out var original, "M", "PackedTexture", "AEM") &&
|
||||
if (Parameters.TryGetTexture2d(out var original, "M", "AEM", "AO") &&
|
||||
!original.Name.Equals("T_BlackMask") && options.TryGetTexture(original, false, out var transformed))
|
||||
{
|
||||
HasAo = true;
|
||||
|
|
@ -101,14 +103,19 @@ public class Material : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
if (Parameters.TryGetScalar(out var specular, "Specular", "Specular Intensity", "Spec"))
|
||||
Specular = specular;
|
||||
|
||||
if (Parameters.TryGetScalar(out var roughnessMin, "RoughnessMin", "SpecRoughnessMin") &&
|
||||
Parameters.TryGetScalar(out var roughnessMax, "RoughnessMax", "SpecRoughnessMax"))
|
||||
Roughness = (roughnessMin + roughnessMax) / 2f;
|
||||
if (Parameters.TryGetScalar(out var roughness, "Rough", "Roughness"))
|
||||
if (Parameters.TryGetScalar(out var roughness, "Rough", "Roughness", "Ro Multiplier", "RO_mul", "Roughness_Mult"))
|
||||
Roughness = roughness;
|
||||
|
||||
if (Parameters.TryGetScalar(out var emissiveMult, "emissive mult", "Emissive_Mult"))
|
||||
EmissiveMult = emissiveMult;
|
||||
if (Parameters.TryGetScalar(out var emissiveMultScalar, "emissive mult", "Emissive_Mult"))
|
||||
EmissiveMult = emissiveMultScalar;
|
||||
else if (Parameters.TryGetLinearColor(out var emissiveMultColor, "Emissive Multiplier", "EmissiveMultiplier"))
|
||||
EmissiveMult = emissiveMultColor.R;
|
||||
|
||||
if (Parameters.TryGetScalar(out var uvScale, "UV Scale"))
|
||||
UVScale = uvScale;
|
||||
|
|
@ -209,6 +216,7 @@ public class Material : IDisposable
|
|||
shader.SetUniform("uParameters.Ao.AmbientOcclusion", Ao.AmbientOcclusion);
|
||||
shader.SetUniform("uParameters.HasAo", HasAo);
|
||||
|
||||
shader.SetUniform("uParameters.Specular", Specular);
|
||||
shader.SetUniform("uParameters.Roughness", Roughness);
|
||||
shader.SetUniform("uParameters.EmissiveMult", EmissiveMult);
|
||||
shader.SetUniform("uParameters.UVScale", UVScale);
|
||||
|
|
@ -223,23 +231,25 @@ public class Material : IDisposable
|
|||
{
|
||||
if (ImGui.BeginTable("parameters", 2))
|
||||
{
|
||||
SnimGui.Layout("Roughness");ImGui.PushID(1);
|
||||
SnimGui.Layout("Specular");ImGui.PushID(1);
|
||||
ImGui.DragFloat("", ref Specular, _step, _zero, 1.0f, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("Roughness");ImGui.PushID(2);
|
||||
ImGui.DragFloat("", ref Roughness, _step, _zero, 1.0f, _mult, _clamp);
|
||||
SnimGui.Layout("Emissive Multiplier");ImGui.PushID(2);
|
||||
ImGui.PopID();SnimGui.Layout("Emissive Multiplier");ImGui.PushID(3);
|
||||
ImGui.DragFloat("", ref EmissiveMult, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();SnimGui.Layout("UV Scale");ImGui.PushID(3);
|
||||
ImGui.PopID();SnimGui.Layout("UV Scale");ImGui.PushID(4);
|
||||
ImGui.DragFloat("", ref UVScale, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();
|
||||
|
||||
if (HasAo)
|
||||
{
|
||||
SnimGui.Layout("Ambient Occlusion");ImGui.PushID(4);
|
||||
SnimGui.Layout("Ambient Occlusion");ImGui.PushID(5);
|
||||
ImGui.DragFloat("", ref Ao.AmbientOcclusion, _step, _zero, 1.0f, _mult, _clamp);ImGui.PopID();
|
||||
if (Ao.HasColorBoost)
|
||||
{
|
||||
SnimGui.Layout("Color Boost");ImGui.PushID(5);
|
||||
SnimGui.Layout("Color Boost");ImGui.PushID(6);
|
||||
ImGui.ColorEdit3("", ref Ao.ColorBoost.Color);ImGui.PopID();
|
||||
SnimGui.Layout("Color Boost Exponent");ImGui.PushID(6);
|
||||
SnimGui.Layout("Color Boost Exponent");ImGui.PushID(7);
|
||||
ImGui.DragFloat("", ref Ao.ColorBoost.Exponent, _step, _zero, _infinite, _mult, _clamp);
|
||||
ImGui.PopID();
|
||||
}
|
||||
|
|
@ -273,7 +283,7 @@ public class Material : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public void ImGuiTextures(Dictionary<string, Texture> icons, Model model)
|
||||
public bool ImGuiTextures(Dictionary<string, Texture> icons, Model model)
|
||||
{
|
||||
if (ImGui.BeginTable("material_textures", 2))
|
||||
{
|
||||
|
|
@ -300,21 +310,46 @@ public class Material : IDisposable
|
|||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
ImGui.Image(GetSelectedTexture() ?? icons["noimage"].GetPointer(),
|
||||
var texture = GetSelectedTexture() ?? icons["noimage"];
|
||||
ImGui.Image(texture.GetPointer(),
|
||||
new Vector2(ImGui.GetContentRegionAvail().X - ImGui.GetScrollX()),
|
||||
Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1.0f, 1.0f, 1.0f, 0.25f));
|
||||
ImGui.Spacing();
|
||||
return ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(ImGuiMouseButton.Left);
|
||||
}
|
||||
|
||||
private IntPtr? GetSelectedTexture()
|
||||
public Vector2[] ImGuiTextureInspector(Texture fallback)
|
||||
{
|
||||
var texture = GetSelectedTexture() ?? fallback;
|
||||
if (ImGui.BeginTable("texture_inspector", 2, ImGuiTableFlags.SizingStretchProp))
|
||||
{
|
||||
SnimGui.Layout("Type");ImGui.Text($" : ({texture.Format}) {texture.Name}");
|
||||
SnimGui.TooltipCopy("(?) Click to Copy Path", texture.Path);
|
||||
SnimGui.Layout("Guid");ImGui.Text($" : {texture.Guid.ToString(EGuidFormats.UniqueObjectGuid)}");
|
||||
SnimGui.Layout("Import");ImGui.Text($" : {texture.ImportedWidth}x{texture.ImportedHeight}");
|
||||
SnimGui.Layout("Export");ImGui.Text($" : {texture.Width}x{texture.Height}");
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
var largest = ImGui.GetContentRegionAvail();
|
||||
largest.X -= ImGui.GetScrollX();
|
||||
largest.Y -= ImGui.GetScrollY();
|
||||
|
||||
var ratio = Math.Min(largest.X / texture.Width, largest.Y / texture.Height);
|
||||
var size = new Vector2(texture.Width * ratio, texture.Height * ratio);
|
||||
var pos = ImGui.GetCursorPos();
|
||||
ImGui.Image(texture.GetPointer(),size, Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1.0f, 1.0f, 1.0f, 0.25f));
|
||||
return new[] { size, pos };
|
||||
}
|
||||
|
||||
private Texture GetSelectedTexture()
|
||||
{
|
||||
return SelectedTexture switch
|
||||
{
|
||||
0 => Diffuse[SelectedChannel]?.GetPointer(),
|
||||
1 => Normals[SelectedChannel]?.GetPointer(),
|
||||
2 => SpecularMasks[SelectedChannel]?.GetPointer(),
|
||||
3 => Ao.Texture?.GetPointer(),
|
||||
4 => Emissive[SelectedChannel]?.GetPointer(),
|
||||
0 => Diffuse[SelectedChannel],
|
||||
1 => Normals[SelectedChannel],
|
||||
2 => SpecularMasks[SelectedChannel],
|
||||
3 => Ao.Texture,
|
||||
4 => Emissive[SelectedChannel],
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ public class Model : IDisposable
|
|||
public void Setup(Options options)
|
||||
{
|
||||
_handle = GL.CreateProgram();
|
||||
var broken = GL.GetInteger(GetPName.MaxTextureUnits) == 0;
|
||||
|
||||
_ebo = new BufferObject<uint>(Indices, BufferTarget.ElementArrayBuffer);
|
||||
_vbo = new BufferObject<float>(Vertices, BufferTarget.ArrayBuffer);
|
||||
|
|
@ -221,7 +222,7 @@ public class Model : IDisposable
|
|||
_vao.VertexAttributePointer(2, 3, VertexAttribPointerType.Float, _vertexSize, 4); // normal
|
||||
_vao.VertexAttributePointer(3, 3, VertexAttribPointerType.Float, _vertexSize, 7); // tangent
|
||||
_vao.VertexAttributePointer(4, 2, VertexAttribPointerType.Float, _vertexSize, 10); // uv
|
||||
_vao.VertexAttributePointer(5, 1, VertexAttribPointerType.Float, _vertexSize, 12); // texture index
|
||||
if (!broken) _vao.VertexAttributePointer(5, 1, VertexAttribPointerType.Float, _vertexSize, 12); // texture index
|
||||
_vao.VertexAttributePointer(6, 4, VertexAttribPointerType.Float, _vertexSize, 13); // color
|
||||
_vao.VertexAttributePointer(7, 4, VertexAttribPointerType.Float, _vertexSize, 17); // boneids
|
||||
_vao.VertexAttributePointer(8, 4, VertexAttribPointerType.Float, _vertexSize, 21); // boneweights
|
||||
|
|
@ -232,7 +233,7 @@ public class Model : IDisposable
|
|||
for (var i = 0; i < Materials.Length; i++)
|
||||
{
|
||||
if (!Materials[i].IsUsed) continue;
|
||||
Materials[i].Setup(options, NumTexCoords);
|
||||
Materials[i].Setup(options, broken ? 1 : NumTexCoords);
|
||||
}
|
||||
|
||||
if (HasMorphTargets)
|
||||
|
|
@ -268,6 +269,7 @@ public class Model : IDisposable
|
|||
_vao.Bind();
|
||||
shader.SetUniform("uMorphTime", MorphTime);
|
||||
shader.SetUniform("uNumTexCoords", NumTexCoords);
|
||||
shader.SetUniform("uHasVertexColors", HasVertexColors);
|
||||
|
||||
GL.PolygonMode(MaterialFace.FrontAndBack, Wireframe ? PolygonMode.Line : PolygonMode.Fill);
|
||||
for (int section = 0; section < Sections.Length; section++)
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public class Options
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Red : Specular
|
||||
/// Red : Specular (if possible)
|
||||
/// Blue : Roughness
|
||||
/// Green : Metallic
|
||||
/// </summary>
|
||||
|
|
@ -112,6 +112,8 @@ public class Options
|
|||
switch (_game)
|
||||
{
|
||||
case "hk_project":
|
||||
case "gameface":
|
||||
case "divineknockout":
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
|
|
@ -120,13 +122,73 @@ public class Options
|
|||
{
|
||||
for (var i = 0; i < mip.SizeX * mip.SizeY; i++)
|
||||
{
|
||||
(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]); // 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
|
|
@ -258,27 +259,50 @@ public class Renderer : IDisposable
|
|||
else if (m.TryConvert(out var mesh))
|
||||
{
|
||||
model = new Model(m, mesh, t);
|
||||
if (actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
|
||||
if (actor.TryGetValue(out FPackageIndex baseMaterial, "BaseMaterial") &&
|
||||
actor.TryGetAllValues(out FPackageIndex[] textureData, "TextureData"))
|
||||
{
|
||||
for (int j = 0; j < textureData.Length; j++)
|
||||
var material = model.Materials.FirstOrDefault(x => x.Name == baseMaterial.Name);
|
||||
if (material is { IsUsed: true })
|
||||
{
|
||||
if (!model.Materials[model.Sections[j].MaterialIndex].IsUsed ||
|
||||
textureData[j].Load() is not { } textureDataIdx)
|
||||
continue;
|
||||
for (int j = 0; j < textureData.Length; j++)
|
||||
{
|
||||
var diffuse_key = j switch
|
||||
{
|
||||
0 => "Diffuse",
|
||||
> 0 => $"Diffuse_Texture_{j + 1}",
|
||||
_ => CMaterialParams2.FallbackDiffuse
|
||||
};
|
||||
var normal_key = j switch
|
||||
{
|
||||
0 => "Normals",
|
||||
> 0 => $"Normals_Texture_{j + 1}",
|
||||
_ => CMaterialParams2.FallbackNormals
|
||||
};
|
||||
var specularmasks_key = j switch
|
||||
{
|
||||
0 => "SpecularMasks",
|
||||
> 0 => $"SpecularMasks_{j + 1}",
|
||||
_ => CMaterialParams2.FallbackNormals
|
||||
};
|
||||
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex overrideMaterial, "OverrideMaterial") &&
|
||||
overrideMaterial.TryLoad(out var material) && material is UMaterialInterface unrealMaterial)
|
||||
model.Materials[model.Sections[j].MaterialIndex].SwapMaterial(unrealMaterial);
|
||||
if (textureData[j]?.Load() is not { } textureDataIdx)
|
||||
continue;
|
||||
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex diffuse, "Diffuse") &&
|
||||
diffuse.Load() is UTexture2D diffuseTexture)
|
||||
model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Diffuse[0][0]] = diffuseTexture;
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex normal, "Normal") &&
|
||||
normal.Load() is UTexture2D normalTexture)
|
||||
model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.Normals[0][0]] = normalTexture;
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex specular, "Specular") &&
|
||||
specular.Load() is UTexture2D specularTexture)
|
||||
model.Materials[model.Sections[j].MaterialIndex].Parameters.Textures[CMaterialParams2.SpecularMasks[0][0]] = specularTexture;
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex overrideMaterial, "OverrideMaterial") &&
|
||||
overrideMaterial.TryLoad(out var oMaterial) && oMaterial is UMaterialInterface oUnrealMaterial)
|
||||
material.SwapMaterial(oUnrealMaterial);
|
||||
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex diffuse, "Diffuse") &&
|
||||
diffuse.Load() is UTexture2D diffuseTexture)
|
||||
material.Parameters.Textures[diffuse_key] = diffuseTexture;
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex normal, "Normal") &&
|
||||
normal.Load() is UTexture2D normalTexture)
|
||||
material.Parameters.Textures[normal_key] = normalTexture;
|
||||
if (textureDataIdx.TryGetValue(out FPackageIndex specular, "Specular") &&
|
||||
specular.Load() is UTexture2D specularTexture)
|
||||
material.Parameters.Textures[specularmasks_key] = specularTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (staticMeshComp.TryGetValue(out FPackageIndex[] overrideMaterials, "OverrideMaterials"))
|
||||
|
|
|
|||
|
|
@ -30,25 +30,43 @@ public class Skeleton : IDisposable
|
|||
continue;
|
||||
|
||||
var transform = Transform.Identity;
|
||||
var matrix = Matrix4x4.Identity;
|
||||
while (boneIndex > -1)
|
||||
{
|
||||
var t = RefSkel.ReferenceSkeleton.FinalRefBonePose[boneIndex];
|
||||
transform.Position += t.Rotation.RotateVector(t.Translation.ToMapVector()) * Constants.SCALE_DOWN_RATIO;
|
||||
|
||||
var bone = RefSkel.ReferenceSkeleton.FinalRefBonePose[boneIndex];
|
||||
boneIndex = RefSkel.ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex;
|
||||
var parentBone = RefSkel.ReferenceSkeleton.FinalRefBonePose[boneIndex < 0 ? 0 : boneIndex];
|
||||
|
||||
var orig_loc = bone.Translation;
|
||||
parentBone.Rotation.Conjugate();
|
||||
orig_loc = parentBone.Rotation.RotateVector(orig_loc);
|
||||
|
||||
var orig_quat = bone.Rotation;
|
||||
orig_quat *= parentBone.Rotation;
|
||||
orig_quat.Conjugate();
|
||||
|
||||
var p_rotated = orig_quat * orig_loc;
|
||||
orig_quat.Conjugate();
|
||||
p_rotated *= orig_quat;
|
||||
|
||||
matrix *=
|
||||
Matrix4x4.CreateFromQuaternion(orig_quat) *
|
||||
Matrix4x4.CreateTranslation(p_rotated);
|
||||
|
||||
// Console.WriteLine(matrix.Translation);
|
||||
}
|
||||
// for (int j = 0; j <= 3; j++)
|
||||
// for (int j = 0; j <= boneIndex; j++)
|
||||
// {
|
||||
// var t = RefSkel.ReferenceSkeleton.FinalRefBonePose[j];
|
||||
// // var matrix = Matrix4x4.CreateScale(t.Scale3D.ToMapVector());
|
||||
// // matrix *= Matrix4x4.CreateFromQuaternion(t.Rotation);
|
||||
// transform.Position += t.Rotation.UnrotateVector(t.Translation.ToMapVector()) * Constants.SCALE_DOWN_RATIO;
|
||||
// var r = RefSkel.ReferenceSkeleton.FinalRefBonePose[j - (j == 0 ? 0 : 1)].Rotation;
|
||||
// r.Conjugate();
|
||||
// matrix *= Matrix4x4.CreateFromQuaternion(r) * Matrix4x4.CreateTranslation(t.Translation);
|
||||
//
|
||||
// // Console.WriteLine($@"{t.Translation}");
|
||||
// // transform.Relation *= matrix;
|
||||
// Console.WriteLine($@"{t.Translation}");
|
||||
// transform.Relation *= matrix;
|
||||
// }
|
||||
|
||||
Sockets[i] = new Socket(socket, transform);
|
||||
Sockets[i] = new Socket(socket, matrix.Translation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using FModel.Framework;
|
|||
using ImGuiNET;
|
||||
using OpenTK.Windowing.Common;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using FModel.Settings;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
|
|
@ -43,6 +44,8 @@ public class SnimGui
|
|||
private readonly Save _saver = new ();
|
||||
private readonly string _renderer;
|
||||
private readonly string _version;
|
||||
private bool _ti_open;
|
||||
private bool _ti_overlayUv;
|
||||
private bool _viewportFocus;
|
||||
|
||||
private readonly Vector4 _accentColor = new (0.125f, 0.42f, 0.831f, 1.0f);
|
||||
|
|
@ -75,6 +78,7 @@ public class SnimGui
|
|||
Draw3DViewport(s);
|
||||
DrawNavbar();
|
||||
|
||||
if (_ti_open) DrawTextureInspector(s);
|
||||
Controller.Render();
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +242,30 @@ public class SnimGui
|
|||
}
|
||||
});
|
||||
|
||||
Modal("GPU OpenGL Info", ImGui.MenuItem("GPU Info"), () =>
|
||||
{
|
||||
var s = new StringBuilder();
|
||||
s.AppendLine($"MaxTextureImageUnits: {GL.GetInteger(GetPName.MaxTextureImageUnits)}");
|
||||
s.AppendLine($"MaxTextureUnits: {GL.GetInteger(GetPName.MaxTextureUnits)}");
|
||||
s.AppendLine($"MaxVertexTextureImageUnits: {GL.GetInteger(GetPName.MaxVertexTextureImageUnits)}");
|
||||
s.AppendLine($"MaxCombinedTextureImageUnits: {GL.GetInteger(GetPName.MaxCombinedTextureImageUnits)}");
|
||||
s.AppendLine($"MaxGeometryTextureImageUnits: {GL.GetInteger(GetPName.MaxGeometryTextureImageUnits)}");
|
||||
s.AppendLine($"MaxTextureCoords: {GL.GetInteger(GetPName.MaxTextureCoords)}");
|
||||
s.AppendLine($"Renderer: {_renderer}");
|
||||
s.AppendLine($"Version: {_version}");
|
||||
ImGui.TextWrapped(s.ToString());
|
||||
ImGui.Separator();
|
||||
|
||||
var size = new Vector2(120, 0);
|
||||
ImGui.InvisibleButton("", size * 4);
|
||||
ImGui.SameLine();
|
||||
ImGui.SetItemDefaultFocus();
|
||||
if (ImGui.Button("OK", size))
|
||||
{
|
||||
ImGui.CloseCurrentPopup();
|
||||
}
|
||||
});
|
||||
|
||||
Modal("About Snooper", ImGui.MenuItem("About"), () =>
|
||||
{
|
||||
ImGui.TextWrapped(
|
||||
|
|
@ -556,9 +584,9 @@ hello world!
|
|||
}
|
||||
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
if (ImGui.CollapsingHeader("Textures"))
|
||||
if (ImGui.CollapsingHeader("Textures") && material.ImGuiTextures(icons, model))
|
||||
{
|
||||
material.ImGuiTextures(icons, model);
|
||||
_ti_open = true;
|
||||
}
|
||||
|
||||
ImGui.SetNextItemOpen(true, ImGuiCond.Appearing);
|
||||
|
|
@ -590,6 +618,32 @@ hello world!
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawTextureInspector(Snooper s)
|
||||
{
|
||||
if (ImGui.Begin("Texture Inspector", ref _ti_open, ImGuiWindowFlags.NoScrollbar) &&
|
||||
s.Renderer.Options.TryGetModel(out var model) &&
|
||||
s.Renderer.Options.TryGetSection(model, out var section))
|
||||
{
|
||||
var vectors = model.Materials[section.MaterialIndex].ImGuiTextureInspector(s.Renderer.Options.Icons["noimage"]);
|
||||
if (_ti_overlayUv)
|
||||
{
|
||||
var size = vectors[0];
|
||||
var drawList = ImGui.GetWindowDrawList();
|
||||
drawList.PushClipRect(size, size, true);
|
||||
ImGui.SetCursorPos(vectors[1]);
|
||||
ImGui.InvisibleButton("canvas", size, ImGuiButtonFlags.MouseButtonLeft | ImGuiButtonFlags.MouseButtonRight);
|
||||
drawList.AddLine(new Vector2(0, 0), size, 255, 2f);
|
||||
drawList.PopClipRect();
|
||||
}
|
||||
Popup(() =>
|
||||
{
|
||||
if (ImGui.MenuItem("Overlay UVs", null, _ti_overlayUv))
|
||||
_ti_overlayUv = !_ti_overlayUv;
|
||||
});
|
||||
}
|
||||
ImGui.End(); // if window is collapsed
|
||||
}
|
||||
|
||||
private void Draw3DViewport(Snooper s)
|
||||
{
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
|
|
@ -727,15 +781,15 @@ hello world!
|
|||
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
||||
}
|
||||
|
||||
public static void TooltipCopy(string name)
|
||||
public static void TooltipCopy(string label, string text = null)
|
||||
{
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.BeginTooltip();
|
||||
ImGui.Text(name);
|
||||
ImGui.Text(label);
|
||||
ImGui.EndTooltip();
|
||||
}
|
||||
if (ImGui.IsItemClicked()) ImGui.SetClipboardText(name);
|
||||
if (ImGui.IsItemClicked()) ImGui.SetClipboardText(text ?? label);
|
||||
}
|
||||
|
||||
private void Theme()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
using CUE4Parse.UE4.Assets.Exports.SkeletalMesh;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
|
||||
namespace FModel.Views.Snooper;
|
||||
|
||||
|
|
@ -19,6 +21,15 @@ public class Socket : IDisposable
|
|||
// Transform.Scale = socket.RelativeScale.ToMapVector();
|
||||
}
|
||||
|
||||
public Socket(USkeletalMeshSocket socket, Vector3 position)
|
||||
{
|
||||
Name = socket.SocketName.Text;
|
||||
Bone = socket.BoneName.Text;
|
||||
Transform = Transform.Identity;
|
||||
var pos = position /*+ socket.RelativeRotation.RotateVector(socket.RelativeLocation)*/;
|
||||
Transform.Position = new FVector(pos.X, pos.Z, pos.Y) * Constants.SCALE_DOWN_RATIO;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Windows;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
using CUE4Parse.UE4.Objects.Core.Misc;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
|
@ -15,6 +16,7 @@ public class Texture : IDisposable
|
|||
private readonly TextureTarget _target;
|
||||
|
||||
public readonly string Type;
|
||||
public readonly FGuid Guid;
|
||||
public readonly string Name;
|
||||
public readonly string Path;
|
||||
public readonly EPixelFormat Format;
|
||||
|
|
@ -22,7 +24,6 @@ public class Texture : IDisposable
|
|||
public readonly uint ImportedHeight;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public string Label;
|
||||
|
||||
public Texture(TextureType type)
|
||||
{
|
||||
|
|
@ -34,7 +35,8 @@ public class Texture : IDisposable
|
|||
TextureType.MsaaFramebuffer => TextureTarget.Texture2DMultisample,
|
||||
_ => TextureTarget.Texture2D
|
||||
};
|
||||
Label = "(?) Click to Copy Path";
|
||||
|
||||
Guid = new FGuid();
|
||||
}
|
||||
|
||||
public Texture(uint width, uint height) : this(TextureType.MsaaFramebuffer)
|
||||
|
|
@ -72,8 +74,9 @@ public class Texture : IDisposable
|
|||
public Texture(byte[] data, int width, int height, UTexture2D texture2D) : this(TextureType.Normal)
|
||||
{
|
||||
Type = texture2D.ExportType;
|
||||
Guid = texture2D.LightingGuid;
|
||||
Name = texture2D.Name;
|
||||
Path = texture2D.Owner?.Name;
|
||||
Path = texture2D.GetPathName();
|
||||
Format = texture2D.Format;
|
||||
ImportedWidth = texture2D.ImportedSize.X;
|
||||
ImportedHeight = texture2D.ImportedSize.Y;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user