private void OnExport() { if (SelectedTerritory == null) { return; } try { Territory territory = new Territory(SelectedTerritory.TerritoryType); if (territory == null) { System.Windows.MessageBox.Show($"Could not find territory data for {SelectedTerritory.Name}", "Territory not found", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); return; } _Progress = new Ookii.Dialogs.Wpf.ProgressDialog() { WindowTitle = "Exporting territory " + territory.Name }; _Progress.Show(); _Progress.DoWork += (object sender, System.ComponentModel.DoWorkEventArgs eventArgs) => { _Export(territory, (Ookii.Dialogs.Wpf.ProgressDialog)sender); }; } catch (Exception e) { System.Windows.MessageBox.Show(string.Format("Error reading territory for {0}:{1}{2}", SelectedTerritory.Name, Environment.NewLine, e), "Failure to read territory", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); } _Progress = null; }
private void OnBruteForce() { IsBruteForceAvailable = false; var progDlg = new Ookii.Dialogs.Wpf.ProgressDialog(); progDlg.WindowTitle = "Brute-forcing"; progDlg.Text = "This is going to take a while..."; progDlg.DoWork += DoBruteForceWork; progDlg.RunWorkerCompleted += OnBruteForceComplete; progDlg.ShowDialog(System.Windows.Application.Current.MainWindow); progDlg.ProgressBarStyle = Ookii.Dialogs.Wpf.ProgressBarStyle.ProgressBar; progDlg.ShowTimeRemaining = true; }
private void ExtractCommand_Executed(object sender, ExecutedRoutedEventArgs e) { if (FileListView.SelectedItems.Count == 0) { // Shouldn't happen (due to ExtractCommand_CanExecute), but check anyway. return; } AppModel model = (AppModel)DataContext; using var browserDialog = new FolderBrowserDialog { ShowNewFolderButton = true, UseDescriptionForTitle = true, Description = "Select folder to extract to", }; Window window = Window.GetWindow(this); if (!browserDialog.ShowDialog(window)) { return; } MsiFile[] filesToExtract = new MsiFile[FileListView.SelectedItems.Count]; FileListView.SelectedItems.CopyTo(filesToExtract, 0); string text = $"Extracting {filesToExtract.Length} files..."; if (filesToExtract.Length == 1) { text = "Extracting one file..."; } using var progressDialog = new ProgressDialog { MinimizeBox = false, WindowTitle = "Extracting Files...", CancellationText = "Canceling...", UseCompactPathsForDescription = true, Text = text, }; void DoWork(object?sender, DoWorkEventArgs e) { if (string.IsNullOrEmpty(model.MsiPath)) { throw new InvalidOperationException("MsiPath not set, we should not have gotten here"); } try { Wixtracts.ExtractFiles(new LessIO.Path(model.MsiPath), browserDialog.SelectedPath, filesToExtract, (arg) => { var progress = (Wixtracts.ExtractionProgress)arg; if (progressDialog.CancellationPending) { throw new OperationCanceledException(); } int percentProgress; string message; if (progress.Activity == Wixtracts.ExtractionActivity.Initializing) { message = "Initializing extraction"; percentProgress = 0; } else if (progress.Activity == Wixtracts.ExtractionActivity.Uncompressing) { message = "Decompressing CAB file"; percentProgress = 0; } else if (progress.Activity == Wixtracts.ExtractionActivity.ExtractingFile) { double fraction = (double)progress.FilesExtractedSoFar / (double)progress.TotalFileCount; percentProgress = (int)Math.Round(fraction * 100); message = progress.CurrentFileName; } else if (progress.Activity == Wixtracts.ExtractionActivity.Complete) { message = "Finishing up"; percentProgress = 100; } else { throw new ArgumentException("Invalid ExtractionActivity"); } this.Dispatcher.Invoke(() => progressDialog.ReportProgress(percentProgress, null, message)); }); } catch (System.IO.FileNotFoundException ex) { #pragma warning disable SA1130 // Use lambda syntax (not valid syntax here for some reason) Dispatcher.BeginInvoke((Action) delegate #pragma warning restore SA1130 // Use lambda syntax { TaskDialogPage page = new TaskDialogPage(); page.Instruction = "Cannot extract the specified files."; page.Text = $"The file \"{ex.FileName}\" was not found."; page.Icon = TaskDialogIcon.Get(TaskDialogStandardIcon.Error); page.StandardButtons.Add(TaskDialogResult.Close); page.AllowCancel = true; TaskDialog dialog = new TaskDialog(); dialog.Page = page; dialog.Show(window); }); return; } catch (Exception ex) { // Rethrow the exception on the main thread. Dispatcher.Invoke(() => throw ex); } } progressDialog.DoWork += DoWork; progressDialog.ShowDialog(window); }
private void _Export(Territory territory, Ookii.Dialogs.Wpf.ProgressDialog progress) { string teriName = territory.Name; try { string currentTitle = ""; var _ExportDirectory = $"./{territory.Name}/"; Dictionary <string, int> objCount = new Dictionary <string, int>(); if (!System.IO.Directory.Exists(Environment.CurrentDirectory + $"{_ExportDirectory}")) { System.IO.Directory.CreateDirectory(Environment.CurrentDirectory + $"{_ExportDirectory}"); } var teriFileName = $"./{_ExportDirectory}/{territory.Name}.obj"; var fileName = teriFileName; var lightsFileName = $"./{_ExportDirectory}/{territory.Name}-lights.txt"; var _ExportFileName = fileName; { var f = System.IO.File.Create(fileName); f.Close(); } System.IO.File.AppendAllText(fileName, $"o {territory.Name}\n"); System.IO.File.WriteAllText(lightsFileName, ""); int lights = 0; List <string> lightStrs = new List <string>() { "import bpy" }; List <string> vertStr = new List <string>(); Dictionary <string, bool> exportedPaths = new Dictionary <string, bool>(); UInt64 vs = 1, vt = 1, vn = 1, i = 0; Matrix IdentityMatrix = Matrix.Identity; void ExportMaterials(Material m, string path) { vertStr.Add($"mtllib {path}.mtl"); bool found = false; if (exportedPaths.TryGetValue(path, out found)) { return; } exportedPaths.Add(path, true); System.IO.File.Delete($"{_ExportDirectory}/{path}.mtl"); System.IO.File.AppendAllText($"{_ExportDirectory}/{path}.mtl", $"newmtl {path}\n"); foreach (var img in m.TexturesFiles) { var mtlName = img.Path.Replace('/', '_'); if (exportedPaths.TryGetValue(path + mtlName, out found)) { continue; } SaintCoinach.Imaging.ImageConverter.Convert(img).Save($"{_ExportDirectory}/{mtlName}.png"); if (mtlName.Contains("_dummy_")) { continue; } if (mtlName.Contains("_n.tex")) { System.IO.File.AppendAllText($"./{_ExportDirectory}/{path}.mtl", $"bump {mtlName}.png\n"); } else if (mtlName.Contains("_s.tex")) { System.IO.File.AppendAllText($"./{_ExportDirectory}/{path}.mtl", $"map_Ks {mtlName}.png\n"); } else if (!mtlName.Contains("_a.tex")) { System.IO.File.AppendAllText($"./{_ExportDirectory}/{path}.mtl", $"map_Kd {mtlName}.png\n"); } else { System.IO.File.AppendAllText($"./{_ExportDirectory}/{path}.mtl", $"map_Ka {mtlName}.png\n"); } exportedPaths.Add(path + mtlName, true); } } Matrix CreateMatrix(SaintCoinach.Graphics.Vector3 translation, SaintCoinach.Graphics.Vector3 rotation, SaintCoinach.Graphics.Vector3 scale) { return(Matrix.Scaling(scale.ToDx()) * Matrix.RotationX(rotation.X) * Matrix.RotationY(rotation.Y) * Matrix.RotationZ(rotation.Z) * Matrix.Translation(translation.ToDx())); } void ExportMesh(ref Mesh mesh, ref Matrix lgbTransform, ref string materialName, ref string modelFilePath, ref Matrix rootGimTransform, ref Matrix currGimTransform, ref Matrix modelTransform) { i++; if (progress.CancellationPending) { throw new ExportCancelException("User canceled export"); } var k = 0; UInt64 tempVs = 0, tempVn = 0, tempVt = 0; foreach (var v in mesh.Vertices) { var x = v.Position.Value.X; var y = v.Position.Value.Y; var z = v.Position.Value.Z; var w = v.Position.Value.W; var transform = (modelTransform * rootGimTransform * currGimTransform) * lgbTransform; var t = Matrix.Translation(x, y, z) * transform; x = t.TranslationVector.X; y = t.TranslationVector.Y; z = t.TranslationVector.Z; // .Replace(',','.') cause decimal separator locale memes if (v.Color != null) { vertStr.Add($"v {x} {y} {z} {v.Color.Value.X} {v.Color.Value.Y} {v.Color.Value.Z} {v.Color.Value.W}".Replace(',', '.')); } else { vertStr.Add($"v {x} {y} {z}".Replace(',', '.')); } tempVs++; vertStr.Add($"vn {v.Normal.Value.X} {v.Normal.Value.Y} {v.Normal.Value.Z}".Replace(',', '.')); tempVn++; if (v.UV != null) { vertStr.Add($"vt {v.UV.Value.X} {v.UV.Value.Y * -1.0}".Replace(',', '.')); tempVt++; } } vertStr.Add($"g {modelFilePath}_{i.ToString()}_{k.ToString()}"); vertStr.Add($"usemtl {materialName}"); for (UInt64 j = 0; j + 3 < (UInt64)mesh.Indices.Length + 1; j += 3) { vertStr.Add( $"f " + $"{mesh.Indices[j] + vs}/{mesh.Indices[j] + vt}/{mesh.Indices[j] + vn} " + $"{mesh.Indices[j + 1] + vs}/{mesh.Indices[j + 1] + vt}/{mesh.Indices[j + 1] + vn} " + $"{mesh.Indices[j + 2] + vs}/{mesh.Indices[j + 2] + vt}/{mesh.Indices[j + 2] + vn}"); } if (i % 1000 == 0) { System.IO.File.AppendAllLines(_ExportFileName, vertStr); vertStr.Clear(); } vs += tempVs; vn += tempVn; vt += tempVt; } Dictionary <string, bool> exportedSgbFiles = new Dictionary <string, bool>(); void ExportSgbModels(SaintCoinach.Graphics.Sgb.SgbFile sgbFile, ref Matrix lgbTransform, ref Matrix rootGimTransform, ref Matrix currGimTransform) { foreach (var sgbGroup in sgbFile.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { bool newGroup = true; foreach (var mdl in sgbGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbModelEntry>()) { Model hq = null; var filePath = mdl.ModelFilePath; var modelTransform = CreateMatrix(mdl.Header.Translation, mdl.Header.Rotation, mdl.Header.Scale); progress.ReportProgress(0, currentTitle, filePath); try { hq = mdl.Model.Model.GetModel(ModelQuality.High); } catch (Exception e) { System.Diagnostics.Debug.WriteLine($"Unable to load model for {mdl.Name} path: {filePath}. Exception: {e.Message}"); continue; } if (newGroup) { //vertStr.Add($"o {sgbFile.File.Path}_{sgbGroup.Name}_{i}"); newGroup = false; } for (var j = 0; j < hq.Meshes.Length; ++j) { var mesh = hq.Meshes[j]; var mtl = mesh.Material.Get(); var path = mtl.File.Path.Replace('/', '_').Replace(".mtrl", ".tex"); ExportMaterials(mtl, path); ExportMesh(ref mesh, ref lgbTransform, ref path, ref filePath, ref rootGimTransform, ref currGimTransform, ref modelTransform); } } foreach (var light in sgbGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbLightEntry>()) { var pos = light.Header.Translation; var transform = (Matrix.Translation(pos.X, pos.Y, pos.Z) * (rootGimTransform * currGimTransform) * lgbTransform).TranslationVector; pos.X = transform.X; pos.Y = transform.Y; pos.Z = transform.Z; lightStrs.Add($"#LIGHT_{lights++}_{light.Name}_{light.Header.UnknownId}"); lightStrs.Add($"#pos {pos.X} {pos.Y} {pos.Z}"); lightStrs.Add($"#UNKNOWNFLAGS 0x{light.Header.UnknownFlag1:X8} 0x{light.Header.UnknownFlag2:X8} 0x{light.Header.UnknownFlag3:X8} 0x{light.Header.UnknownFlag4:X8}"); lightStrs.Add($"#UNKNOWN {light.Header.Rotation.X} {light.Header.Rotation.Y} {light.Header.Rotation.Z}"); lightStrs.Add($"#UNKNOWN2 {light.Header.Scale.X} {light.Header.Scale.Y} {light.Header.Scale.Z}"); lightStrs.Add($"#unk {light.Header.Entry1.X} {light.Header.Entry1.Y}"); lightStrs.Add($"#unk2 {light.Header.Entry2.X} {light.Header.Entry2.Y}"); lightStrs.Add($"#unk3 {light.Header.Entry3.X} {light.Header.Entry3.Y}"); lightStrs.Add($"#unk4 {light.Header.Entry4.X} {light.Header.Entry4.Y}"); lightStrs.Add(""); } } } progress.ReportProgress(0, currentTitle = "Terrain", ""); if (territory.Terrain != null) { foreach (var part in territory.Terrain.Parts) { var hq = part.Model.GetModel(ModelQuality.High); var filePath = hq.Definition.File.Path; var lgbTransform = CreateMatrix(part.Translation, part.Rotation, part.Scale); progress.ReportProgress(0, currentTitle, part.Model.File.Path); for (var j = 0; j < hq.Meshes.Length; ++j) { var mesh = hq.Meshes[j]; var mtl = mesh.Material.Get(); var path = mtl.File.Path.Replace('/', '_').Replace(".mtrl", ".tex"); ExportMaterials(mtl, path); ExportMesh(ref mesh, ref lgbTransform, ref path, ref filePath, ref IdentityMatrix, ref IdentityMatrix, ref IdentityMatrix); } } } System.IO.File.AppendAllLines(_ExportFileName, vertStr); vertStr.Clear(); vs = 1; vn = 1; vt = 1; i = 0; foreach (var lgb in territory.LgbFiles) { foreach (var lgbGroup in lgb.Groups) { bool newGroup = true; foreach (var part in lgbGroup.Entries) { if (part == null) { continue; } if (newGroup && (part.Type == SaintCoinach.Graphics.Lgb.LgbEntryType.Model || part.Type == SaintCoinach.Graphics.Lgb.LgbEntryType.Gimmick || part.Type == SaintCoinach.Graphics.Lgb.LgbEntryType.Light)) { progress.WindowTitle = $"Exporting {territory.Name} ({lgbGroup.Name})"; progress.ReportProgress(0, currentTitle = $"Exporting {territory.Name} Group {lgbGroup.Name}", $"Group {lgbGroup.Name}"); newGroup = false; System.IO.File.AppendAllLines(_ExportFileName, vertStr); vertStr.Clear(); //vertStr.Add($"o {lgbGroup.Name}"); vs = 1; vn = 1; vt = 1; i = 0; _ExportFileName = $"./{_ExportDirectory}/{teriName}-{lgbGroup.Name}.obj"; lightsFileName = $"./{_ExportDirectory}/{teriName}-{lgbGroup.Name}-lights.txt"; var f = System.IO.File.Create(_ExportFileName); f.Close(); f = System.IO.File.Create(lightsFileName); f.Close(); } switch (part.Type) { case SaintCoinach.Graphics.Lgb.LgbEntryType.Model: var asMdl = part as SaintCoinach.Graphics.Lgb.LgbModelEntry; progress.ReportProgress(0, currentTitle = "Exporting LgbModel", asMdl.ModelFilePath); if (asMdl.Model == null) { continue; } var hq = asMdl.Model.Model.GetModel(ModelQuality.High); var lgbTransform = CreateMatrix(asMdl.Header.Translation, asMdl.Header.Rotation, asMdl.Header.Scale); var filePath = asMdl.ModelFilePath; for (var j = 0; j < hq.Meshes.Length; ++j) { var mesh = hq.Meshes[j]; var mtl = mesh.Material.Get(); var path = mtl.File.Path.Replace('/', '_').Replace(".mtrl", ".tex"); ExportMaterials(mtl, path); ExportMesh(ref mesh, ref lgbTransform, ref path, ref filePath, ref IdentityMatrix, ref IdentityMatrix, ref IdentityMatrix); } break; case SaintCoinach.Graphics.Lgb.LgbEntryType.Gimmick: var asGim = part as SaintCoinach.Graphics.Lgb.LgbGimmickEntry; if (asGim.Gimmick == null) { continue; } progress.ReportProgress(0, currentTitle = $"Exporting Gimmick {asGim.Name} {asGim.Header.GimmickId}", ""); lgbTransform = CreateMatrix(asGim.Header.Translation, asGim.Header.Rotation, asGim.Header.Scale); ExportSgbModels(asGim.Gimmick, ref lgbTransform, ref IdentityMatrix, ref IdentityMatrix); foreach (var rootGimGroup in asGim.Gimmick.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { foreach (var rootGimEntry in rootGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGimmickEntry>()) { if (rootGimEntry.Gimmick != null) { var rootGimTransform = CreateMatrix(rootGimEntry.Header.Translation, rootGimEntry.Header.Rotation, rootGimEntry.Header.Scale); ExportSgbModels(rootGimEntry.Gimmick, ref lgbTransform, ref rootGimTransform, ref IdentityMatrix); foreach (var subGimGroup in rootGimEntry.Gimmick.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { foreach (var subGimEntry in subGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGimmickEntry>()) { var subGimTransform = CreateMatrix(subGimEntry.Header.Translation, subGimEntry.Header.Rotation, subGimEntry.Header.Scale); ExportSgbModels(subGimEntry.Gimmick, ref lgbTransform, ref rootGimTransform, ref subGimTransform); } } } } } break; case SaintCoinach.Graphics.Lgb.LgbEntryType.EventObject: var asEobj = part as SaintCoinach.Graphics.Lgb.LgbEventObjectEntry; if (asEobj.Gimmick == null) { continue; } progress.ReportProgress(0, currentTitle = $"Exporting EObj {asEobj.Name} {asEobj.Header.EventObjectId} {asEobj.Header.GimmickId}", ""); lgbTransform = CreateMatrix(asEobj.Header.Translation, asEobj.Header.Rotation, asEobj.Header.Scale); ExportSgbModels(asEobj.Gimmick, ref lgbTransform, ref IdentityMatrix, ref IdentityMatrix); foreach (var rootGimGroup in asEobj.Gimmick.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { foreach (var rootGimEntry in rootGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGimmickEntry>()) { if (rootGimEntry.Gimmick != null) { var rootGimTransform = CreateMatrix(rootGimEntry.Header.Translation, rootGimEntry.Header.Rotation, rootGimEntry.Header.Scale); ExportSgbModels(rootGimEntry.Gimmick, ref lgbTransform, ref rootGimTransform, ref IdentityMatrix); foreach (var subGimGroup in rootGimEntry.Gimmick.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { foreach (var subGimEntry in subGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGimmickEntry>()) { var subGimTransform = CreateMatrix(subGimEntry.Header.Translation, subGimEntry.Header.Rotation, subGimEntry.Header.Scale); ExportSgbModels(subGimEntry.Gimmick, ref lgbTransform, ref rootGimTransform, ref subGimTransform); } } } } foreach (var sgb1CEntry in rootGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGroup1CEntry>()) { if (sgb1CEntry.Gimmick != null) { ExportSgbModels(sgb1CEntry.Gimmick, ref lgbTransform, ref IdentityMatrix, ref IdentityMatrix); foreach (var subGimGroup in sgb1CEntry.Gimmick.Data.OfType <SaintCoinach.Graphics.Sgb.SgbGroup>()) { foreach (var subGimEntry in subGimGroup.Entries.OfType <SaintCoinach.Graphics.Sgb.SgbGimmickEntry>()) { var subGimTransform = CreateMatrix(subGimEntry.Header.Translation, subGimEntry.Header.Rotation, subGimEntry.Header.Scale); ExportSgbModels(subGimEntry.Gimmick, ref lgbTransform, ref IdentityMatrix, ref subGimTransform); } } } } } break; case SaintCoinach.Graphics.Lgb.LgbEntryType.Light: var asLight = part as SaintCoinach.Graphics.Lgb.LgbLightEntry; lightStrs.Add($"#LIGHT_{lights++}_{asLight.Name}_{asLight.Header.UnknownId}"); lightStrs.Add($"#pos {asLight.Header.Translation.X} {asLight.Header.Translation.Y} {asLight.Header.Translation.Z}"); lightStrs.Add($"#UNKNOWNFLAGS 0x{asLight.Header.UnknownFlag1:X8} 0x{asLight.Header.UnknownFlag2:X8} 0x{asLight.Header.UnknownFlag3:X8} 0x{asLight.Header.UnknownFlag4:X8}"); lightStrs.Add($"#UNKNOWN {asLight.Header.Rotation.X} {asLight.Header.Rotation.Y} {asLight.Header.Rotation.Z}"); lightStrs.Add($"#UNKNOWN2 {asLight.Header.Scale.X} {asLight.Header.Scale.Y} {asLight.Header.Scale.Z}"); lightStrs.Add($"#unk {asLight.Header.Entry1.X} {asLight.Header.Entry1.Y}"); lightStrs.Add($"#unk2 {asLight.Header.Entry2.X} {asLight.Header.Entry2.Y}"); lightStrs.Add($"#unk3 {asLight.Header.Entry3.X} {asLight.Header.Entry3.Y}"); lightStrs.Add($"#unk4 {asLight.Header.Entry4.X} {asLight.Header.Entry4.Y}"); lightStrs.Add(""); break; } } System.IO.File.AppendAllLines(lightsFileName, lightStrs); lightStrs.Clear(); } } System.IO.File.AppendAllLines(_ExportFileName, vertStr); vertStr.Clear(); System.IO.File.AppendAllLines(lightsFileName, lightStrs); lightStrs.Clear(); System.Windows.Forms.MessageBox.Show("Finished exporting " + territory.Name, "", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information); } catch (ExportCancelException e) { System.Windows.Forms.MessageBox.Show(e.Message, $"Canceled {teriName} export"); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.StackTrace); System.Windows.Forms.MessageBox.Show(e.StackTrace, $"Unable to export {teriName}"); } }
private void OnBruteForce() { IsBruteForceAvailable = false; var progDlg = new Ookii.Dialogs.Wpf.ProgressDialog(); progDlg.WindowTitle = "Brute-forcing"; progDlg.Text = "This is going to take a while..."; progDlg.DoWork += DoBruteForceWork; progDlg.RunWorkerCompleted += OnBruteForceComplete; progDlg.ShowDialog(System.Windows.Application.Current.MainWindow); progDlg.ProgressBarStyle = Ookii.Dialogs.Wpf.ProgressBarStyle.ProgressBar; progDlg.ShowTimeRemaining = true; }
private void Synchronize_Click(object sender, RoutedEventArgs e) { foreach (RepositoryDiffDataItem file in _diffData) { string reason; if (!file.ActionsAreValid(out reason)) { MessageBox.Show( string.Format("The highlighted file ({0}) has invalid actions selected:\n\n {1}", file.Filename, reason), "Invalid Actions", MessageBoxButton.OK, MessageBoxImage.Stop); DiffGrid.SelectedItem = file; return; } } // // Update the FooChangeSet with the selected actions. // foreach (RepositoryDiffDataItem file in _diffData) { foreach (Guid repoId in _changeSet.RepositoryIDs) { _changeSet[file.Filename].FileOperation[repoId] = file.FileOperation[repoId]; } } Dictionary<Guid, FooSyncUrl> basePaths = new Dictionary<Guid, FooSyncUrl>(); foreach (Guid repoId in _trees.Keys) { if (_trees[repoId].Base.AbsoluteUri.EndsWith("/")) { basePaths.Add(repoId, _trees[repoId].Base); } else { basePaths.Add(repoId, new FooSyncUrl(_trees[repoId].Base.ToString() + "/")); } } Ookii.Dialogs.Wpf.ProgressDialog dlg = new Ookii.Dialogs.Wpf.ProgressDialog(); dlg.WindowTitle = "Copying Files..."; dlg.Text = "Copying Files..."; dlg.ShowCancelButton = true; dlg.UseCompactPathsForDescription = true; dlg.ProgressBarStyle = Ookii.Dialogs.Wpf.ProgressBarStyle.ProgressBar; dlg.DoWork += new DoWorkEventHandler(CopyEngineWorker); dlg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CopyEngineFinished); dlg.Show(new Tuple<FooChangeSet, Dictionary<Guid, FooSyncUrl>>(_changeSet, basePaths)); }