public void Reload(LevelSettings settings, IDialogHandler progressReporter = null) { if (string.IsNullOrEmpty(Path)) { Sounds = null; LoadException = new Exception("Path is empty."); return; } // Load the catalog try { var path = settings.MakeAbsolute(Path); if (File.Exists(path)) { WadSounds newSounds = WadSounds.ReadFromFile(path); Sounds = newSounds; LoadException = null; } else { LoadException = new Exception("File not found: " + path); } } catch (Exception exc) { logger.Warn(exc, "Unable to load catalog '" + Path + "'."); Sounds = null; LoadException = exc; } }
private bool OpenArchive(string filename = null) { CheckForSavedChanges(); if (filename == null) { filename = LevelFileDialog.BrowseFile(this, null, _configuration.SoundTool_LastCatalogPath, "Select archive to open", WadSounds.FormatExtensions, null, false); } if (filename == null || !File.Exists(filename)) { return(false); } // Read the sounds archive in XML or TXT format var sounds = WadSounds.ReadFromFile(filename); if (sounds == null) { return(false); } // File read correctly, save catalog path to recent _configuration.SoundTool_LastCatalogPath = filename; dgvSoundInfos.Rows.Clear(); // Fill the grid sounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id)); foreach (var soundInfo in sounds.SoundInfos) { dgvSoundInfos.Rows.Add(soundInfo.Id.ToString().PadLeft(4, '0'), soundInfo.Name); dgvSoundInfos.Rows[dgvSoundInfos.Rows.Count - 1].Tag = soundInfo; } SelectSoundInfo(); // Decide on saved flag based on file format. // If TXT was loaded (i.e. conversion was made), mark the file as unsaved. var extension = Path.GetExtension(filename); if (extension == ".xml") { _currentArchive = filename; Saved = true; } else { _currentArchive = null; Saved = false; } return(true); }
private void Prj2SoundsConversionDialog_Load(object sender, EventArgs e) { // Try to load default Sounds.xml if (File.Exists("Catalogs\\Sounds.tr4.xml")) { string filename = Path.GetDirectoryName(Application.ExecutablePath) + "\\Catalogs\\Sounds.tr4.xml"; var sounds = WadSounds.ReadFromFile(filename); if (sounds != null) { Sounds = sounds; tbSoundsCatalogPath.Text = filename; } } // Add rows ReloadSoundInfos(); }
private void butSearchSoundsCatalogPath_Click(object sender, EventArgs e) { string result = LevelFileDialog.BrowseFile(this, "Select sound catalog to import", LevelSettings.FileFormatsSoundsCatalogs, false); if (result != null) { var sounds = WadSounds.ReadFromFile(result); if (sounds == null) { return; } Sounds = sounds; tbSoundsCatalogPath.Text = result; } }
public static Wad2 ConvertTr4Wad(Tr4Wad oldWad, IDialogHandler progressReporter) { logger.Info("Converting TR4 WAD to Wad2"); var wad = new Wad2() { SoundSystem = SoundSystem.Xml, GameVersion = TRVersion.Game.TR4 }; // Convert all textures Dictionary <int, WadTexture> textures = ConvertTr4TexturesToWadTexture(oldWad, wad); logger.Info("Textures read."); // Convert sounds var sfxPath = Path.GetDirectoryName(oldWad.FileName) + "\\" + Path.GetFileNameWithoutExtension(oldWad.FileName) + ".sfx"; if (File.Exists(sfxPath)) { wad.Sounds = WadSounds.ReadFromFile(sfxPath); logger.Info("Sounds read."); } // Convert moveables for (int i = 0; i < oldWad.Moveables.Count; i++) { ConvertTr4MoveableToWadMoveable(wad, oldWad, i, textures); } logger.Info("Moveables read."); // Convert statics for (int i = 0; i < oldWad.Statics.Count; i++) { ConvertTr4StaticMeshToWadStatic(wad, oldWad, i, textures); } logger.Info("Statics read."); // Convert sprites ConvertTr4Sprites(wad, oldWad); logger.Info("Sprites read."); return(wad); }
public static bool ConvertPrj2ToNewSoundFormat(Level level, string src, string dest, string soundsCatalog, bool save) { /* PROCEDURE: * 1. Collect all sound sources of level: if embedded sound info is null, then it's a sound source * that is referencing a Wad file and we should just remap it, otherwise it's a custom sound source * created inside Tomb Editor and we must export it to Xml and we must export samples too * 2. Try to guess the ID for Wad sounds and generate instead a new ID above 602 for custom sounds * (ID = 602 is the start of TR1 area of extended soundmap of TRNG and it should be rarely used) * 3. Show the dialog to the user. Here he can load an additional catalog if he changed sounds via TRLE tools * 4. Assign new IDs and new names to sound infos * 5. Remap sound sources * 6. Export samples if needed * 7. Save Prj2 + Xml if custom sounds are present */ try { // Check for sound system if (level.Settings.SoundSystem == SoundSystem.Xml) { return(true); } // Infer the wad version from level version TRVersion.Game version = level.Settings.GameVersion.Native(); // Collect all sounds to remap var conversionList = new List <SoundInfoConversionRow>(); // We start from sound id = 602 which is the TR1 sound area of TRNG extended soundmap. // This area is reserved for TR1 enemies and so it *** should *** be used rarely int lastSoundId = 602; foreach (var room in level.Rooms) { if (room != null) { foreach (var obj in room.Objects) { if (obj is SoundSourceInstance) { SoundSourceInstance soundSource = obj as SoundSourceInstance; if (soundSource.WadReferencedSoundName != null && soundSource.WadReferencedSoundName != "") { if (!conversionList.Select(f => f.OldName).Contains(soundSource.WadReferencedSoundName)) { // First try to get sound name from TrCatalog int newId = TrCatalog.TryGetSoundInfoIdByDescription(version, soundSource.WadReferencedSoundName); var row = new SoundInfoConversionRow(null, soundSource.WadReferencedSoundName); if (newId == -1) { // If sound was not found in catalog, then assign a generic Id and ask to the user row.NewName = Regex.Replace(soundSource.WadReferencedSoundName, "[^A-Za-z0-9 _]", "").ToUpper(); row.NewId = lastSoundId++; } else { // Otherwise, we are lucky, and we can just assign the correct Id row.NewName = TrCatalog.GetOriginalSoundName(version, (uint)newId); row.NewId = newId; } conversionList.Add(row); } } else if (soundSource.EmbeddedSoundInfo != null) { bool found = false; foreach (var r in conversionList) { if (r.SoundInfo != null && r.SoundInfo == soundSource.EmbeddedSoundInfo) { found = true; break; } } if (found) { continue; } // Let's first try a search in TrCatalog, maybe we are lucky // First try to get sound name from TrCatalog /*int newId = TrCatalog.TryGetSoundInfoIdByDescription(version, soundSource.EmbeddedSoundInfo.Name); * * var row = new SoundInfoConversionRow(soundSource.EmbeddedSoundInfo, soundSource.EmbeddedSoundInfo.Name); * if (newId == -1) * { * // If sound was not found in catalog, then assign a generic Id and ask to the user * row.NewName = Regex.Replace(soundSource.EmbeddedSoundInfo.Name, "[^A-Za-z0-9 _]", "").ToUpper(); * row.NewId = lastSoundId++; * } * else * { * // Otherwise, we are lucky, and we can just assign the correct Id * row.NewName = TrCatalog.GetOriginalSoundName(version, (uint)newId); * row.NewId = newId; * }*/ // TODO: Lwmte proposed to also there check in TrCatalog, but we should assume that // embedded sound sources are custom sound sources, created by thhe user with custom samples // and we should think carrefully about this var row = new SoundInfoConversionRow(soundSource.EmbeddedSoundInfo, soundSource.EmbeddedSoundInfo.Name); row.NewName = Regex.Replace(soundSource.EmbeddedSoundInfo.Name, "[^A-Za-z0-9 _]", "").ToUpper(); row.NewId = lastSoundId++; // These flags are handle by Tomb Editor and set only for embedded sound sources row.SaveToXml = true; row.ExportSamples = true; conversionList.Add(row); } } } } } WadSounds sounds = null; // Now we'll show a dialog with all conversion rows and the user will need to make some choices if (conversionList.Count != 0) { using (var form = new Prj2SoundsConversionDialog(version, conversionList)) { if (form.ShowDialog() == DialogResult.Cancel) { return(false); } // If the user has loaded an additional catalog, let's get a pointer to it if (form.Sounds != null) { sounds = form.Sounds; } } } // Assign new Id and name foreach (var row in conversionList) { if (row.SoundInfo != null) { row.SoundInfo.Id = row.NewId; row.SoundInfo.Name = row.NewName; } } // We'll export only embedded sound sources var newSounds = new WadSounds(); // Remap sound sources foreach (var room in level.Rooms) { if (room != null) { foreach (var obj in room.Objects) { if (obj is SoundSourceInstance) { SoundSourceInstance soundSource = obj as SoundSourceInstance; if (soundSource.WadReferencedSoundName != null && soundSource.WadReferencedSoundName != "") { soundSource.SoundId = -1; foreach (var row in conversionList) { if (row.OldName == soundSource.WadReferencedSoundName && row.NewId != -1) { soundSource.SoundId = row.NewId; break; } } soundSource.WadReferencedSoundName = ""; soundSource.EmbeddedSoundInfo = null; } else if (soundSource.EmbeddedSoundInfo != null) { // We export embedded sound infos if (!newSounds.SoundInfos.Contains(soundSource.EmbeddedSoundInfo)) { newSounds.SoundInfos.Add(soundSource.EmbeddedSoundInfo); } soundSource.SoundId = -1; foreach (var row in conversionList) { if (row.SoundInfo == soundSource.EmbeddedSoundInfo && row.NewId != -1) { soundSource.SoundId = row.NewId; // Try to bind samples from additional catalog, if loaded /*if (sounds != null) * { * WadSoundInfo catalogInfo = sounds.TryGetSoundInfo(row.NewId); * if (catalogInfo != null && catalogInfo.Samples.Count > 0) * { * soundSource.EmbeddedSoundInfo.Samples.Clear(); * soundSource.EmbeddedSoundInfo.Samples.AddRange(catalogInfo.Samples); * // TODO: in theory if valid samples are found in catalog, we shouldn't need to * // export them * row.ExportSamples = false; * } * }*/ break; } } soundSource.WadReferencedSoundName = ""; soundSource.EmbeddedSoundInfo = null; } } } } } // Export samples foreach (var row in conversionList) { if (row.SoundInfo != null && row.ExportSamples) { var samples = new List <string>(); foreach (var sample in row.SoundInfo.Samples) { if (sample.IsLoaded) { string sampleName = Path.GetFileNameWithoutExtension(dest) + "_" + row.NewName.ToLower() + "_" + row.SoundInfo.Samples.IndexOf(sample) + ".wav"; samples.Add(sampleName); File.WriteAllBytes(Path.GetDirectoryName(dest) + "\\" + sampleName, sample.Data); } } row.SoundInfo.Samples.Clear(); foreach (var sample in samples) { row.SoundInfo.Samples.Add(new WadSample(sample)); } } } // Sort sound infos newSounds.SoundInfos.Sort((a, b) => a.Id.CompareTo(b.Id)); // Make a backup copy if (save && src == dest) { int index = 0; string backupFilename = ""; while (true) { backupFilename = dest + "." + index + ".bak"; if (!File.Exists(backupFilename)) { break; } index++; } File.Copy(src, backupFilename, true); } // Save Xml to file if (newSounds.SoundInfos.Count != 0) { string xmlFileName = Path.GetDirectoryName(dest) + "\\" + Path.GetFileNameWithoutExtension(dest) + ".xml"; WadSounds.SaveToXml(xmlFileName, newSounds); // Assign Xml to level settings level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings, level.Settings.MakeRelative(xmlFileName, VariableType.LevelDirectory))); } level.Settings.SoundSystem = SoundSystem.Xml; // Try to get Xml and SFX files foreach (var wadRef in level.Settings.Wads) { if (wadRef != null && wadRef.LoadException == null) { string wadPath = level.Settings.MakeAbsolute(wadRef.Path); string extension = Path.GetExtension(wadPath).ToLower(); if (extension == ".wad") { string sfxPath = Path.GetDirectoryName(wadPath) + "\\" + Path.GetFileNameWithoutExtension(wadPath) + ".sfx"; if (File.Exists(sfxPath)) { sounds = WadSounds.ReadFromFile(sfxPath); if (sounds != null) { level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings, level.Settings.MakeRelative(sfxPath, VariableType.LevelDirectory))); } } } else if (extension == ".wad2") { string xmlPath = Path.GetDirectoryName(wadPath) + "\\" + Path.GetFileNameWithoutExtension(wadPath) + ".xml"; if (File.Exists(xmlPath)) { sounds = WadSounds.ReadFromFile(xmlPath); if (sounds != null) { level.Settings.SoundsCatalogs.Add(new ReferencedSoundsCatalog(level.Settings, level.Settings.MakeRelative(xmlPath, VariableType.LevelDirectory))); } } } } } // Assign sounds if possible foreach (var soundRef in level.Settings.SoundsCatalogs) { if (soundRef.LoadException == null) { foreach (var sound in soundRef.Sounds.SoundInfos) { if (!level.Settings.SelectedSounds.Contains(sound.Id)) { level.Settings.SelectedSounds.Add(sound.Id); } } } } // Save Prj2 with Xml sounds if (save) { using (var stream = File.OpenWrite(dest)) Prj2Writer.SaveToPrj2(stream, level); } return(true); } catch (Exception ex) { return(false); } }