public void ReadFromFile(string stylePath, bool saveSprites) { var context = new CancellableContext(null); bool cancelled; ReadFromFile(stylePath, saveSprites, context, out cancelled); }
public void BuildTextureAtlas() { var context = new CancellableContext(null); bool cancelled; BuildTextureAtlas(context, out cancelled); }
public void ConvertFiles(string sourcePath, string destinationPath) { var context = new CancellableContext(null); bool cancelled; ConvertFiles(sourcePath, destinationPath, context, out cancelled); }
private static void SaveSprites(StyleData styleData, ZipStorer zip, CancellableContext context) { //cars for (var i = styleData.SpriteBase.Car; i < styleData.SpriteBase.Ped; i++) { if (context.IsCancelling) { return; } SaveCarSprite(styleData, zip, i); } for (var i = styleData.SpriteBase.Ped; i < styleData.SpriteBase.CodeObj; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + i]; SaveSpriteRemap(styleData, styleData.SpriteEntries[i], basePalette, zip, "Peds/" + i); //var pedRemaps = new List<Remap>(53); //Ped Remaps are still broken... //for (var j = 0; j < 53; j++) //{ // var remapPalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + styleData.PaletteBase.Sprite + styleData.PaletteBase.CarRemap + j]; //...probably the bug lays here // pedRemaps.Add(new PedestrianRemap(j, remapPalette)); //} //styleData.Sprites.Add(i, new SpriteItem(SpriteType.Pedestrian, basePalette, pedRemaps)); styleData.Sprites.Add(i, new SpriteItem(SpriteType.Pedestrian, basePalette)); } //Code Obj for (var i = styleData.SpriteBase.CodeObj; i < styleData.SpriteBase.MapObj; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + i]; SaveSpriteRemap(styleData, styleData.SpriteEntries[i], basePalette, zip, "CodeObj/" + i); styleData.Sprites.Add(i, new SpriteItem(SpriteType.CodeObject, basePalette)); } //Map obj for (var i = styleData.SpriteBase.MapObj; i < styleData.SpriteBase.User; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + i]; SaveSpriteRemap(styleData, styleData.SpriteEntries[i], basePalette, zip, "MapObj/" + i); styleData.Sprites.Add(i, new SpriteItem(SpriteType.MapObject, basePalette)); } //User for (var i = styleData.SpriteBase.User; i < styleData.SpriteBase.Font; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + i]; SaveSpriteRemap(styleData, styleData.SpriteEntries[i], basePalette, zip, "User/" + i); styleData.Sprites.Add(i, new SpriteItem(SpriteType.User, basePalette)); } //Font //Some fonts looks wrong... for (var i = styleData.SpriteBase.Font; i < styleData.SpriteEntries.Length; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + i]; SaveSpriteRemap(styleData, styleData.SpriteEntries[i], basePalette, zip, "Font/" + i); styleData.Sprites.Add(i, new SpriteItem(SpriteType.Font, basePalette)); } }
private static void SaveTiles(StyleData styleData, ZipStorer zip, CancellableContext context) { var tilesCount = styleData.TileData.Length / (64 * 64); for (var i = 0; i < tilesCount; i++) { if (context.IsCancelling) { return; } SaveTile(styleData, zip, ref i); } }
protected override void BuildTextureAtlas(CancellableContext context, out bool cancelled) { var entries = CreateImageEntries(context, out cancelled); if (cancelled) { return; } var outputWidth = GuessOutputWidth(entries); var outputHeight = GuessOutputHeight(entries, outputWidth); var root = new Node(0, 0, outputWidth, outputHeight); if (context.IsCancelling) { cancelled = true; return; } CreateOutputBitmap(outputWidth, outputHeight); TileDictionary = new SerializableDictionary <int, CompactRectangle>(); foreach (var entry in entries) { if (context.IsCancelling) { cancelled = true; return; } CompactRectangle rect; if (entry.SameImageIndex == 0) { var node = root.Insert(entry.Width, entry.Height); if (node == null) { continue; //no space to put the image, increase the output image? } entry.X = node.Rectangle.X; entry.Y = node.Rectangle.Y; rect = Place(entry); } else { rect = TileDictionary[entry.SameImageIndex]; } var index = int.Parse(entry.FileName); TileDictionary.Add(index, rect); } Image.Save(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + ImagePath, ImageFormat.Png); Serialize(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(ImagePath) + Globals.XmlFormat); }
protected virtual List <ImageEntry> CreateImageEntries(CancellableContext context, out bool cancelled) { cancelled = false; var entries = new List <ImageEntry>(); CrcDictionary.Clear(); ZipEntries = ZipStore.ReadCentralDir(); for (var i = 0; i < ZipEntries.Count; i++) { if (context.IsCancelling) { cancelled = true; return(null); } var entry = new ImageEntry(); if (!CrcDictionary.ContainsKey(ZipEntries[i].Crc32)) { CrcDictionary.Add(ZipEntries[i].Crc32, entry); var source = GetBitmapFromZip(ZipStore, i); if (source != null) { entry.Width = source.Width + 2 * Padding; // Include a single pixel padding around each sprite, to avoid filtering problems if the sprite is scaled or rotated. entry.Height = source.Height + 2 * Padding; source.Dispose(); } else { entry.Width = 0; // + 2*Padding; entry.Height = 0; // +2 * Padding; } } else { var sameEntry = CrcDictionary[ZipEntries[i].Crc32]; entry.SameImageIndex = sameEntry.Index; entry.Width = sameEntry.Width; entry.Height = sameEntry.Height; } entry.Index = i; entry.FileName = ParsePath(ZipEntries[i].FilenameInZip); entry.ZipEntryIndex = i; entries.Add(entry); } return(entries); }
private static void SaveDeltas(StyleData styleData, ZipStorer zip, CancellableContext context) { for (var i = 0; i < styleData.DeltaIndexes.Length; i++) { var basePalette = styleData.PaletteIndexes[styleData.PaletteBase.Tile + styleData.DeltaIndexes[i].Sprite]; var deltaItem = new DeltaItem(); styleData.Deltas.Add(styleData.DeltaIndexes[i].Sprite, deltaItem); for (uint j = 0; j < styleData.DeltaIndexes[i].DeltaSize.Count; j++) { if (context.IsCancelling) { return; } SaveDelta(styleData, styleData.DeltaIndexes[i].Sprite, basePalette, j, zip, styleData.DeltaIndexes[i].Sprite + "_" + j); var spriteEntry = styleData.SpriteEntries[i]; deltaItem.SubItems.Add(new DeltaSubItem((DeltaType)j, spriteEntry.Width, spriteEntry.Height)); } } }
private void BuildTextureAtlasCompleteCallback(IAsyncResult ar) { var worker = (BuildTextureAtlasDelegate)((AsyncResult)ar).AsyncDelegate; var async = (AsyncOperation)ar.AsyncState; bool cancelled; // finish the asynchronous operation worker.EndInvoke(out cancelled, ar); // clear the running task flag lock (_sync) { IsBusy = false; _buildTextureAtlasContext = null; } // raise the completed event var completedArgs = new AsyncCompletedEventArgs(null, cancelled, null); async.PostOperationCompleted(e => OnBuildTextureAtlasCompleted((AsyncCompletedEventArgs)e), completedArgs); }
private void ConversionCompletedCallback(IAsyncResult ar) { // get the original worker delegate and the AsyncOperation instance var worker = (ConvertFilesDelegate)((AsyncResult)ar).AsyncDelegate; var async = (AsyncOperation)ar.AsyncState; bool cancelled; // finish the asynchronous operation worker.EndInvoke(out cancelled, ar); // clear the running task flag lock (_syncCancel) { _isBusy = false; _convertFilesContext = null; } // raise the completed event var completedArgs = new AsyncCompletedEventArgs(null, cancelled, null); async.PostOperationCompleted(e => OnConversionCompleted((AsyncCompletedEventArgs)e), completedArgs); }
public virtual void BuildTextureAtlasAsync() { var worker = new BuildTextureAtlasDelegate(BuildTextureAtlas); var completedCallback = new AsyncCallback(BuildTextureAtlasCompleteCallback); lock (_sync) { if (IsBusy) { throw new InvalidOperationException("The control is currently busy."); } var async = AsyncOperationManager.CreateOperation(null); var context = new CancellableContext(async); bool cancelled; worker.BeginInvoke(context, out cancelled, completedCallback, async); IsBusy = true; _buildTextureAtlasContext = context; } }
public IAsyncResult ReadFromFileAsync(string stylePath, bool saveSprites) { var worker = new ConvertStyleFileDelegate(ReadFromFile); var completedCallback = new AsyncCallback(BuildTextureAtlasCompletedCallback); lock (_sync) { if (IsBusy) { throw new InvalidOperationException("The control is currently busy."); } var async = AsyncOperationManager.CreateOperation(null); var context = new CancellableContext(async); bool cancelled; var result = worker.BeginInvoke(stylePath, saveSprites, context, out cancelled, completedCallback, async); IsBusy = true; _convertStyleFileContext = context; return(result); } }
public void ConvertFilesAsync(string sourcePath, string destinationPath) { sourcePath = Extensions.CheckDirectorySeparator(sourcePath); destinationPath = Extensions.CheckDirectorySeparator(destinationPath); var worker = new ConvertFilesDelegate(ConvertFiles); var completedCallback = new AsyncCallback(ConversionCompletedCallback); lock (_syncCancel) { if (_isBusy) { throw new InvalidOperationException("The control is currently busy."); } var async = AsyncOperationManager.CreateOperation(null); var context = new CancellableContext(async); bool cancelled; worker.BeginInvoke(sourcePath, destinationPath, context, out cancelled, completedCallback, async); _isBusy = true; _convertFilesContext = context; } }
private void SaveData(StyleData styleData, bool saveSprites, CancellableContext context, out bool cancelled) { var styleFile = Path.GetFileNameWithoutExtension(StylePath); if (saveSprites) { CarInfo.Serialize(styleData.CarInfo, Globals.MiscSubDir + Path.DirectorySeparatorChar + Globals.CarStyleSuffix + Globals.XmlFormat); Palette.SavePalettes(styleData.Palettes, Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Globals.PaletteSuffix + Globals.TextureImageFormat); } _threadCount = saveSprites ? 3 : 1; var memoryStreamTiles = new MemoryStream(); using (var zip = ZipStorer.Create(memoryStreamTiles, string.Empty)) { if (context.IsCancelling) { cancelled = true; return; } SaveTiles(styleData, zip, context); if (context.IsCancelling) { cancelled = true; return; } } memoryStreamTiles.Position = 0; if (Globals.SaveZipFiles) { using (var stream = new FileStream(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + styleFile + Globals.TilesSuffix + Globals.ZipFormat, FileMode.Create, FileAccess.Write)) { var bytes = new byte[memoryStreamTiles.Length]; memoryStreamTiles.Read(bytes, 0, (int)memoryStreamTiles.Length); stream.Write(bytes, 0, bytes.Length); } if (context.IsCancelling) { cancelled = true; return; } memoryStreamTiles.Position = 0; } TextureAtlas atlas = CreateTextureAtlas <TextureAtlasTiles>(ZipStorer.Open(memoryStreamTiles, FileAccess.Read), styleFile + Globals.TilesSuffix); _memoryStreams.Add(atlas, memoryStreamTiles); _runningAtlas.Add(atlas); if (context.IsCancelling) { cancelled = true; return; } if (saveSprites) { var memoryStreamSprites = new MemoryStream(); using (var zip = ZipStorer.Create(memoryStreamSprites, string.Empty)) { if (context.IsCancelling) { cancelled = true; return; } SaveSprites(styleData, zip, context); if (context.IsCancelling) { cancelled = true; return; } } memoryStreamSprites.Position = 0; if (Globals.SaveZipFiles) { using (var stream = new FileStream(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Globals.SpritesSuffix + Globals.ZipFormat, FileMode.Create, FileAccess.Write)) { var bytes = new byte[memoryStreamSprites.Length]; memoryStreamSprites.Read(bytes, 0, (int)memoryStreamSprites.Length); stream.Write(bytes, 0, bytes.Length); } if (context.IsCancelling) { cancelled = true; return; } memoryStreamSprites.Position = 0; } atlas = CreateTextureAtlas <TextureAtlasSprites>(ZipStorer.Open(memoryStreamSprites, FileAccess.Read), Globals.SpritesSuffix, styleData.Sprites); _memoryStreams.Add(atlas, memoryStreamSprites); _runningAtlas.Add(atlas); if (context.IsCancelling) { cancelled = true; return; } var memoryStreamDeltas = new MemoryStream(); using (var zip = ZipStorer.Create(memoryStreamDeltas, string.Empty)) { if (context.IsCancelling) { cancelled = true; return; } SaveDeltas(styleData, zip, context); if (context.IsCancelling) { cancelled = true; return; } } memoryStreamDeltas.Position = 0; if (Globals.SaveZipFiles) { using (var stream = new FileStream(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Globals.DeltasSuffix + Globals.ZipFormat, FileMode.Create, FileAccess.Write)) { var bytes = new byte[memoryStreamDeltas.Length]; memoryStreamDeltas.Read(bytes, 0, (int)memoryStreamDeltas.Length); stream.Write(bytes, 0, bytes.Length); } memoryStreamDeltas.Position = 0; } atlas = CreateTextureAtlas <TextureAtlasDeltas>(ZipStorer.Open(memoryStreamDeltas, FileAccess.Read), Globals.DeltasSuffix, styleData.Deltas); _memoryStreams.Add(atlas, memoryStreamDeltas); _runningAtlas.Add(atlas); } WaitHandle.WaitOne(); cancelled = WaitHandle.Value; GC.Collect(); }
private void ReadFromFile(string stylePath, bool saveSprites, CancellableContext context, out bool cancelled) { cancelled = false; var styleData = new StyleData { PaletteIndexes = new ushort[] {}, Palettes = new Palette[] {}, PaletteBase = new PaletteBase(), TileData = new byte[] {}, SpriteData = new byte[] {}, SpriteEntries = new SpriteEntry[] {}, SpriteBase = new SpriteBase(), FontBases = new int[] {}, DeltaData = new byte[] {}, DeltaIndexes = new DeltaIndex[] {}, Sprites = new SerializableDictionary <int, SpriteItem>(), Deltas = new SerializableDictionary <int, DeltaItem>(), CarInfo = new SerializableDictionary <int, CarInfo>(), CarSprites = new Dictionary <int, List <int> >() }; BinaryReader reader = null; try { if (!File.Exists(stylePath)) { throw new FileNotFoundException("Style File not found!", stylePath); } StylePath = stylePath; System.Diagnostics.Debug.WriteLine("Reading style file " + stylePath); var stream = new FileStream(stylePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); styleData.OriginalDateTime = File.GetLastWriteTime(stylePath); reader = new BinaryReader(stream); var encoder = System.Text.Encoding.ASCII; var magicNumber = encoder.GetString(reader.ReadBytes(4)); //GBMP if (magicNumber != "GBST") { throw new FormatException("Wrong style format!"); } int version = reader.ReadUInt16(); System.Diagnostics.Debug.WriteLine("Style version: " + version); while (stream.Position < stream.Length) { var chunkType = encoder.GetString(reader.ReadBytes(4)); var chunkSize = (int)reader.ReadUInt32(); System.Diagnostics.Debug.WriteLine("Found chunk '" + chunkType + "' with size " + chunkSize.ToString(CultureInfo.InvariantCulture) + "."); if (context.IsCancelling) { cancelled = true; return; } switch (chunkType) { case "TILE": //Tiles styleData.TileData = ReadTiles(reader, chunkSize); break; case "PPAL": //Physical Palette styleData.Palettes = ReadPhysicalPalette(reader, chunkSize); break; case "SPRB": //Sprite Bases styleData.SpriteBase = ReadSpriteBases(reader); break; case "PALX": //Palette Index styleData.PaletteIndexes = ReadPaletteIndexes(reader, chunkSize); break; case "OBJI": //Map Objects ReadMapObjects(reader, chunkSize); break; case "FONB": //Font Base styleData.FontBases = ReadFonts(reader, styleData.SpriteBase.Font); break; case "DELX": //Delta Index styleData.DeltaIndexes = ReadDeltaIndex(reader, chunkSize); break; case "DELS": //Delta Store styleData.DeltaData = ReadDeltaStore(reader, chunkSize); break; case "CARI": //Car Info styleData.CarInfo = ReadCars(reader, chunkSize, styleData.CarSprites); break; case "SPRG": //Sprite Graphics styleData.SpriteData = ReadSpritesGraphics(reader, chunkSize); break; case "SPRX": //Sprite Index styleData.SpriteEntries = ReadSpriteIndex(reader, chunkSize); break; case "PALB": //Palette Base styleData.PaletteBase = ReadPaletteBase(reader); break; case "SPEC": //Undocumented //Shows how tiles behave, for example in a physical way or what kind of sounds they make when somone walks on them ReadSurfaces(reader, chunkSize); break; case "RECY": ReadRecyclingInfo(reader, chunkSize); break; default: System.Diagnostics.Debug.WriteLine("Skipping chunk '" + chunkType + "'..."); reader.ReadBytes(chunkSize); break; } } } catch (Exception e) { throw; } finally { if (reader != null) { reader.Close(); } } SaveData(styleData, saveSprites, context, out cancelled); }
protected override void BuildTextureAtlas(CancellableContext context, out bool cancelled) { var entries = CreateImageEntries(context, out cancelled); if (cancelled) { return; } // Sort so the largest sprites get arranged first. var comparer = new ImageEntryComparer { CompareSize = true }; entries.Sort(comparer); var outputWidth = GuessOutputWidth(entries); var outputHeight = GuessOutputHeight(entries, outputWidth); if (context.IsCancelling) { cancelled = true; return; } // Sort the sprites back into index order. comparer.CompareSize = false; entries.Sort(comparer); var root = new Node(0, 0, outputWidth, outputHeight); CreateOutputBitmap(outputWidth, outputHeight); var itemsToRemove = new List <ItemToRemove>(); foreach (var entry in entries) { if (context.IsCancelling) { cancelled = true; return; } CompactRectangle rect; if (entry.SameImageIndex == 0) { if (entry.Width * entry.Height > 0) { var node = root.Insert(entry.Width, entry.Height); if (node == null) { continue; //ToDo: the picture could not be inserted because there were not enough space. Increase the output image? } entry.X = node.Rectangle.X; entry.Y = node.Rectangle.Y; rect = Place(entry); } else { rect = new CompactRectangle(); } } else { var sameEntry = entries[entry.SameImageIndex]; var sameSpriteDeltaId = _deltaIndexDictionary[sameEntry.FileName]; var sameSpriteId = sameSpriteDeltaId[0]; var sameDeltaIndex = sameSpriteDeltaId[1]; rect = DeltaDictionary[sameSpriteId].SubItems[sameDeltaIndex].Rectangle; } var spriteDeltaId = _deltaIndexDictionary[entry.FileName]; var spriteId = spriteDeltaId[0]; var deltaIndex = spriteDeltaId[1]; var subDeltaItem = DeltaDictionary[spriteId].SubItems[deltaIndex]; if (entry.Width * entry.Height > 0) { var cachedRect = _cachedRectDictionary[entry.SameImageIndex == 0 ? entry.ZipEntryIndex : entry.SameImageIndex]; subDeltaItem.RelativePosition = new Point(cachedRect.X, cachedRect.Y); subDeltaItem.Rectangle = rect; } else { var itemToRemove = new ItemToRemove { SpriteId = spriteId, DeltaSubItem = subDeltaItem }; itemsToRemove.Add(itemToRemove); } } foreach (var itemToRemove in itemsToRemove) { var deltaIndexToRemove = -1; for (var i = 0; i < DeltaDictionary[itemToRemove.SpriteId].SubItems.Count; i++) { if (DeltaDictionary[itemToRemove.SpriteId].SubItems[i].Type != itemToRemove.DeltaSubItem.Type) { continue; } deltaIndexToRemove = i; break; } if (deltaIndexToRemove > -1) { DeltaDictionary[itemToRemove.SpriteId].SubItems.RemoveAt(deltaIndexToRemove); } } Image.Save(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + ImagePath, ImageFormat.Png); Serialize(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(ImagePath) + Globals.XmlFormat); }
protected override void BuildTextureAtlas(CancellableContext context, out bool cancelled) { var entries = CreateImageEntries(context, out cancelled); if (cancelled) { return; } // Sort so the largest sprites get arranged first. var comparer = new ImageEntryComparer { CompareSize = true }; entries.Sort(comparer); var outputWidth = GuessOutputWidth(entries); var outputHeight = GuessOutputHeight(entries, outputWidth); outputWidth = 2048; //ToDo if (context.IsCancelling) { cancelled = true; return; } // Sort the sprites back into index order. comparer.CompareSize = false; entries.Sort(comparer); var root = new Node(0, 0, outputWidth, outputHeight); CreateOutputBitmap(outputWidth, outputHeight); //SpriteDictionary = new SerializableDictionary<int, SpriteItem>(); foreach (var entry in entries) { if (context.IsCancelling) { cancelled = true; return; } CompactRectangle rect; if (entry.SameImageIndex == 0) { var node = root.Insert(entry.Width, entry.Height); if (node == null) { continue; //ToDo: the picture could not be inserted because there were not enough space. Increase the output image? } entry.X = node.Rectangle.X; entry.Y = node.Rectangle.Y; rect = Place(entry); } else { rect = SpriteDictionary[entry.SameImageIndex].Rectangle; } var item = SpriteDictionary[entry.Index]; item.Rectangle = rect; } Image.Save(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + ImagePath, ImageFormat.Png); Serialize(Globals.GraphicsSubDir + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(ImagePath) + Globals.XmlFormat); }
private void ConvertFiles(string sourcePath, string destinationPath, CancellableContext asyncContext, out bool cancelled) { cancelled = false; CreateSubDirectories(destinationPath); //convert style files for (int i = 0; i < Globals.StyleMapFiles.Length; i++) { var styleFile = Globals.StyleMapFiles[i]; if (asyncContext.IsCancelling) { cancelled = true; return; } //copy over style file (because some data in it are still needed) var style = new Style.Style(); var sourceFile = sourcePath + Globals.DataSubDir + Path.DirectorySeparatorChar + styleFile + Globals.StyleFileExtension; var targetFile = destinationPath + Globals.GraphicsSubDir + Path.DirectorySeparatorChar + styleFile + Globals.StyleFileExtension; if (!File.Exists(targetFile) || !Extensions.FilesAreEqual(sourceFile, targetFile)) { File.Copy(sourceFile, targetFile, true); } style.ConvertStyleFileCompleted += StyleOnConvertStyleFileCompleted; style.ReadFromFileAsync(targetFile, i == 0); _runningStyles.Add(style); } //copy over maps var mapFiles = Globals.StyleMapFiles.Select(mapFile => sourcePath + Globals.DataSubDir + Path.DirectorySeparatorChar + mapFile + Globals.MapFileExtension).ToList(); mapFiles.AddRange(Globals.MapFilesMultiplayer.Select(multiplayerMapFile => sourcePath + Globals.DataSubDir + Path.DirectorySeparatorChar + multiplayerMapFile + Globals.MapFileExtension)); for (var i = 0; i < mapFiles.Count; i++) { if (asyncContext.IsCancelling) { cancelled = true; return; } var targetFile = destinationPath + Globals.MapsSubDir + Path.DirectorySeparatorChar + Path.GetFileName(mapFiles[i]); if (File.Exists(targetFile)) { if (Extensions.FilesAreEqual(mapFiles[i], targetFile)) { continue; } } File.Copy(mapFiles[i], targetFile, true); } var miscFiles = Globals.MiscFiles.Select(miscFile => sourcePath + Globals.DataSubDir + Path.DirectorySeparatorChar + miscFile).ToList(); for (var i = 0; i < miscFiles.Count; i++) { if (asyncContext.IsCancelling) { cancelled = true; return; } var targetFile = destinationPath + Globals.MiscSubDir + Path.DirectorySeparatorChar + Path.GetFileName(miscFiles[i]); if (File.Exists(targetFile)) { if (Extensions.FilesAreEqual(miscFiles[i], targetFile)) { continue; } } File.Copy(miscFiles[i], targetFile, true); } WaitHandle.WaitOne(); IndexFile.Save(); cancelled = WaitHandle.Value; }
protected abstract void BuildTextureAtlas(CancellableContext context, out bool cancel);