mirror of
https://github.com/4sval/FModel.git
synced 2026-06-22 07:50:10 -05:00
added Bnk sound reader + xml/txt asset support + fixed FN 1.8 textures
This commit is contained in:
parent
a298cbf7e5
commit
2c3a05684e
|
|
@ -110,6 +110,7 @@
|
|||
<None Remove="Resources\volume-mute.png" />
|
||||
<None Remove="Resources\volume-plus.png" />
|
||||
<None Remove="Resources\wifi-strength-off.ico" />
|
||||
<None Remove="Resources\Xml.xshd" />
|
||||
<None Remove="Resources\zip-box.png" />
|
||||
<None Include="FModel.ico">
|
||||
<Pack>True</Pack>
|
||||
|
|
@ -120,6 +121,7 @@
|
|||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Ini.xshd" />
|
||||
<EmbeddedResource Include="Resources\Json.xshd" />
|
||||
<EmbeddedResource Include="Resources\Xml.xshd" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
322
FModel/PakReader/BnkReader.cs
Normal file
322
FModel/PakReader/BnkReader.cs
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace FModel.PakReader
|
||||
{
|
||||
/// <summary>
|
||||
/// http://wiki.xentax.com/index.php/Wwise_SoundBank_(*.bnk)
|
||||
/// don't copy paste pls, try to understand what you write from this
|
||||
/// DATASection holds the .wem files
|
||||
/// STIDSection holds the .wem files name in a dictionary where the key is the .wem file id from DATASection
|
||||
/// i see no use (for FModel) in other sections atm
|
||||
/// </summary>
|
||||
public class BnkReader
|
||||
{
|
||||
private const uint _BKHD_ID = 0x44484B42;
|
||||
private const uint _DIDX_ID = 0x58444944;
|
||||
private const uint _DATA_ID = 0x41544144;
|
||||
private const uint _HIRC_ID = 0x43524948;
|
||||
private const uint _STID_ID = 0x44495453;
|
||||
private const uint _STMG_ID = 0x474D5453;
|
||||
public Dictionary<string, byte[]> AudioFiles;
|
||||
|
||||
public BnkReader(BinaryReader reader)
|
||||
{
|
||||
DIDXSection didxSection = null;
|
||||
DATASection dataSection = null;
|
||||
HIRCSection hircSection = null;
|
||||
STIDSection stidSection = null;
|
||||
STMGSection stmgSection = null;
|
||||
AudioFiles = new Dictionary<string, byte[]>();
|
||||
|
||||
while (reader.BaseStream.Position < reader.BaseStream.Length)
|
||||
{
|
||||
uint SectionIdentifier = reader.ReadUInt32();
|
||||
uint SectionLength = reader.ReadUInt32();
|
||||
long Position = reader.BaseStream.Position;
|
||||
switch (SectionIdentifier)
|
||||
{
|
||||
case _BKHD_ID:
|
||||
BKHDSection _ = new BKHDSection(reader);
|
||||
break;
|
||||
case _DIDX_ID:
|
||||
didxSection = new DIDXSection(reader, Position + SectionLength);
|
||||
break;
|
||||
case _DATA_ID:
|
||||
if (didxSection != null) dataSection = new DATASection(reader, Position, didxSection);
|
||||
break;
|
||||
case _HIRC_ID:
|
||||
hircSection = new HIRCSection(reader);
|
||||
break;
|
||||
case _STID_ID:
|
||||
stidSection = new STIDSection(reader);
|
||||
break;
|
||||
case _STMG_ID:
|
||||
stmgSection = new STMGSection(reader);
|
||||
break;
|
||||
}
|
||||
|
||||
reader.BaseStream.Seek(Position + SectionLength, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
if (didxSection != null && dataSection != null && didxSection.WemFilesRef.Count == dataSection.WemFiles.Count)
|
||||
{
|
||||
for (int i = 0; i < didxSection.WemFilesRef.Count; i++)
|
||||
{
|
||||
string key = $"{didxSection.WemFilesRef[i].Id}.wem";
|
||||
if (stidSection != null && stidSection.SoundBanks.TryGetValue(didxSection.WemFilesRef[i].Id, out string name))
|
||||
key = name;
|
||||
|
||||
AudioFiles[key] = dataSection.WemFiles[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class BKHDSection
|
||||
{
|
||||
public uint Version;
|
||||
public uint Id;
|
||||
|
||||
public BKHDSection(BinaryReader reader)
|
||||
{
|
||||
Version = reader.ReadUInt32();
|
||||
Id = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class DIDXSection
|
||||
{
|
||||
public List<WemObject> WemFilesRef;
|
||||
|
||||
public DIDXSection(BinaryReader reader, long length)
|
||||
{
|
||||
WemFilesRef = new List<WemObject>();
|
||||
while (reader.BaseStream.Position < length)
|
||||
{
|
||||
WemFilesRef.Add(new WemObject(reader));
|
||||
}
|
||||
}
|
||||
|
||||
public class WemObject
|
||||
{
|
||||
public uint Id;
|
||||
public uint Offset;
|
||||
public uint Length;
|
||||
|
||||
public WemObject(BinaryReader reader)
|
||||
{
|
||||
Id = reader.ReadUInt32();
|
||||
Offset = reader.ReadUInt32();
|
||||
Length = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DATASection
|
||||
{
|
||||
public List<byte[]> WemFiles;
|
||||
|
||||
public DATASection(BinaryReader reader, long position, DIDXSection didxSection)
|
||||
{
|
||||
WemFiles = new List<byte[]>(didxSection.WemFilesRef.Count);
|
||||
foreach (var fileRef in didxSection.WemFilesRef)
|
||||
{
|
||||
reader.BaseStream.Seek(position + fileRef.Offset, SeekOrigin.Begin);
|
||||
WemFiles.Add(reader.ReadBytes(Convert.ToInt32(fileRef.Length)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class HIRCSection
|
||||
{
|
||||
public uint ObjectNumber;
|
||||
public WwiseObject[] Objects;
|
||||
|
||||
public HIRCSection(BinaryReader reader)
|
||||
{
|
||||
ObjectNumber = reader.ReadUInt32();
|
||||
Objects = new WwiseObject[ObjectNumber];
|
||||
for (int i = 0; i < Objects.Length; i++)
|
||||
{
|
||||
Objects[i] = new WwiseObject(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class WwiseObject
|
||||
{
|
||||
public WwiseObjectType Type;
|
||||
public uint Length;
|
||||
public uint Id;
|
||||
public byte[] AdditionalData;
|
||||
|
||||
public WwiseObject(BinaryReader reader)
|
||||
{
|
||||
Type = (WwiseObjectType)reader.ReadByte();
|
||||
Length = reader.ReadUInt32();
|
||||
Id = reader.ReadUInt32();
|
||||
|
||||
AdditionalData = Type switch
|
||||
{
|
||||
_ => reader.ReadBytes(Convert.ToInt32(Length - sizeof(uint))),
|
||||
};
|
||||
}
|
||||
|
||||
public enum WwiseObjectType : byte
|
||||
{
|
||||
Settings,
|
||||
SoundSFXVoice,
|
||||
EventAction,
|
||||
Event,
|
||||
SequenceContainer,
|
||||
SwitchContainer,
|
||||
AudioBus,
|
||||
BlendContainer,
|
||||
MusicSegment,
|
||||
MusicTrack,
|
||||
MusicSwitchContainer,
|
||||
MusicPlaylistContainer,
|
||||
Attenuation,
|
||||
DialogueEvent,
|
||||
MotionBus,
|
||||
MotionFX,
|
||||
Effect,
|
||||
AuxiliaryBus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class STIDSection
|
||||
{
|
||||
public uint SoundBankNumber;
|
||||
public Dictionary<uint, string> SoundBanks;
|
||||
|
||||
public STIDSection(BinaryReader reader)
|
||||
{
|
||||
reader.ReadUInt32();
|
||||
SoundBankNumber = reader.ReadUInt32();
|
||||
SoundBanks = new Dictionary<uint, string>(Convert.ToInt32(SoundBankNumber));
|
||||
for (int i = 0; i < SoundBankNumber; i++)
|
||||
{
|
||||
SoundBanks[reader.ReadUInt32()] = reader.ReadString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class STMGSection
|
||||
{
|
||||
public float VolumeThreshold;
|
||||
public ushort MaxVoiceInstances;
|
||||
public uint StateGroupNumber;
|
||||
public StateGroupObject[] StateGroups;
|
||||
public uint SwitchGroupNumber;
|
||||
public SwitchGroupObject[] SwitchGroups;
|
||||
public uint GameParameterNumber;
|
||||
public GameParameterObject[] GameParameters;
|
||||
|
||||
public STMGSection(BinaryReader reader)
|
||||
{
|
||||
VolumeThreshold = reader.ReadSingle();
|
||||
MaxVoiceInstances = reader.ReadUInt16();
|
||||
StateGroupNumber = reader.ReadUInt32();
|
||||
StateGroups = new StateGroupObject[Convert.ToInt32(StateGroups)];
|
||||
for (int i = 0; i < StateGroups.Length; i++)
|
||||
{
|
||||
StateGroups[i] = new StateGroupObject(reader);
|
||||
}
|
||||
SwitchGroupNumber = reader.ReadUInt32();
|
||||
SwitchGroups = new SwitchGroupObject[SwitchGroupNumber];
|
||||
for (int i = 0; i < SwitchGroups.Length; i++)
|
||||
{
|
||||
SwitchGroups[i] = new SwitchGroupObject(reader);
|
||||
}
|
||||
GameParameterNumber = reader.ReadUInt32();
|
||||
GameParameters = new GameParameterObject[GameParameterNumber];
|
||||
for (int i = 0; i < GameParameters.Length; i++)
|
||||
{
|
||||
GameParameters[i] = new GameParameterObject(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class StateGroupObject
|
||||
{
|
||||
public uint StateId;
|
||||
public uint DefaultTransitionTime;
|
||||
public uint CustomTransitionTimeNumber;
|
||||
public CustomTransitionTimeObject[] CustomTransitionTimes;
|
||||
|
||||
public StateGroupObject(BinaryReader reader)
|
||||
{
|
||||
StateId = reader.ReadUInt32();
|
||||
DefaultTransitionTime = reader.ReadUInt32();
|
||||
CustomTransitionTimeNumber = reader.ReadUInt32();
|
||||
CustomTransitionTimes = new CustomTransitionTimeObject[CustomTransitionTimeNumber];
|
||||
for (int i = 0; i < CustomTransitionTimes.Length; i++)
|
||||
{
|
||||
CustomTransitionTimes[i] = new CustomTransitionTimeObject(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class CustomTransitionTimeObject
|
||||
{
|
||||
public uint FromId;
|
||||
public uint ToId;
|
||||
public uint TransitionTime;
|
||||
|
||||
public CustomTransitionTimeObject(BinaryReader reader)
|
||||
{
|
||||
FromId = reader.ReadUInt32();
|
||||
ToId = reader.ReadUInt32();
|
||||
TransitionTime = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SwitchGroupObject
|
||||
{
|
||||
public uint SwitchId;
|
||||
public uint GameParameterId;
|
||||
public uint PointNumber;
|
||||
public PointObject[] Points;
|
||||
|
||||
public SwitchGroupObject(BinaryReader reader)
|
||||
{
|
||||
SwitchId = reader.ReadUInt32();
|
||||
GameParameterId = reader.ReadUInt32();
|
||||
PointNumber = reader.ReadUInt32();
|
||||
Points = new PointObject[PointNumber];
|
||||
for (int i = 0; i < Points.Length; i++)
|
||||
{
|
||||
Points[i] = new PointObject(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class PointObject
|
||||
{
|
||||
public float GameParameterValue;
|
||||
public uint SwitchId;
|
||||
public uint CurveShape;
|
||||
|
||||
public PointObject(BinaryReader reader)
|
||||
{
|
||||
GameParameterValue = reader.ReadSingle();
|
||||
SwitchId = reader.ReadUInt32();
|
||||
CurveShape = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GameParameterObject
|
||||
{
|
||||
public uint Id;
|
||||
public float DefaultValue;
|
||||
|
||||
public GameParameterObject(BinaryReader reader)
|
||||
{
|
||||
Id = reader.ReadUInt32();
|
||||
DefaultValue = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ namespace PakReader.Parsers.Class
|
|||
for (int i = 0; i < NumRows; i++)
|
||||
{
|
||||
int num = 1;
|
||||
string RowName = reader.ReadFName().String;
|
||||
string RowName = reader.ReadFName().String ?? "";
|
||||
string baseName = RowName;
|
||||
while (RowMap.ContainsKey(RowName))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace PakReader.Parsers.Class
|
|||
for (int i = 0; i < NumRows; i++)
|
||||
{
|
||||
int num = 1;
|
||||
string RowName = reader.ReadFName().String;
|
||||
string RowName = reader.ReadFName().String ?? "";
|
||||
string baseName = RowName;
|
||||
while (RowMap.ContainsKey(RowName))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ namespace PakReader.Parsers.Class
|
|||
internal USoundWave(PackageReader reader, Stream ubulk, long ubulkOffset) : base(reader)
|
||||
{
|
||||
// if UE4.25+ && Windows -> True
|
||||
bStreaming = FModel.Globals.Game.Version >= EPakVersion.PATH_HASH_INDEX ? true : false;
|
||||
bStreaming = FModel.Globals.Game.Version >= EPakVersion.PATH_HASH_INDEX;
|
||||
|
||||
bCooked = reader.ReadInt32() != 0;
|
||||
if (this.TryGetValue("bStreaming", out var v) && v is BoolProperty b)
|
||||
|
|
|
|||
|
|
@ -32,11 +32,20 @@ namespace PakReader.Parsers.Class
|
|||
{
|
||||
var data = new List<FTexturePlatformData>(1); // Probably gonna be only one texture anyway
|
||||
var PixelFormatName = reader.ReadFName();
|
||||
while (!PixelFormatName.IsNone)
|
||||
if (FModel.Globals.Game.Version < EPakVersion.INDEX_ENCRYPTION)
|
||||
{
|
||||
_ = reader.ReadInt64(); // SkipOffset
|
||||
_ = reader.ReadInt32(); // SkipOffset
|
||||
data.Add(new FTexturePlatformData(reader, ubulk, bulkOffset));
|
||||
PixelFormatName = reader.ReadFName();
|
||||
reader.ReadFName();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!PixelFormatName.IsNone)
|
||||
{
|
||||
_ = reader.ReadInt64(); // SkipOffset
|
||||
data.Add(new FTexturePlatformData(reader, ubulk, bulkOffset));
|
||||
PixelFormatName = reader.ReadFName();
|
||||
}
|
||||
}
|
||||
PlatformDatas = data.ToArray();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace PakReader.Parsers.Objects
|
|||
"MovieSceneFloatValue" => new FRichCurveKey(reader),
|
||||
"MovieSceneFloatChannel" => new FMovieSceneFloatChannel(reader),
|
||||
"MovieSceneEvaluationTemplate" => new FMovieSceneEvaluationTemplate(reader),
|
||||
"SkeletalMeshSamplingLODBuiltData" => new FSkeletalMeshSamplingLODBuiltData(reader),
|
||||
//"SkeletalMeshSamplingLODBuiltData" => new FSkeletalMeshSamplingLODBuiltData(reader),
|
||||
"VectorMaterialInput" => new FVectorMaterialInput(reader),
|
||||
"ColorMaterialInput" => new FColorMaterialInput(reader),
|
||||
"ExpressionInput" => new FMaterialInput(reader),
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace PakReader.Parsers.PropertyTagData
|
|||
"StrProperty" => new StrProperty(reader),
|
||||
"TextProperty" => new TextProperty(reader),
|
||||
"InterfaceProperty" => new InterfaceProperty(reader),
|
||||
"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag),
|
||||
"LazyObjectProperty" => new LazyObjectProperty(reader, tag),
|
||||
//"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag),
|
||||
//"LazyObjectProperty" => new LazyObjectProperty(reader, tag),
|
||||
"SoftObjectProperty" => new SoftObjectProperty(reader, readType),
|
||||
"UInt64Property" => new UInt64Property(reader),
|
||||
"UInt32Property" => new UInt32Property(reader),
|
||||
|
|
@ -55,8 +55,8 @@ namespace PakReader.Parsers.PropertyTagData
|
|||
"StrProperty" => new StrProperty(reader).Value,
|
||||
"TextProperty" => new TextProperty(reader).Value,
|
||||
"InterfaceProperty" => new InterfaceProperty(reader).Value,
|
||||
"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag).Value,
|
||||
"LazyObjectProperty" => new LazyObjectProperty(reader, tag).Value,
|
||||
//"MulticastDelegateProperty" => new MulticastDelegateProperty(reader, tag).Value,
|
||||
//"LazyObjectProperty" => new LazyObjectProperty(reader, tag).Value,
|
||||
"SoftObjectProperty" => new SoftObjectProperty(reader, readType).Value,
|
||||
"UInt64Property" => new UInt64Property(reader).Value,
|
||||
"UInt32Property" => new UInt32Property(reader).Value,
|
||||
|
|
|
|||
10
FModel/Properties/Resources.Designer.cs
generated
10
FModel/Properties/Resources.Designer.cs
generated
|
|
@ -2780,6 +2780,16 @@ namespace FModel.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une ressource localisée de type System.Byte[].
|
||||
/// </summary>
|
||||
public static byte[] Xml {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("Xml", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recherche une chaîne localisée semblable à Yes.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1063,4 +1063,7 @@ It's now the most used free software to leak on Fortnite.</value>
|
|||
<data name="WithPosition" xml:space="preserve">
|
||||
<value>Position / Value</value>
|
||||
</data>
|
||||
<data name="Xml" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Xml.xshd;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
||||
63
FModel/Resources/Xml.xshd
Normal file
63
FModel/Resources/Xml.xshd
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<SyntaxDefinition name="XML" extensions=".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.ilproj;.booproj;.build;.xfrm;.targets;.xaml;.xpt;.xft;.map;.wsdl;.disco;.ps1xml;.nuspec" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
|
||||
<Color foreground="Green" name="Comment" exampleText="<!-- comment -->" />
|
||||
<Color foreground="Blue" name="CData" exampleText="<![CDATA[data]]>" />
|
||||
<Color foreground="Blue" name="DocType" exampleText="<!DOCTYPE rootElement>" />
|
||||
<Color foreground="#89DDFF" name="XmlDeclaration" exampleText='<?xml version="1.0"?>' />
|
||||
<Color foreground="#F07178" name="XmlTag" exampleText='<tag attribute="value" />' />
|
||||
<Color foreground="#C792DD" name="AttributeName" exampleText='<tag attribute="value" />' />
|
||||
<Color foreground="#C3E88D" name="AttributeValue" exampleText='<tag attribute="value" />' />
|
||||
<Color foreground="Teal" name="Entity" exampleText="index.aspx?a=1&amp;b=2" />
|
||||
<Color foreground="Olive" name="BrokenEntity" exampleText="index.aspx?a=1&b=2" />
|
||||
|
||||
<RuleSet>
|
||||
<Span color="Comment" multiline="true">
|
||||
<Begin><!--</Begin>
|
||||
<End>--></End>
|
||||
</Span>
|
||||
<Span color="CData" multiline="true">
|
||||
<Begin><!\[CDATA\[</Begin>
|
||||
<End>]]></End>
|
||||
</Span>
|
||||
<Span color="DocType" multiline="true">
|
||||
<Begin><!DOCTYPE</Begin>
|
||||
<End>></End>
|
||||
</Span>
|
||||
<Span color="XmlDeclaration" multiline="true">
|
||||
<Begin><\?</Begin>
|
||||
<End>\?></End>
|
||||
</Span>
|
||||
<Span color="XmlTag" multiline="true">
|
||||
<Begin><</Begin>
|
||||
<End>></End>
|
||||
<RuleSet>
|
||||
<!-- Treat the position before '<' as end, as that's not a valid character
|
||||
in attribute names and indicates the user forgot a closing quote. -->
|
||||
<Span color="AttributeValue" multiline="true" ruleSet="EntitySet">
|
||||
<Begin>"</Begin>
|
||||
<End>"|(?=<)</End>
|
||||
</Span>
|
||||
<Span color="AttributeValue" multiline="true" ruleSet="EntitySet">
|
||||
<Begin>'</Begin>
|
||||
<End>'|(?=<)</End>
|
||||
</Span>
|
||||
<Rule color="AttributeName">[\d\w_\-\.]+(?=(\s*=))</Rule>
|
||||
<Rule color="AttributeValue">=</Rule>
|
||||
</RuleSet>
|
||||
</Span>
|
||||
<Import ruleSet="EntitySet"/>
|
||||
</RuleSet>
|
||||
|
||||
<RuleSet name="EntitySet">
|
||||
<Rule color="Entity">
|
||||
&
|
||||
[\w\d\#]+
|
||||
;
|
||||
</Rule>
|
||||
|
||||
<Rule color="BrokenEntity">
|
||||
&
|
||||
[\w\d\#]*
|
||||
#missing ;
|
||||
</Rule>
|
||||
</RuleSet>
|
||||
</SyntaxDefinition>
|
||||
|
|
@ -25,6 +25,7 @@ using System.Text;
|
|||
using FModel.ViewModels.DataGrid;
|
||||
using static FModel.Creator.FortniteCreator;
|
||||
using static FModel.Creator.ValorantCreator;
|
||||
using FModel.PakReader;
|
||||
|
||||
namespace FModel.Utils
|
||||
{
|
||||
|
|
@ -72,6 +73,7 @@ namespace FModel.Utils
|
|||
switch (selected.PakEntry.GetExtension())
|
||||
{
|
||||
case ".ini":
|
||||
case ".txt":
|
||||
{
|
||||
using var asset = GetMemoryStream(selected.PakEntry.PakFileName, mount + selected.PakEntry.GetPathWithoutExtension());
|
||||
asset.Position = 0;
|
||||
|
|
@ -79,6 +81,14 @@ namespace FModel.Utils
|
|||
AvalonEditVm.avalonEditViewModel.Set(reader.ReadToEnd(), mount + selected.PakEntry.Name, AvalonEditVm.IniHighlighter);
|
||||
break;
|
||||
}
|
||||
case ".xml":
|
||||
{
|
||||
using var asset = GetMemoryStream(selected.PakEntry.PakFileName, mount + selected.PakEntry.GetPathWithoutExtension());
|
||||
asset.Position = 0;
|
||||
using var reader = new StreamReader(asset);
|
||||
AvalonEditVm.avalonEditViewModel.Set(reader.ReadToEnd(), mount + selected.PakEntry.Name, AvalonEditVm.XmlHighlighter);
|
||||
break;
|
||||
}
|
||||
case ".uproject":
|
||||
case ".uplugin":
|
||||
case ".upluginmanifest":
|
||||
|
|
@ -132,6 +142,21 @@ namespace FModel.Utils
|
|||
case ".ushaderbytecode":
|
||||
case ".pck":
|
||||
break;
|
||||
case ".bnk":
|
||||
{
|
||||
using var asset = GetMemoryStream(selected.PakEntry.PakFileName, mount + selected.PakEntry.GetPathWithoutExtension());
|
||||
asset.Position = 0;
|
||||
BnkReader bnk = new BnkReader(new BinaryReader(asset));
|
||||
Application.Current.Dispatcher.Invoke(delegate
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Window]", $"Opening Audio Player for {selected.PakEntry.GetNameWithExtension()}");
|
||||
if (!FWindows.IsWindowOpen<Window>(Properties.Resources.AudioPlayer))
|
||||
new AudioPlayer().LoadFiles(bnk.AudioFiles, selected.PakEntry.GetPathWithoutFile());
|
||||
else
|
||||
((AudioPlayer)FWindows.GetOpenedWindow<Window>(Properties.Resources.AudioPlayer)).LoadFiles(bnk.AudioFiles, selected.PakEntry.GetPathWithoutFile());
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
AvalonEditVm.avalonEditViewModel.Set(GetJsonProperties(selected.PakEntry, mount, true), mount + selected.PakEntry.Name);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ namespace FModel.ViewModels.AvalonEdit
|
|||
|
||||
public static readonly IHighlightingDefinition JsonHighlighter = LoadHighlighter("Json.xshd");
|
||||
public static readonly IHighlightingDefinition IniHighlighter = LoadHighlighter("Ini.xshd");
|
||||
public static readonly IHighlightingDefinition XmlHighlighter = LoadHighlighter("Xml.xshd");
|
||||
public static IHighlightingDefinition LoadHighlighter(string resourceName)
|
||||
{
|
||||
Assembly executingAssembly = Assembly.GetExecutingAssembly();
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
using FModel.Utils;
|
||||
using PakReader.Parsers.Objects;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace FModel.ViewModels.ListBox
|
||||
{
|
||||
static class ListBoxVm
|
||||
{
|
||||
public static ObservableSortedList<ListBoxViewModel> gameFiles = new ObservableSortedList<ListBoxViewModel>();
|
||||
public static ObservableCollection<ListBoxViewModel2> soundFiles = new ObservableCollection<ListBoxViewModel2>();
|
||||
}
|
||||
|
||||
public class ListBoxViewModel : PropertyChangedBase, IComparable
|
||||
|
|
@ -34,4 +36,39 @@ namespace FModel.ViewModels.ListBox
|
|||
set { this.SetProperty(ref this._pakEntry, value); }
|
||||
}
|
||||
}
|
||||
|
||||
public class ListBoxViewModel2 : PropertyChangedBase
|
||||
{
|
||||
private string _content;
|
||||
public string Content
|
||||
{
|
||||
get { return _content; }
|
||||
|
||||
set { this.SetProperty(ref this._content, value); }
|
||||
}
|
||||
|
||||
private string _fullPath;
|
||||
public string FullPath
|
||||
{
|
||||
get { return _fullPath; }
|
||||
|
||||
set { this.SetProperty(ref this._fullPath, value); }
|
||||
}
|
||||
|
||||
private string _folder;
|
||||
public string Folder
|
||||
{
|
||||
get { return _folder; }
|
||||
|
||||
set { this.SetProperty(ref this._folder, value); }
|
||||
}
|
||||
|
||||
private byte[] _data;
|
||||
public byte[] Data
|
||||
{
|
||||
get { return _data; }
|
||||
|
||||
set { this.SetProperty(ref this._data, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ namespace FModel.Windows.Launcher
|
|||
}
|
||||
|
||||
string spellbreakerFilesPath = Paks.GetSpellbreakPakFilesPath();
|
||||
if (!string.IsNullOrEmpty(battlebreakersFilesPath))
|
||||
if (!string.IsNullOrEmpty(spellbreakerFilesPath))
|
||||
{
|
||||
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[LauncherInstalled.dat]", $"Spellbreak found at {spellbreakerFilesPath}");
|
||||
Globals.gNotifier.ShowCustomMessage("Spellbreak", Properties.Resources.PathAutoDetected, "/FModel;component/Resources/spellbreak.ico");
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:properties="clr-namespace:FModel.Properties"
|
||||
xmlns:utils="clr-namespace:FModel.Utils"
|
||||
mc:Ignorable="d"
|
||||
Style="{StaticResource {x:Type Window}}"
|
||||
Title="{x:Static properties:Resources.AudioPlayer}" Height="300" MinHeight="300" Width="1000" MinWidth="1000"
|
||||
Title="{x:Static properties:Resources.AudioPlayer}"
|
||||
Height="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}, Converter={utils:Screens}, ConverterParameter='0.50' }"
|
||||
Width="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenWidth}, Converter={utils:Screens}, ConverterParameter='0.50' }"
|
||||
WindowStartupLocation="CenterScreen" Icon="/FModel;component/FModel.ico"
|
||||
Closed="OnClosed">
|
||||
<Grid>
|
||||
|
|
@ -19,85 +22,116 @@
|
|||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TabControl Grid.Row="0" Grid.Column="0" BorderBrush="{x:Null}">
|
||||
<TabItem x:Name="AudioPlayer_TabItm" Header="{x:Static properties:Resources.FFile}">
|
||||
<Grid>
|
||||
<Grid.Background>
|
||||
<LinearGradientBrush EndPoint="0.25,0.9" StartPoint="0.75,1">
|
||||
<GradientStop Color="#FF252D36" Offset="0"/>
|
||||
<GradientStop Color="#FF252E38" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="5"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="10"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Row="0" Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="2"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Grid.Column="1" Grid.Row="1" Content="{x:Static properties:Resources.AudioDevices}"/>
|
||||
<Label Grid.Column="1" Grid.Row="2" Content="{x:Static properties:Resources.Name}"/>
|
||||
<Label Grid.Column="1" Grid.Row="3" Content="{x:Static properties:Resources.BytesPerSecond}"/>
|
||||
<Label Grid.Column="1" Grid.Row="4" Content="{x:Static properties:Resources.Duration}"/>
|
||||
<Label Grid.Column="1" Grid.Row="5" Content="{x:Static properties:Resources.Volume}"/>
|
||||
<Button Grid.Column="3" Grid.Row="7" Height="20" Width="40" Click="OnPlayPauseClick"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,50,-1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="15"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TabControl Grid.Row="0" BorderBrush="{x:Null}">
|
||||
<TabItem x:Name="AudioPlayer_TabItm" Header="{x:Static properties:Resources.FFile}">
|
||||
<Grid>
|
||||
<Grid.Background>
|
||||
<LinearGradientBrush EndPoint="0.25,0.9" StartPoint="0.75,1">
|
||||
<GradientStop Color="#FF252D36" Offset="0"/>
|
||||
<GradientStop Color="#FF252E38" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Grid.Background>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="5"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="10"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image x:Name="PlayPauseImg" Grid.Column="1" Source="/FModel;component/Resources/play.png"
|
||||
Width="14" Stretch="UniformToFill" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
<Button Grid.Column="3" Grid.Row="7" Height="20" Width="40" Click="OnStopClick"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,0,-1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="15"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label Grid.Column="1" Grid.Row="1" Content="{x:Static properties:Resources.AudioDevices}"/>
|
||||
<Label Grid.Column="1" Grid.Row="2" Content="{x:Static properties:Resources.Name}"/>
|
||||
<Label Grid.Column="1" Grid.Row="3" Content="{x:Static properties:Resources.BytesPerSecond}"/>
|
||||
<Label Grid.Column="1" Grid.Row="4" Content="{x:Static properties:Resources.Duration}"/>
|
||||
<Label Grid.Column="1" Grid.Row="5" Content="{x:Static properties:Resources.Volume}"/>
|
||||
|
||||
<Image Grid.Column="1" Source="/FModel;component/Resources/stop.png"
|
||||
Width="14" Stretch="UniformToFill" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
<Button Grid.Column="1" Grid.Row="7" Content="{x:Static properties:Resources.Open}"
|
||||
Click="OnOpenClick" Height="19" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
|
||||
|
||||
<ComboBox x:Name="AudioDevices_CmbBox" Grid.Column="3" Grid.Row="1"
|
||||
<ComboBox x:Name="AudioDevices_CmbBox" Grid.Column="3" Grid.Row="1"
|
||||
DisplayMemberPath="Name" SelectionChanged="OnSelectionChanged"/>
|
||||
<TextBox Grid.Column="3" Grid.Row="2" TextWrapping="NoWrap"
|
||||
<TextBox Grid.Column="3" Grid.Row="2" TextWrapping="NoWrap"
|
||||
Style="{StaticResource ResourceKey=SelectableTextBox}" Text="{Binding Content, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="3" Grid.Row="3" TextWrapping="NoWrap"
|
||||
<TextBox Grid.Column="3" Grid.Row="3" TextWrapping="NoWrap"
|
||||
Style="{StaticResource ResourceKey=SelectableTextBox}" Text="{Binding Bytes, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="3" Grid.Row="4" TextWrapping="NoWrap"
|
||||
<TextBox Grid.Column="3" Grid.Row="4" TextWrapping="NoWrap"
|
||||
Style="{StaticResource ResourceKey=SelectableTextBox}" Text="{Binding Duration, Mode=TwoWay}"/>
|
||||
<Slider Grid.Column="3" Grid.Row="5"
|
||||
<Slider Grid.Column="3" Grid.Row="5"
|
||||
Style="{StaticResource Horizontal_Slider}" TickPlacement="None" VerticalAlignment="Center"
|
||||
Minimum="0" Maximum="1" TickFrequency="0.1" Value="{Binding Volume, Mode=TwoWay}"
|
||||
Thumb.DragCompleted="UpdateVolume"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="2" Margin="10,20,10,0" >
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="2"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListBox x:Name="Sound_LstBox" Grid.Row="0" BorderBrush="#FF333C46" SelectionChanged="OnSelectedItemChanged"/>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="5"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="10"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Grid.Column="2" Grid.Row="1" Height="20" MinWidth="40" Click="OnAddClick"
|
||||
Content="{x:Static properties:Resources.Add}" HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Margin="0,0,100,-1" Padding="5,1,5,1"/>
|
||||
<Button Grid.Column="2" Grid.Row="1" Height="20" Width="40" Click="OnPlayPauseClick"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,50,-1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="15"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image x:Name="PlayPauseImg" Grid.Column="1" Source="/FModel;component/Resources/play.png"
|
||||
Width="14" Stretch="UniformToFill" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
<Button Grid.Column="2" Grid.Row="1" Height="20" Width="40" Click="OnStopClick"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,0,-1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1"/>
|
||||
<ColumnDefinition Width="15"/>
|
||||
<ColumnDefinition Width="1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Image Grid.Column="1" Source="/FModel;component/Resources/stop.png"
|
||||
Width="14" Stretch="UniformToFill" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="1" Margin="10,20,10,0" >
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using FModel.Discord;
|
||||
using FModel.ViewModels.ListBox;
|
||||
using FModel.ViewModels.SoundPlayer;
|
||||
using FModel.Windows.SoundPlayer.Visualization;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
|
@ -20,6 +23,7 @@ namespace FModel.Windows.SoundPlayer
|
|||
private UserControls.SpectrumAnalyzer spectrumAnalyzer;
|
||||
private UserControls.Timeline timeline;
|
||||
private UserControls.Timeclock timeclock;
|
||||
private string _oldPlayedSound = string.Empty;
|
||||
|
||||
public AudioPlayer()
|
||||
{
|
||||
|
|
@ -31,12 +35,14 @@ namespace FModel.Windows.SoundPlayer
|
|||
private void OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
output.Stop();
|
||||
ListBoxVm.soundFiles.Clear();
|
||||
DiscordIntegration.Restore();
|
||||
InputFileVm.inputFileViewModel.Reset();
|
||||
}
|
||||
private void Startup()
|
||||
{
|
||||
DiscordIntegration.SaveCurrentPresence();
|
||||
Sound_LstBox.ItemsSource = ListBoxVm.soundFiles;
|
||||
AudioPlayer_TabItm.DataContext = InputFileVm.inputFileViewModel;
|
||||
AudioDevices_CmbBox.ItemsSource = InputFileVm.inputFileViewModel.Devices;
|
||||
AudioDevices_CmbBox.SelectedItem = InputFileVm.inputFileViewModel.Devices.Where(x => x.DeviceId == Properties.Settings.Default.AudioPlayerDevice).FirstOrDefault();
|
||||
|
|
@ -54,30 +60,69 @@ namespace FModel.Windows.SoundPlayer
|
|||
Time.Content = timeline;
|
||||
}
|
||||
|
||||
private void OnOpenClick(object sender, RoutedEventArgs e)
|
||||
private void OnAddClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var ofd = new OpenFileDialog
|
||||
{
|
||||
Title = Properties.Resources.SelectFile,
|
||||
Filter = Properties.Resources.OggFilter,
|
||||
Multiselect = true,
|
||||
InitialDirectory = Properties.Settings.Default.OutputPath + "\\Sounds\\"
|
||||
};
|
||||
if ((bool)ofd.ShowDialog())
|
||||
LoadFile(ofd.FileName);
|
||||
{
|
||||
foreach (string file in ofd.FileNames)
|
||||
LoadFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFiles(Dictionary<string, byte[]> files, string gameFolder)
|
||||
{
|
||||
Focus();
|
||||
|
||||
ListBoxVm.soundFiles.Clear();
|
||||
foreach (var (key, value) in files)
|
||||
{
|
||||
ListBoxVm.soundFiles.Add(new ListBoxViewModel2
|
||||
{
|
||||
Content = key,
|
||||
Data = value,
|
||||
FullPath = string.Empty,
|
||||
Folder = gameFolder
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFile(string filepath)
|
||||
{
|
||||
Focus();
|
||||
|
||||
output.Stop();
|
||||
output.Load(filepath);
|
||||
output.Play();
|
||||
var item = new ListBoxViewModel2
|
||||
{
|
||||
Content = Path.GetFileName(filepath),
|
||||
Data = null,
|
||||
FullPath = filepath,
|
||||
Folder = string.Empty
|
||||
};
|
||||
ListBoxVm.soundFiles.Add(item);
|
||||
|
||||
string name = Path.GetFileName(filepath);
|
||||
InputFileVm.inputFileViewModel.Set(name, output);
|
||||
DiscordIntegration.Update(string.Empty, string.Format(Properties.Resources.Listening, name));
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
if (ListBoxVm.soundFiles.Count == 1) // auto play if one in queue
|
||||
{
|
||||
output.Stop();
|
||||
output.Load(filepath);
|
||||
output.Play();
|
||||
Sound_LstBox.SelectedIndex = 0;
|
||||
|
||||
string name = Path.GetFileName(filepath);
|
||||
InputFileVm.inputFileViewModel.Set(name, output);
|
||||
DiscordIntegration.Update(string.Empty, string.Format(Properties.Resources.Listening, name));
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Sound_LstBox.SelectedIndex = ListBoxVm.soundFiles.IndexOf(item);
|
||||
Sound_LstBox.ScrollIntoView(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVolume(object sender, RoutedEventArgs e)
|
||||
|
|
@ -89,7 +134,18 @@ namespace FModel.Windows.SoundPlayer
|
|||
{
|
||||
if (output.HasMedia)
|
||||
{
|
||||
if (output.IsPlaying)
|
||||
if (!output.FileName.Equals(_oldPlayedSound))
|
||||
{
|
||||
output.Stop();
|
||||
output.Load(_oldPlayedSound);
|
||||
output.Play();
|
||||
|
||||
string name = Path.GetFileName(_oldPlayedSound);
|
||||
InputFileVm.inputFileViewModel.Set(name, output);
|
||||
DiscordIntegration.Update(string.Empty, string.Format(Properties.Resources.Listening, name));
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
}
|
||||
else if (output.IsPlaying)
|
||||
{
|
||||
output.Pause();
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/play.png"));
|
||||
|
|
@ -100,6 +156,19 @@ namespace FModel.Windows.SoundPlayer
|
|||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Sound_LstBox.SelectedIndex > -1 && Sound_LstBox.SelectedItem is ListBoxViewModel2 selected)
|
||||
{
|
||||
output.Stop();
|
||||
output.Load(selected.FullPath);
|
||||
output.Play();
|
||||
|
||||
InputFileVm.inputFileViewModel.Set(selected.Content, output);
|
||||
DiscordIntegration.Update(string.Empty, string.Format(Properties.Resources.Listening, selected.Content));
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStopClick(object sender, RoutedEventArgs e)
|
||||
|
|
@ -125,5 +194,46 @@ namespace FModel.Windows.SoundPlayer
|
|||
output.SwapDevice(d);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSelectedItemChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ListBox listBox && listBox.SelectedItem is ListBoxViewModel2 selectedItem)
|
||||
{
|
||||
// vgmstream convert on select
|
||||
if (string.IsNullOrEmpty(selectedItem.FullPath) && selectedItem.Data != null)
|
||||
{
|
||||
string file = Properties.Settings.Default.OutputPath + "\\vgmstream\\test.exe";
|
||||
if (File.Exists(file))
|
||||
{
|
||||
string folder = Properties.Settings.Default.OutputPath + "\\Sounds\\" + selectedItem.Folder + "\\";
|
||||
Directory.CreateDirectory(folder);
|
||||
File.WriteAllBytes(folder + selectedItem.Content, selectedItem.Data);
|
||||
string newFile = Path.ChangeExtension(folder + selectedItem.Content, ".wav");
|
||||
var vgmstream = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = file,
|
||||
Arguments = $"-o \"{newFile}\" \"{folder + selectedItem.Content}\"",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
CreateNoWindow = true
|
||||
});
|
||||
vgmstream.WaitForExit();
|
||||
if (vgmstream.ExitCode == 0)
|
||||
{
|
||||
ListBoxVm.soundFiles.Remove(selectedItem);
|
||||
_oldPlayedSound = newFile;
|
||||
LoadFile(newFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!_oldPlayedSound.Equals(selectedItem.FullPath))
|
||||
_oldPlayedSound = selectedItem.FullPath;
|
||||
|
||||
if (output.HasMedia && output.FileName.Equals(_oldPlayedSound))
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/pause.png"));
|
||||
else
|
||||
PlayPauseImg.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/play.png"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ namespace FModel.Windows.SoundPlayer.Visualization
|
|||
public class OutputSource : ISource, IDisposable
|
||||
{
|
||||
private string _filename;
|
||||
public string FileName
|
||||
{
|
||||
get { return _filename; }
|
||||
}
|
||||
private Uri _uri;
|
||||
private IWaveSource _waveSource;
|
||||
private ISampleSource _sampleSource;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user