├── SirenSharp ├── sirensharp.ico ├── ViewModels │ ├── ViewModelBase.cs │ ├── ErrorsViewModel.cs │ ├── NewProjectViewModel.cs │ └── GenerateResourceViewModel.cs ├── Services │ ├── IAwcGenerator.cs │ ├── IResourceGenerator.cs │ ├── IDataGenerator.cs │ ├── AwcGenerator.cs │ └── ResourceGenerator.cs ├── App.xaml ├── Models │ ├── DLC.cs │ ├── Resource.cs │ ├── SoundSet.cs │ ├── Siren.cs │ ├── Sound.cs │ └── Project.cs ├── AssemblyInfo.cs ├── Converters │ ├── NullVisibilityConverter.cs │ └── FileSizeConverter.cs ├── Views │ ├── NewProjectWindow.xaml.cs │ ├── MainWindow.xaml.cs │ ├── GenerateResourceWindow.xaml.cs │ ├── AWCPropertiesView.xaml.cs │ ├── SirenPropertiesView.xaml.cs │ ├── AboutWindow.xaml.cs │ ├── AboutWindow.xaml │ ├── AWCPropertiesView.xaml │ ├── NewProjectWindow.xaml │ ├── GenerateResourceWindow.xaml │ └── SirenPropertiesView.xaml ├── Validators │ ├── ProjectNameValidator.cs │ ├── SirenNameValidator.cs │ ├── ResourceNameValidator.cs │ ├── AwcNameValidator.cs │ ├── DLCNameValidator.cs │ └── AudioFileValidator.cs ├── SirenSharp.csproj └── App.xaml.cs ├── lib └── CodeWalker.Core │ ├── Resources │ └── magic.dat │ ├── GameFiles │ ├── FileTypes │ │ ├── Builders │ │ │ └── YndBuilder.cs │ │ ├── VehicleLayoutsFile.cs │ │ ├── JPsoFile.cs │ │ ├── YfdFile.cs │ │ ├── Stats.cs │ │ ├── YvrFile.cs │ │ ├── YwrFile.cs │ │ ├── PedFile.cs │ │ ├── YtdFile.cs │ │ ├── YdrFile.cs │ │ ├── DlcSetupFile.cs │ │ ├── YftFile.cs │ │ ├── YedFile.cs │ │ ├── YldFile.cs │ │ ├── YddFile.cs │ │ ├── GtxdFile.cs │ │ ├── YptFile.cs │ │ ├── YbnFile.cs │ │ └── YmfFile.cs │ ├── GameFile.cs │ └── Resources │ │ ├── ResourceFile.cs │ │ ├── ResourceAnalyzer.cs │ │ ├── VertexType.cs │ │ └── WaypointRecord.cs │ ├── CodeWalker.Core.csproj │ ├── Utils │ ├── BoundingBoxes.cs │ ├── Matrices.cs │ ├── Quaternions.cs │ └── Cache.cs │ ├── World │ ├── Weapon.cs │ ├── Vehicle.cs │ ├── Timecycle.cs │ ├── TimecycleMods.cs │ ├── Heightmaps.cs │ └── PopZones.cs │ └── Properties │ ├── Resources.Designer.cs │ └── Resources.resx ├── README.md ├── LICENSE ├── SirenSharp.sln └── .gitattributes /SirenSharp/sirensharp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BJDubb/SirenSharp/HEAD/SirenSharp/sirensharp.ico -------------------------------------------------------------------------------- /lib/CodeWalker.Core/Resources/magic.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BJDubb/SirenSharp/HEAD/lib/CodeWalker.Core/Resources/magic.dat -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/Builders/YndBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CodeWalker.Core.GameFiles.FileTypes.Builders 8 | { 9 | public class YndBuilder 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SirenSharp/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using CommunityToolkit.Mvvm.ComponentModel; 7 | 8 | namespace SirenSharp.ViewModels 9 | { 10 | public abstract class ViewModelBase : ObservableObject 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SirenSharp/Services/IAwcGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SirenSharp.Models; 7 | 8 | namespace SirenSharp.Services 9 | { 10 | public interface IAwcGenerator 11 | { 12 | public string GenerateAwcXml(SoundSet soundSet); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SirenSharp/Services/IResourceGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SirenSharp.Models; 7 | 8 | namespace SirenSharp.Services 9 | { 10 | public interface IResourceGenerator 11 | { 12 | public void GenerateResource(string resourceName, string dlcName, string folderPath, List soundSets); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SirenSharp/Services/IDataGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using SirenSharp.Models; 7 | 8 | namespace SirenSharp.Services 9 | { 10 | public interface IDataGenerator 11 | { 12 | public string GenerateDatXml(DLC dlc, List soundSets); 13 | public string GenerateNametable(List soundSets); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SirenSharp/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /SirenSharp/Models/DLC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SirenSharp.Models 8 | { 9 | public class DLC 10 | { 11 | public string Name { get; set; } 12 | public List SoundSets { get; set; } 13 | public DLC(string name) 14 | { 15 | Name = name; 16 | SoundSets = new List(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /SirenSharp/Models/Resource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SirenSharp.Models 8 | { 9 | public class Resource 10 | { 11 | public List DLCs { get; set; } 12 | 13 | public string Name { get; } 14 | 15 | public Resource(string name) 16 | { 17 | DLCs = new List(); 18 | 19 | Name = name; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/CodeWalker.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /SirenSharp/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Windows; 3 | 4 | [assembly: ThemeInfo( 5 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 6 | //(used if a resource is not found in the page, 7 | // or application resource dictionaries) 8 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 9 | //(used if a resource is not found in the page, 10 | // app, or any theme specific resource dictionaries) 11 | )] 12 | -------------------------------------------------------------------------------- /SirenSharp/Converters/NullVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows; 9 | 10 | namespace SirenSharp.Converters 11 | { 12 | public class NullVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return value != null; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SirenSharp/Views/NewProjectWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace SirenSharp.Views 16 | { 17 | /// 18 | /// Interaction logic for NewProjectWindow.xaml 19 | /// 20 | public partial class NewProjectWindow : Window 21 | { 22 | public NewProjectWindow() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SirenSharp/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace SirenSharp.Views 17 | { 18 | /// 19 | /// Interaction logic for MainWindow.xaml 20 | /// 21 | public partial class MainWindow : Window 22 | { 23 | public MainWindow() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SirenSharp/Views/GenerateResourceWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace SirenSharp.Views 16 | { 17 | /// 18 | /// Interaction logic for GenerateResourceWindow.xaml 19 | /// 20 | public partial class GenerateResourceWindow : Window 21 | { 22 | public GenerateResourceWindow() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SirenSharp/Views/AWCPropertiesView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace SirenSharp.Views 17 | { 18 | /// 19 | /// Interaction logic for AWCPropertiesView.xaml 20 | /// 21 | public partial class AWCPropertiesView : UserControl 22 | { 23 | public AWCPropertiesView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SirenSharp/Views/SirenPropertiesView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace SirenSharp.Views 17 | { 18 | /// 19 | /// Interaction logic for SirenPropertiesView.xaml 20 | /// 21 | public partial class SirenPropertiesView : UserControl 22 | { 23 | public SirenPropertiesView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SirenSharp/Validators/ProjectNameValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace SirenSharp.Validators 10 | { 11 | public class ProjectNameValidator : ValidationRule 12 | { 13 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 14 | { 15 | string sirenName = (string)value; 16 | 17 | if (string.IsNullOrEmpty(sirenName)) return new ValidationResult(false, "Name can't be empty."); 18 | 19 | if (sirenName.Contains(" ")) return new ValidationResult(false, "Name can't include spaces."); 20 | 21 | return ValidationResult.ValidResult; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SirenSharp/Validators/SirenNameValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace SirenSharp.Validators 10 | { 11 | public class SirenNameValidator : ValidationRule 12 | { 13 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 14 | { 15 | string sirenName = (string)value; 16 | 17 | if (string.IsNullOrEmpty(sirenName) ) return new ValidationResult(false, "Name can't be empty."); 18 | 19 | if (sirenName.Contains(" ")) return new ValidationResult(false, "Name can't include spaces."); 20 | 21 | return ValidationResult.ValidResult; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SirenSharp/Validators/ResourceNameValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace SirenSharp.Validators 10 | { 11 | public class ResourceNameValidator : ValidationRule 12 | { 13 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 14 | { 15 | string sirenName = (string)value; 16 | 17 | if (string.IsNullOrEmpty(sirenName)) return new ValidationResult(false, "Name can't be empty."); 18 | 19 | if (sirenName.Contains(" ")) return new ValidationResult(false, "Name can't include spaces. (Use hypens instead)"); 20 | 21 | return ValidationResult.ValidResult; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SirenSharp/Validators/AwcNameValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace SirenSharp.Validators 10 | { 11 | public class AwcNameValidator : ValidationRule 12 | { 13 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 14 | { 15 | string sirenName = (string)value; 16 | 17 | if (sirenName is null) return ValidationResult.ValidResult; 18 | 19 | if (string.IsNullOrEmpty(sirenName)) return new ValidationResult(false, "Name can't be empty."); 20 | 21 | if (sirenName.Contains(" ")) return new ValidationResult(false, "Name can't include spaces."); 22 | 23 | return ValidationResult.ValidResult; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SirenSharp/Validators/DLCNameValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | namespace SirenSharp.Validators 10 | { 11 | public class DLCNameValidator : ValidationRule 12 | { 13 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 14 | { 15 | string sirenName = (string)value; 16 | 17 | if (string.IsNullOrEmpty(sirenName)) return new ValidationResult(false, "Name can't be empty."); 18 | 19 | if (sirenName.Contains(" ")) return new ValidationResult(false, "Name can't include spaces."); 20 | 21 | if (sirenName.Contains("dlc_")) return new ValidationResult(false, "'dlc_' prefix is not needed."); 22 | 23 | return ValidationResult.ValidResult; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # SirenSharp 3 | 4 | A FiveM tool for creating server sided sirens. 5 | 6 | ![image](https://github.com/BJDubb/SirenSharp/assets/47697544/7c4d7d52-226e-486a-971d-5a449bd11e65) 7 | 8 | 9 | 10 | ## Credits 11 | 12 | @Dexyfex for [CodeWalker](https://github.com/dexyfex/CodeWalker) 13 | 14 | 15 | ## Getting Started 16 | 17 | Download latest version from the [releases](https://github.com/BJDubb/SirenSharp/releases/latest) page. 18 | 19 | Unzip the `.rar/.zip` and run `SirenSharp.exe` 20 | 21 | 22 | ## Discord 23 | 24 | Join the [discord](https://discord.gg/GCMRtBNCXR) or meesage me at BJDubb\# 0001 if you are having any issues. 25 | 26 | 27 | ## Guides 28 | 29 | Head over to the [docs](https://docs.sirensharp.dev/overview/what-is-sirensharp) to learn how to use SirenSharp 30 | 31 | Youtube tutorial [here](https://youtu.be/oTv3mVHZAK0) 32 | 33 | 34 | 35 | ## Donate 36 | 37 | Donate to help the development of SirenSharp. 38 | 39 | [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/T6T0L425H) 40 | -------------------------------------------------------------------------------- /SirenSharp/SirenSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WinExe 5 | net7.0-windows 6 | enable 7 | true 8 | sirensharp.ico 9 | 10 | 0.3 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CodeWalker.GameFiles 9 | { 10 | [TypeConverter(typeof(ExpandableObjectConverter))] 11 | public class VehicleLayoutsFile : GameFile, PackedFile 12 | { 13 | public string Xml { get; set; } 14 | 15 | public VehicleLayoutsFile() : base(null, GameFileType.VehicleLayouts) 16 | { } 17 | public VehicleLayoutsFile(RpfFileEntry entry) : base(entry, GameFileType.VehicleLayouts) 18 | { 19 | } 20 | 21 | public void Load(byte[] data, RpfFileEntry entry) 22 | { 23 | RpfFileEntry = entry; 24 | Name = entry.Name; 25 | FilePath = Name; 26 | 27 | 28 | //always XML .meta 29 | Xml = TextUtil.GetUTF8Text(data); 30 | 31 | //TODO: parse CVehicleMetadataMgr XML 32 | 33 | 34 | Loaded = true; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Beckam White 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SirenSharp/Validators/AudioFileValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows.Controls; 9 | using NAudio.FileFormats.Wav; 10 | using NAudio.Wave; 11 | 12 | namespace SirenSharp.Validators 13 | { 14 | public class AudioFileValidator : ValidationRule 15 | { 16 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 17 | { 18 | string filepath = (string)value; 19 | 20 | //if (string.IsNullOrEmpty(filepath)) return ValidationResult.ValidResult; 21 | 22 | if (!File.Exists(filepath)) return new ValidationResult(false, "File does not exist"); 23 | 24 | try 25 | { 26 | new WaveFileReader(filepath); 27 | } 28 | catch (FormatException e) 29 | { 30 | return new ValidationResult(false, e.Message); 31 | } 32 | 33 | return ValidationResult.ValidResult; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/JPsoFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CodeWalker.GameFiles 9 | { 10 | public class JPsoFile : PackedFile 11 | { 12 | public RpfFileEntry FileEntry { get; set; } 13 | public PsoFile Pso { get; set; } 14 | 15 | 16 | public void Load(byte[] data, RpfFileEntry entry) 17 | { 18 | //MemoryStream ms = new MemoryStream(data); 19 | 20 | FileEntry = entry; 21 | 22 | MemoryStream ms = new MemoryStream(data); 23 | 24 | if (PsoFile.IsPSO(ms)) 25 | { 26 | Pso = new PsoFile(); 27 | Pso.Load(ms); 28 | 29 | //PsoTypes.EnsurePsoTypes(Pso); 30 | 31 | var root = PsoTypes.GetRootEntry(Pso); 32 | if (root != null) 33 | { 34 | } 35 | return; 36 | } 37 | else 38 | { 39 | 40 | } 41 | 42 | 43 | 44 | 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SirenSharp/Models/SoundSet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Xml.Serialization; 10 | using CommunityToolkit.Mvvm.ComponentModel; 11 | using SirenSharp.Converters; 12 | 13 | namespace SirenSharp.Models 14 | { 15 | public class SoundSet : ObservableObject 16 | { 17 | 18 | public ObservableCollection Sounds { get; set; } 19 | private string name; 20 | public string Name 21 | { 22 | get => name; 23 | set 24 | { 25 | name = value; 26 | OnPropertyChanged(); 27 | } 28 | } 29 | 30 | public SoundSet() 31 | { 32 | } 33 | 34 | public SoundSet(string name) 35 | { 36 | Name = name; 37 | Sounds = new ObservableCollection(); 38 | } 39 | 40 | public void AddSound(Sound sound) 41 | { 42 | Sounds.Add(sound); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /SirenSharp/Views/AboutWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Navigation; 16 | using System.Windows.Shapes; 17 | 18 | namespace SirenSharp.Views 19 | { 20 | /// 21 | /// Interaction logic for AboutWindow.xaml 22 | /// 23 | public partial class AboutWindow : Window 24 | { 25 | public AboutWindow() 26 | { 27 | InitializeComponent(); 28 | var version = Assembly.GetExecutingAssembly().GetName().Version; 29 | versionText.Text = $"Version: v{version.Major}.{version.Minor}"; 30 | } 31 | 32 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 33 | { 34 | Process.Start(new ProcessStartInfo { FileName = e.Uri.AbsoluteUri, UseShellExecute = true}); 35 | e.Handled = true; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/Utils/BoundingBoxes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using SharpDX; 3 | 4 | namespace CodeWalker.Core.Utils 5 | { 6 | public static class BoundingBoxExtensions 7 | { 8 | public static Vector3 Size(this BoundingBox bounds) 9 | { 10 | return new Vector3( 11 | Math.Abs(bounds.Maximum.X - bounds.Minimum.X), 12 | Math.Abs(bounds.Maximum.Y - bounds.Minimum.Y), 13 | Math.Abs(bounds.Maximum.Z - bounds.Minimum.Z)); 14 | } 15 | 16 | public static Vector3 Center(this BoundingBox bounds) 17 | { 18 | return (bounds.Minimum + bounds.Maximum) * 0.5F; 19 | } 20 | 21 | public static BoundingBox Encapsulate(this BoundingBox box, BoundingBox bounds) 22 | { 23 | box.Minimum = Vector3.Min(box.Minimum, bounds.Minimum); 24 | box.Maximum = Vector3.Max(box.Maximum, bounds.Maximum); 25 | return box; 26 | } 27 | 28 | public static float Radius(this BoundingBox box) 29 | { 30 | var extents = (box.Maximum - box.Minimum) * 0.5F; 31 | return extents.Length(); 32 | } 33 | 34 | public static BoundingBox Expand(this BoundingBox b, float amount) 35 | { 36 | return new BoundingBox(b.Minimum - Vector3.One * amount, b.Maximum + Vector3.One * amount); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SirenSharp/Models/Siren.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NAudio.Wave; 8 | 9 | namespace SirenSharp.Models 10 | { 11 | public class Siren 12 | { 13 | public string SirenName { get; set; } 14 | private string audioPath { get; set; } 15 | public string AudioPath { get => audioPath; set => UpdateFilePath(value); } 16 | public int Samples { get; private set; } 17 | public int SampleRate { get; private set; } 18 | public TimeSpan Length { get; private set; } 19 | public string FileName => new FileInfo(AudioPath).Name; 20 | 21 | public Siren(string sirenName, string audioPath) 22 | { 23 | SirenName = sirenName; 24 | AudioPath = audioPath; 25 | } 26 | 27 | private void UpdateFilePath(string filePath) 28 | { 29 | audioPath = filePath; 30 | 31 | using (var wfr = new WaveFileReader(AudioPath)) 32 | { 33 | Length = wfr.TotalTime; 34 | SampleRate = wfr.WaveFormat.SampleRate; 35 | int len = (int)wfr.Length; 36 | int other = wfr.WaveFormat.Channels * wfr.WaveFormat.BitsPerSample / 8; 37 | Samples = len / other; 38 | } 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SirenSharp/Converters/FileSizeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System; 9 | 10 | namespace SirenSharp.Converters 11 | { 12 | public class FileSizeConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | double len = (long)value; 17 | string[] sizes = { "B", "KB", "MB", "GB", "TB" }; 18 | int order = 0; 19 | while (len >= 1024 && order < sizes.Length - 1) 20 | { 21 | order++; 22 | len = len / 1024; 23 | } 24 | 25 | return string.Format("{0:0.##} {1}", len, sizes[order]); 26 | } 27 | 28 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | 33 | public static string HumanReadableBytes(long size) 34 | { 35 | double len = size; 36 | string[] sizes = { "B", "KB", "MB", "GB", "TB" }; 37 | int order = 0; 38 | while (len >= 1024 && order < sizes.Length - 1) 39 | { 40 | order++; 41 | len = len / 1024; 42 | } 43 | 44 | return string.Format("{0:0.##} {1}", len, sizes[order]); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/YfdFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CodeWalker.GameFiles 9 | { 10 | [TypeConverter(typeof(ExpandableObjectConverter))] 11 | public class YfdFile : GameFile, PackedFile 12 | { 13 | public FrameFilterDictionary FrameFilterDictionary { get; set; } 14 | 15 | public string LoadException { get; set; } 16 | 17 | 18 | public YfdFile() : base(null, GameFileType.Yfd) 19 | { 20 | } 21 | public YfdFile(RpfFileEntry entry) : base(entry, GameFileType.Yfd) 22 | { 23 | } 24 | 25 | public void Load(byte[] data, RpfFileEntry entry) 26 | { 27 | Name = entry.Name; 28 | RpfFileEntry = entry; 29 | //Hash = entry.ShortNameHash; 30 | 31 | 32 | RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; 33 | if (resentry == null) 34 | { 35 | throw new Exception("File entry wasn't a resource! (is it binary data?)"); 36 | } 37 | 38 | ResourceDataReader rd = null; 39 | try 40 | { 41 | rd = new ResourceDataReader(resentry, data); 42 | } 43 | catch (Exception ex) 44 | { 45 | //data = entry.File.DecompressBytes(data); //?? 46 | LoadException = ex.ToString(); 47 | } 48 | 49 | FrameFilterDictionary = rd?.ReadBlock(); 50 | 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SirenSharp/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using SirenSharp.Services; 11 | using SirenSharp.ViewModels; 12 | using SirenSharp.Views; 13 | 14 | namespace SirenSharp 15 | { 16 | /// 17 | /// Interaction logic for App.xaml 18 | /// 19 | public partial class App : Application 20 | { 21 | private ServiceProvider serviceProvider; 22 | 23 | public App() 24 | { 25 | ServiceCollection services = new ServiceCollection(); 26 | ConfigureServices(services); 27 | serviceProvider = services.BuildServiceProvider(); 28 | } 29 | 30 | private void ConfigureServices(ServiceCollection services) 31 | { 32 | services 33 | .AddTransient() 34 | .AddTransient() 35 | .AddTransient() 36 | .AddSingleton() 37 | .AddSingleton(services => new MainWindow 38 | { 39 | DataContext = services.GetRequiredService() 40 | }); 41 | } 42 | 43 | private void OnStartup(object sender, StartupEventArgs e) 44 | { 45 | var mainWindow = serviceProvider.GetRequiredService(); 46 | mainWindow.Show(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SirenSharp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33414.496 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SirenSharp", "SirenSharp\SirenSharp.csproj", "{1E562E51-3BD0-4269-92B1-F5219F541ECB}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodeWalker.Core", "lib\CodeWalker.Core\CodeWalker.Core.csproj", "{F509FD4B-3CA1-4A53-80A5-ED291BFB0E9C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1E562E51-3BD0-4269-92B1-F5219F541ECB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {1E562E51-3BD0-4269-92B1-F5219F541ECB}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {1E562E51-3BD0-4269-92B1-F5219F541ECB}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {1E562E51-3BD0-4269-92B1-F5219F541ECB}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {F509FD4B-3CA1-4A53-80A5-ED291BFB0E9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F509FD4B-3CA1-4A53-80A5-ED291BFB0E9C}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F509FD4B-3CA1-4A53-80A5-ED291BFB0E9C}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F509FD4B-3CA1-4A53-80A5-ED291BFB0E9C}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {36BBB666-730E-4032-8B08-77979CDE7A75} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /SirenSharp/ViewModels/ErrorsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Runtime.CompilerServices; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace SirenSharp.ViewModels 11 | { 12 | public class ErrorsViewModel : INotifyDataErrorInfo 13 | { 14 | private readonly Dictionary> propertyErrors = new Dictionary>(); 15 | public bool HasErrors => propertyErrors.Any(); 16 | public event EventHandler? ErrorsChanged; 17 | 18 | public IEnumerable GetErrors(string? propertyName) 19 | { 20 | if (propertyName is null) return propertyErrors.First().Value; 21 | return propertyErrors.GetValueOrDefault(propertyName); 22 | } 23 | 24 | public void AddError(string errorMessage, [CallerMemberName] string propertyName = null) 25 | { 26 | if (!propertyErrors.ContainsKey(propertyName)) 27 | { 28 | propertyErrors.Add(propertyName, new List()); 29 | } 30 | 31 | propertyErrors[propertyName].Add(errorMessage); 32 | OnErrorsChanged(propertyName); 33 | } 34 | 35 | private void OnErrorsChanged(string propertyName) 36 | { 37 | ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); 38 | } 39 | 40 | public void ClearErrors([CallerMemberName] string propertyName = null) 41 | { 42 | if (propertyErrors.Remove(propertyName)) 43 | { 44 | OnErrorsChanged(propertyName); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/Stats.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CodeWalker.GameFiles 8 | { 9 | 10 | 11 | public static class StatsNames 12 | { 13 | public static Dictionary Index = new Dictionary(); 14 | private static object syncRoot = new object(); 15 | 16 | public static volatile bool FullIndexBuilt = false; 17 | 18 | public static void Clear() 19 | { 20 | lock (syncRoot) 21 | { 22 | Index.Clear(); 23 | } 24 | } 25 | 26 | public static bool Ensure(string str) 27 | { 28 | uint hash = JenkHash.GenHash(str); 29 | if (hash == 0) return true; 30 | lock (syncRoot) 31 | { 32 | if (!Index.ContainsKey(hash)) 33 | { 34 | Index.Add(hash, str); 35 | return false; 36 | } 37 | } 38 | return true; 39 | } 40 | 41 | public static bool Ensure(string str, uint hash) 42 | { 43 | if (hash == 0) return true; 44 | lock (syncRoot) 45 | { 46 | if (!Index.ContainsKey(hash)) 47 | { 48 | Index.Add(hash, str); 49 | return false; 50 | } 51 | } 52 | return true; 53 | } 54 | 55 | public static string GetString(uint hash) 56 | { 57 | string res; 58 | lock (syncRoot) 59 | { 60 | if (!Index.TryGetValue(hash, out res)) 61 | { 62 | res = hash.ToString(); 63 | } 64 | } 65 | return res; 66 | } 67 | public static string TryGetString(uint hash) 68 | { 69 | string res; 70 | lock (syncRoot) 71 | { 72 | if (!Index.TryGetValue(hash, out res)) 73 | { 74 | res = string.Empty; 75 | } 76 | } 77 | return res; 78 | } 79 | 80 | } 81 | 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/World/Weapon.cs: -------------------------------------------------------------------------------- 1 | using CodeWalker.GameFiles; 2 | using SharpDX; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace CodeWalker.World 12 | { 13 | [TypeConverter(typeof(ExpandableObjectConverter))] public class Weapon 14 | { 15 | public string Name { get; set; } = string.Empty; 16 | public MetaHash NameHash { get; set; } = 0;//base weapon name hash 17 | public MetaHash ModelHash { get; set; } = 0;//weapon model name hash, can be _hi 18 | 19 | public YdrFile Ydr { get; set; } = null; 20 | public Drawable Drawable { get; set; } = null; 21 | 22 | public YmapEntityDef RenderEntity = new YmapEntityDef(); //placeholder entity object for rendering 23 | 24 | public Vector3 Position { get; set; } = Vector3.Zero; 25 | public Quaternion Rotation { get; set; } = Quaternion.Identity; 26 | 27 | 28 | public void Init(string name, GameFileCache gfc, bool hidef = true) 29 | { 30 | Name = name; 31 | var modelnamel = name.ToLowerInvariant(); 32 | MetaHash modelhash = JenkHash.GenHash(modelnamel); 33 | MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi"); 34 | var ydrhash = hidef ? modelhashhi : modelhash; 35 | 36 | NameHash = modelhash; 37 | ModelHash = ydrhash; 38 | 39 | var useHash = ModelHash; 40 | Ydr = gfc.GetYdr(ModelHash); 41 | if (Ydr == null) 42 | { 43 | useHash = NameHash; 44 | Ydr = gfc.GetYdr(NameHash); 45 | } 46 | 47 | while ((Ydr != null) && (!Ydr.Loaded)) 48 | { 49 | Thread.Sleep(1);//kinda hacky 50 | Ydr = gfc.GetYdr(useHash); 51 | } 52 | 53 | if (Ydr != null) 54 | { 55 | Drawable = Ydr.Drawable?.ShallowCopy() as Drawable; 56 | } 57 | 58 | 59 | UpdateEntity(); 60 | } 61 | 62 | 63 | public void UpdateEntity() 64 | { 65 | RenderEntity.SetPosition(Position); 66 | RenderEntity.SetOrientation(Rotation); 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/Utils/Matrices.cs: -------------------------------------------------------------------------------- 1 | using SharpDX; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CodeWalker 9 | { 10 | public static class MatrixExtensions 11 | { 12 | 13 | public static Vector3 MultiplyW(this Matrix m, Vector3 v) 14 | { 15 | float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; 16 | float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; 17 | float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; 18 | float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44; 19 | float iw = 1.0f / Math.Abs(w); 20 | return new Vector3(x * iw, y * iw, z * iw); 21 | } 22 | public static Vector3 Multiply(this Matrix m, Vector3 v) 23 | { 24 | float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; 25 | float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; 26 | float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; 27 | return new Vector3(x, y, z); 28 | //this quick mul ignores W... 29 | } 30 | public static Vector3 MultiplyRot(this Matrix m, Vector3 v) 31 | { 32 | float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z));// + m.M41; 33 | float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z));// + m.M42; 34 | float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z));// + m.M43; 35 | return new Vector3(x, y, z); 36 | //this quick mul ignores W and translation... 37 | } 38 | 39 | public static Vector4 Multiply(this Matrix m, Vector4 v) 40 | { 41 | float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z)) + m.M41; 42 | float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z)) + m.M42; 43 | float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z)) + m.M43; 44 | float w = (((m.M14 * v.X) + (m.M24 * v.Y)) + (m.M34 * v.Z)) + m.M44; 45 | return new Vector4(x, y, z, w); 46 | } 47 | 48 | public static Quaternion ToQuaternion(this Matrix m) 49 | { 50 | var rmat = m; 51 | rmat.TranslationVector = Vector3.Zero; 52 | return Quaternion.RotationMatrix(rmat); 53 | } 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/YvrFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | 9 | namespace CodeWalker.GameFiles 10 | { 11 | public class YvrFile : GameFile, PackedFile 12 | { 13 | public VehicleRecordList Records { get; set; } 14 | 15 | public YvrFile() : base(null, GameFileType.Yvr) 16 | { 17 | } 18 | public YvrFile(RpfFileEntry entry) : base(entry, GameFileType.Yvr) 19 | { 20 | } 21 | 22 | public void Load(byte[] data, RpfFileEntry entry) 23 | { 24 | Name = entry.Name; 25 | RpfFileEntry = entry; 26 | 27 | 28 | RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; 29 | if (resentry == null) 30 | { 31 | throw new Exception("File entry wasn't a resource! (is it binary data?)"); 32 | } 33 | 34 | ResourceDataReader rd = new ResourceDataReader(resentry, data); 35 | 36 | //MemoryUsage = 0; 37 | 38 | try 39 | { 40 | Records = rd.ReadBlock(); 41 | 42 | } 43 | catch (Exception ex) 44 | { 45 | string err = ex.ToString(); 46 | } 47 | 48 | 49 | 50 | Loaded = true; 51 | 52 | } 53 | 54 | public byte[] Save() 55 | { 56 | byte[] data = ResourceBuilder.Build(Records, 1); //yvr is type/version 1... 57 | 58 | return data; 59 | } 60 | 61 | 62 | } 63 | 64 | 65 | public class YvrXml : MetaXmlBase 66 | { 67 | 68 | public static string GetXml(YvrFile yvr) 69 | { 70 | StringBuilder sb = new StringBuilder(); 71 | sb.AppendLine(XmlHeader); 72 | 73 | if (yvr?.Records != null) 74 | { 75 | VehicleRecordList.WriteXmlNode(yvr.Records, sb, 0); 76 | } 77 | 78 | return sb.ToString(); 79 | } 80 | 81 | } 82 | 83 | public class XmlYvr 84 | { 85 | 86 | public static YvrFile GetYvr(string xml, string inputFolder = "") 87 | { 88 | XmlDocument doc = new XmlDocument(); 89 | doc.LoadXml(xml); 90 | return GetYvr(doc, inputFolder); 91 | } 92 | 93 | public static YvrFile GetYvr(XmlDocument doc, string inputFolder = "") 94 | { 95 | YvrFile r = new YvrFile(); 96 | 97 | var node = doc.DocumentElement; 98 | if (node != null) 99 | { 100 | r.Records = VehicleRecordList.ReadXmlNode(node); 101 | } 102 | 103 | r.Name = Path.GetFileName(inputFolder); 104 | 105 | return r; 106 | } 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/Utils/Quaternions.cs: -------------------------------------------------------------------------------- 1 | using SharpDX; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CodeWalker 9 | { 10 | 11 | 12 | 13 | public static class QuaternionExtension 14 | { 15 | public static Vector3 Multiply(this Quaternion a, Vector3 b) 16 | { 17 | float axx = a.X * 2.0f; 18 | float ayy = a.Y * 2.0f; 19 | float azz = a.Z * 2.0f; 20 | float awxx = a.W * axx; 21 | float awyy = a.W * ayy; 22 | float awzz = a.W * azz; 23 | float axxx = a.X * axx; 24 | float axyy = a.X * ayy; 25 | float axzz = a.X * azz; 26 | float ayyy = a.Y * ayy; 27 | float ayzz = a.Y * azz; 28 | float azzz = a.Z * azz; 29 | return new Vector3(((b.X * ((1.0f - ayyy) - azzz)) + (b.Y * (axyy - awzz))) + (b.Z * (axzz + awyy)), 30 | ((b.X * (axyy + awzz)) + (b.Y * ((1.0f - axxx) - azzz))) + (b.Z * (ayzz - awxx)), 31 | ((b.X * (axzz - awyy)) + (b.Y * (ayzz + awxx))) + (b.Z * ((1.0f - axxx) - ayyy))); 32 | } 33 | 34 | public static Matrix ToMatrix(this Quaternion q) 35 | { 36 | float xx = q.X * q.X; 37 | float yy = q.Y * q.Y; 38 | float zz = q.Z * q.Z; 39 | float xy = q.X * q.Y; 40 | float zw = q.Z * q.W; 41 | float zx = q.Z * q.X; 42 | float yw = q.Y * q.W; 43 | float yz = q.Y * q.Z; 44 | float xw = q.X * q.W; 45 | Matrix result = new Matrix(); 46 | result.M11 = 1.0f - (2.0f * (yy + zz)); 47 | result.M12 = 2.0f * (xy + zw); 48 | result.M13 = 2.0f * (zx - yw); 49 | result.M14 = 0.0f; 50 | result.M21 = 2.0f * (xy - zw); 51 | result.M22 = 1.0f - (2.0f * (zz + xx)); 52 | result.M23 = 2.0f * (yz + xw); 53 | result.M24 = 0.0f; 54 | result.M31 = 2.0f * (zx + yw); 55 | result.M32 = 2.0f * (yz - xw); 56 | result.M33 = 1.0f - (2.0f * (yy + xx)); 57 | result.M34 = 0.0f; 58 | result.M41 = 0.0f; 59 | result.M42 = 0.0f; 60 | result.M43 = 0.0f; 61 | result.M44 = 1.0f; 62 | return result; 63 | } 64 | 65 | public static Vector4 ToVector4(this Quaternion q) 66 | { 67 | return new Vector4(q.X, q.Y, q.Z, q.W); 68 | } 69 | 70 | public static Quaternion FastLerp(Quaternion a, Quaternion b, float v) 71 | { 72 | var r = new Quaternion(); 73 | var vi = 1.0f - v; 74 | r.X = vi * a.X + v * b.X; 75 | r.Y = vi * a.Y + v * b.Y; 76 | r.Z = vi * a.Z + v * b.Z; 77 | r.W = vi * a.W + v * b.W; 78 | r.Normalize(); 79 | return r; 80 | } 81 | } 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/YwrFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | 9 | namespace CodeWalker.GameFiles 10 | { 11 | public class YwrFile : GameFile, PackedFile 12 | { 13 | public WaypointRecordList Waypoints { get; set; } 14 | 15 | public YwrFile() : base(null, GameFileType.Ywr) 16 | { 17 | } 18 | public YwrFile(RpfFileEntry entry) : base(entry, GameFileType.Ywr) 19 | { 20 | } 21 | 22 | public void Load(byte[] data, RpfFileEntry entry) 23 | { 24 | Name = entry.Name; 25 | RpfFileEntry = entry; 26 | 27 | 28 | RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; 29 | if (resentry == null) 30 | { 31 | throw new Exception("File entry wasn't a resource! (is it binary data?)"); 32 | } 33 | 34 | ResourceDataReader rd = new ResourceDataReader(resentry, data); 35 | 36 | //MemoryUsage = 0; 37 | 38 | try 39 | { 40 | Waypoints = rd.ReadBlock(); 41 | 42 | } 43 | catch (Exception ex) 44 | { 45 | string err = ex.ToString(); 46 | } 47 | 48 | 49 | 50 | Loaded = true; 51 | 52 | } 53 | 54 | public byte[] Save() 55 | { 56 | byte[] data = ResourceBuilder.Build(Waypoints, 1); //ywr is type/version 1... 57 | 58 | return data; 59 | } 60 | 61 | 62 | } 63 | 64 | 65 | public class YwrXml : MetaXmlBase 66 | { 67 | 68 | public static string GetXml(YwrFile ywr) 69 | { 70 | StringBuilder sb = new StringBuilder(); 71 | sb.AppendLine(XmlHeader); 72 | 73 | if (ywr?.Waypoints != null) 74 | { 75 | WaypointRecordList.WriteXmlNode(ywr.Waypoints, sb, 0); 76 | } 77 | 78 | return sb.ToString(); 79 | } 80 | 81 | } 82 | 83 | public class XmlYwr 84 | { 85 | 86 | public static YwrFile GetYwr(string xml, string inputFolder = "") 87 | { 88 | XmlDocument doc = new XmlDocument(); 89 | doc.LoadXml(xml); 90 | return GetYwr(doc, inputFolder); 91 | } 92 | 93 | public static YwrFile GetYwr(XmlDocument doc, string inputFolder = "") 94 | { 95 | YwrFile r = new YwrFile(); 96 | 97 | var node = doc.DocumentElement; 98 | if (node != null) 99 | { 100 | r.Waypoints = WaypointRecordList.ReadXmlNode(node); 101 | } 102 | 103 | r.Name = Path.GetFileName(inputFolder); 104 | 105 | return r; 106 | } 107 | 108 | } 109 | 110 | 111 | } 112 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/GameFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CodeWalker.GameFiles 8 | { 9 | public abstract class GameFile : Cacheable 10 | { 11 | public volatile bool Loaded = false; 12 | public volatile bool LoadQueued = false; 13 | public RpfFileEntry RpfFileEntry { get; set; } 14 | public string Name { get; set; } 15 | public string FilePath { get; set; } //used by the project form. 16 | public GameFileType Type { get; set; } 17 | 18 | 19 | 20 | public GameFile(RpfFileEntry entry, GameFileType type) 21 | { 22 | RpfFileEntry = entry; 23 | Type = type; 24 | MemoryUsage = (entry != null) ? entry.GetFileSize() : 0; 25 | if (entry is RpfResourceFileEntry) 26 | { 27 | var resent = entry as RpfResourceFileEntry; 28 | var newuse = resent.SystemSize + resent.GraphicsSize; 29 | MemoryUsage = newuse; 30 | } 31 | else if (entry is RpfBinaryFileEntry) 32 | { 33 | var binent = entry as RpfBinaryFileEntry; 34 | var newuse = binent.FileUncompressedSize; 35 | if (newuse > MemoryUsage) 36 | { 37 | MemoryUsage = newuse; 38 | } 39 | } 40 | else 41 | { 42 | } 43 | } 44 | 45 | public override string ToString() 46 | { 47 | return (string.IsNullOrEmpty(Name)) ? JenkIndex.GetString(Key.Hash) : Name; 48 | } 49 | 50 | 51 | } 52 | 53 | 54 | public enum GameFileType : int 55 | { 56 | Ydd = 0, 57 | Ydr = 1, 58 | Yft = 2, 59 | Ymap = 3, 60 | Ymf = 4, 61 | Ymt = 5, 62 | Ytd = 6, 63 | Ytyp = 7, 64 | Ybn = 8, 65 | Ycd = 9, 66 | Ypt = 10, 67 | Ynd = 11, 68 | Ynv = 12, 69 | Rel = 13, 70 | Ywr = 14, 71 | Yvr = 15, 72 | Gtxd = 16, 73 | Vehicles = 17, 74 | CarCols = 18, 75 | CarModCols = 19, 76 | CarVariations = 20, 77 | VehicleLayouts = 21, 78 | Peds = 22, 79 | Ped = 23, 80 | Yed = 24, 81 | Yld = 25, 82 | Yfd = 26, 83 | Heightmap = 27, 84 | Watermap = 28, 85 | Mrf = 29, 86 | DistantLights = 30, 87 | Ypdb = 31, 88 | } 89 | 90 | 91 | 92 | 93 | 94 | public struct GameFileCacheKey 95 | { 96 | public uint Hash { get; set; } 97 | public GameFileType Type { get; set; } 98 | 99 | public GameFileCacheKey(uint hash, GameFileType type) 100 | { 101 | Hash = hash; 102 | Type = type; 103 | } 104 | } 105 | 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /SirenSharp/Views/AboutWindow.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | https://github.com/BJDubb/SirenSharp 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | https://www.youtube.com/@bjdubb 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | https://discord.gg/GCMRtBNCXR 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | https://ko-fi.com/bjdubb 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /SirenSharp/Views/AWCPropertiesView.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /SirenSharp/Models/Sound.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Xml.Serialization; 9 | using CommunityToolkit.Mvvm.ComponentModel; 10 | using NAudio.Wave; 11 | 12 | namespace SirenSharp.Models 13 | { 14 | public class Sound : ObservableObject 15 | { 16 | private int samples; 17 | private int sampleRate; 18 | private TimeSpan length; 19 | private long size; 20 | private string name; 21 | 22 | public string Name 23 | { 24 | get => name; set 25 | { 26 | name = value; 27 | OnPropertyChanged(); 28 | } 29 | } 30 | private string audioPath { get; set; } 31 | public string AudioPath 32 | { 33 | get => audioPath; set 34 | { 35 | UpdateFilePath(value); 36 | OnPropertyChanged(); 37 | } 38 | } 39 | [XmlIgnore] 40 | public int Samples 41 | { 42 | get => samples; set 43 | { 44 | samples = value; 45 | OnPropertyChanged(); 46 | } 47 | } 48 | [XmlIgnore] 49 | public int SampleRate 50 | { 51 | get => sampleRate; 52 | set 53 | { 54 | sampleRate = value; 55 | OnPropertyChanged(); 56 | } 57 | } 58 | [XmlIgnore] 59 | public TimeSpan Length 60 | { 61 | get => length; 62 | set 63 | { 64 | length = value; 65 | OnPropertyChanged(); 66 | } 67 | } 68 | public string FileName => new FileInfo(AudioPath).Name; 69 | [XmlIgnore] 70 | public long Size 71 | { 72 | get => size; 73 | set 74 | { 75 | size = value; 76 | OnPropertyChanged(); 77 | } 78 | } 79 | 80 | public Sound() 81 | { 82 | 83 | } 84 | 85 | public Sound(string filePath) 86 | { 87 | AudioPath = filePath; 88 | Name = Path.GetFileNameWithoutExtension(filePath).ToLower().Replace(" ", "_"); 89 | } 90 | 91 | private void UpdateFilePath(string filePath) 92 | { 93 | if (File.Exists(filePath)) 94 | { 95 | using (var wfr = new WaveFileReader(filePath)) 96 | { 97 | Length = wfr.TotalTime; 98 | SampleRate = wfr.WaveFormat.SampleRate; 99 | int len = (int)wfr.Length; 100 | int other = wfr.WaveFormat.Channels * wfr.WaveFormat.BitsPerSample / 8; 101 | Samples = len / other; 102 | } 103 | 104 | Size = new FileInfo(filePath).Length; 105 | } 106 | 107 | audioPath = filePath; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/GameFiles/FileTypes/PedFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.IO; 7 | using System.Xml; 8 | 9 | using TC = System.ComponentModel.TypeConverterAttribute; 10 | using EXP = System.ComponentModel.ExpandableObjectConverter; 11 | 12 | namespace CodeWalker.GameFiles 13 | { 14 | [TC(typeof(EXP))] public class PedFile : GameFile, PackedFile 15 | { 16 | public Meta Meta { get; set; } 17 | public PsoFile Pso { get; set; } 18 | public RbfFile Rbf { get; set; } 19 | public string Xml { get; set; } 20 | 21 | public MCPedVariationInfo VariationInfo { get; set; } 22 | 23 | 24 | 25 | public string[] Strings { get; set; } 26 | 27 | 28 | 29 | 30 | public PedFile() : base(null, GameFileType.Ped) 31 | { } 32 | public PedFile(RpfFileEntry entry) : base(entry, GameFileType.Ped) 33 | { } 34 | 35 | public void Load(byte[] data, RpfFileEntry entry) 36 | { 37 | RpfFileEntry = entry; 38 | Name = entry.Name; 39 | FilePath = Name; 40 | 41 | 42 | RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; 43 | if (resentry == null) 44 | { 45 | NonMetaLoad(data); 46 | Loaded = true; 47 | return; 48 | } 49 | 50 | 51 | ResourceDataReader rd = new ResourceDataReader(resentry, data); 52 | 53 | Meta = rd.ReadBlock(); 54 | 55 | 56 | LoadMeta(); 57 | 58 | 59 | 60 | Loaded = true; 61 | } 62 | 63 | 64 | 65 | private void LoadMeta() 66 | { 67 | var vVariationInfo = MetaTypes.GetTypedData(Meta, MetaName.CPedVariationInfo); 68 | VariationInfo = new MCPedVariationInfo(); 69 | VariationInfo.Load(Meta, vVariationInfo); 70 | 71 | Strings = MetaTypes.GetStrings(Meta); 72 | if (Strings != null) 73 | { 74 | foreach (string str in Strings) 75 | { 76 | JenkIndex.Ensure(str); //just shove them in there 77 | } 78 | } 79 | } 80 | private void LoadPso() 81 | { 82 | 83 | var vVariationInfo = PsoTypes.GetRootItem(Pso); 84 | VariationInfo = new MCPedVariationInfo(); 85 | VariationInfo.Load(Pso, vVariationInfo); 86 | 87 | } 88 | 89 | 90 | 91 | private void NonMetaLoad(byte[] data) 92 | { 93 | //non meta not supported yet! but see what's in there... 94 | MemoryStream ms = new MemoryStream(data); 95 | if (RbfFile.IsRBF(ms)) 96 | { 97 | Rbf = new RbfFile(); 98 | Rbf.Load(ms); 99 | } 100 | else if (PsoFile.IsPSO(ms)) 101 | { 102 | Pso = new PsoFile(); 103 | Pso.Load(ms); 104 | LoadPso(); 105 | } 106 | else 107 | { 108 | } 109 | 110 | } 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lib/CodeWalker.Core/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CodeWalker.Core.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeWalker.Core.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Byte[]. 65 | /// 66 | internal static byte[] magic { 67 | get { 68 | object obj = ResourceManager.GetObject("magic", resourceCulture); 69 | return ((byte[])(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SirenSharp/Views/NewProjectWindow.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |