private void RecursiveAddChunkNode(TreeNodeCollection xiNodes, int xiIndex, Chunk xiChunk) { TreeNode lNode = xiNodes.Insert(xiIndex, xiChunk.Name); //record the mapping on the two objects, for easy reference later //no doubt, this will play merry hell with the GC if you load lots //of different levels... lNode.Tag = xiChunk; xiChunk.TreeNode = lNode; //recurse foreach (Chunk child in xiChunk.GetChildren()) { RecursiveAddChunkNode(lNode.Nodes, child); } }
///======================================================================== /// Method : GetDifferences /// /// <summary> /// Produce a list of differences between this chunk and another. /// /// Subclasses should override this method to produce a customised list /// of differences for themselves, but call the base implementation /// which will handle collecting data from their children. /// </summary> /// <param name="xiChunk"></param> /// <returns></returns> /// <remarks> /// This is a brute force method of comparing differences. An alternative /// would be to record the actual actions taken in the UI - this would /// produce cleaner results, although it would be more work to implement. /// </remarks> ///======================================================================== public virtual List<string> GetDifferences(Chunk xiChunk) { //======================================================================= // Get a list of all the children of this chunk, by type //======================================================================= Dictionary<Type, List<Chunk>> lMyChildren = new Dictionary<Type, List<Chunk>>(); foreach (Chunk lChunk in GetChildren()) { List<Chunk> lChunksOfType; if (!lMyChildren.TryGetValue(lChunk.GetType(), out lChunksOfType)) { lChunksOfType = new List<Chunk>(); lMyChildren[lChunk.GetType()] = lChunksOfType; } lChunksOfType.Add(lChunk); } //======================================================================= // Get a list of all the children of the old chunk, by type //======================================================================= Dictionary<Type, List<Chunk>> lOldChildren = new Dictionary<Type, List<Chunk>>(); foreach (Chunk lChunk in xiChunk.GetChildren()) { List<Chunk> lChunksOfType; if (!lOldChildren.TryGetValue(lChunk.GetType(), out lChunksOfType)) { lChunksOfType = new List<Chunk>(); lOldChildren[lChunk.GetType()] = lChunksOfType; } lChunksOfType.Add(lChunk); } //======================================================================= // Generate the list of differences //======================================================================= List<string> lDifferences = new List<string>(); foreach (Type lChunkType in lMyChildren.Keys) { List<Chunk> lMine = lMyChildren[lChunkType]; if (!lOldChildren.ContainsKey(lChunkType)) { lDifferences.Add(string.Format(" Added {0} {1}(s)", lMine.Count, lChunkType)); continue; } List<Chunk> lOld = lOldChildren[lChunkType]; for (int ii = 0; ii < Math.Min(lMine.Count, lOld.Count); ii++) { List<string> lChildDifferences = lMine[ii].GetDifferences(lOld[ii]); if (lChildDifferences.Count > 0) { lDifferences.AddRange( lChildDifferences.ConvertAll<string>( new Converter<string, string>(delegate(string xiDifference) { return " " + xiDifference; }))); } } if (lMine.Count > lOld.Count) { lDifferences.Add(string.Format(" Added {0} {1}(s)", lMine.Count - lOld.Count, lChunkType)); } else if (lOld.Count > lMine.Count) { lDifferences.Add(string.Format(" Removed {0} {1}(s)", lOld.Count - lMine.Count, lChunkType)); } lOldChildren.Remove(lChunkType); } foreach (Type lChunkType in lOldChildren.Keys) { List<Chunk> lOld = lOldChildren[lChunkType]; lDifferences.Add(string.Format(" Removed {0} {1}(s)", lOld.Count, lChunkType)); } if (lDifferences.Count > 0) { lDifferences.Insert(0, string.Format("On {0}:", Name)); } return lDifferences; }
///======================================================================== /// Method : GetDifferences /// /// <summary> /// Produce a list of differences between this chunk and another. /// /// Subclasses should override this method to produce a customised list /// of differences for themselves, but call the base implementation /// which will handle collecting data from their children. /// </summary> /// <param name="xiChunk"></param> /// <returns></returns> /// <remarks> /// This is a brute force method of comparing differences. An alternative /// would be to record the actual actions taken in the UI - this would /// produce cleaner results, although it would be more work to implement. /// </remarks> ///======================================================================== public virtual List <string> GetDifferences(Chunk xiChunk) { //======================================================================= // Get a list of all the children of this chunk, by type //======================================================================= Dictionary <Type, List <Chunk> > lMyChildren = new Dictionary <Type, List <Chunk> >(); foreach (Chunk lChunk in GetChildren()) { List <Chunk> lChunksOfType; if (!lMyChildren.TryGetValue(lChunk.GetType(), out lChunksOfType)) { lChunksOfType = new List <Chunk>(); lMyChildren[lChunk.GetType()] = lChunksOfType; } lChunksOfType.Add(lChunk); } //======================================================================= // Get a list of all the children of the old chunk, by type //======================================================================= Dictionary <Type, List <Chunk> > lOldChildren = new Dictionary <Type, List <Chunk> >(); foreach (Chunk lChunk in xiChunk.GetChildren()) { List <Chunk> lChunksOfType; if (!lOldChildren.TryGetValue(lChunk.GetType(), out lChunksOfType)) { lChunksOfType = new List <Chunk>(); lOldChildren[lChunk.GetType()] = lChunksOfType; } lChunksOfType.Add(lChunk); } //======================================================================= // Generate the list of differences //======================================================================= List <string> lDifferences = new List <string>(); foreach (Type lChunkType in lMyChildren.Keys) { List <Chunk> lMine = lMyChildren[lChunkType]; if (!lOldChildren.ContainsKey(lChunkType)) { lDifferences.Add(string.Format(" Added {0} {1}(s)", lMine.Count, lChunkType)); continue; } List <Chunk> lOld = lOldChildren[lChunkType]; for (int ii = 0; ii < Math.Min(lMine.Count, lOld.Count); ii++) { List <string> lChildDifferences = lMine[ii].GetDifferences(lOld[ii]); if (lChildDifferences.Count > 0) { lDifferences.AddRange( lChildDifferences.ConvertAll <string>( new Converter <string, string>(delegate(string xiDifference) { return(" " + xiDifference); }))); } } if (lMine.Count > lOld.Count) { lDifferences.Add(string.Format(" Added {0} {1}(s)", lMine.Count - lOld.Count, lChunkType)); } else if (lOld.Count > lMine.Count) { lDifferences.Add(string.Format(" Removed {0} {1}(s)", lOld.Count - lMine.Count, lChunkType)); } lOldChildren.Remove(lChunkType); } foreach (Type lChunkType in lOldChildren.Keys) { List <Chunk> lOld = lOldChildren[lChunkType]; lDifferences.Add(string.Format(" Removed {0} {1}(s)", lOld.Count, lChunkType)); } if (lDifferences.Count > 0) { lDifferences.Insert(0, string.Format("On {0}:", Name)); } return(lDifferences); }
private static void AddChunkToImage(Chunk xiChunk, Bitmap xiBmp, int[,] xiPixelUsageMap) { if (xiChunk is TIMChunk) { try { TIMChunk c = (TIMChunk)xiChunk; Bitmap lTIMImage = c.ToBitmap(); int lPixelsPerTwoBytes; switch (c.BPP) { case TIMChunk.TimBPP._4BPP: lPixelsPerTwoBytes = 4; break; case TIMChunk.TimBPP._8BPP: lPixelsPerTwoBytes = 2; break; case TIMChunk.TimBPP._16BPP: lPixelsPerTwoBytes = 1; break; default: throw new Exception("Can't deal with this BPP"); } Rectangle lDestRect = new Rectangle( WIDTH_SCALE * c.ImageOrgX, c.ImageOrgY, c.ImageWidth * WIDTH_SCALE / lPixelsPerTwoBytes, c.ImageHeight); int lWidthScale = WIDTH_SCALE / lPixelsPerTwoBytes; for (int y = lDestRect.Top; y < lDestRect.Bottom; y++) { for (int x = lDestRect.Left; x < lDestRect.Right; x++) { Color lFromTIM = lTIMImage.GetPixel((x - lDestRect.Left) * lWidthScale, y - lDestRect.Top); SetPixel(xiBmp, x, y, lFromTIM, xiPixelUsageMap); } } if (c.Palette != null) { if (c.ClutCount != 1) throw new Exception("Don't know what to do with multi-CLUT TIMs"); for (int palIdx = 0; palIdx < c.Palette.Length; palIdx++) { Color col = Color.FromArgb(Utils.PS16bitColorToARGB(c.Palette[palIdx])); for (int x = 0; x < WIDTH_SCALE; x++) { SetPixel(xiBmp, WIDTH_SCALE * (c.PaletteOrgX + palIdx) + x, c.PaletteOrgY, col, xiPixelUsageMap); } } } } catch (Exception e) { Console.Error.WriteLine("Error: {0}\nSkipping this TIM", e); } } else { foreach (Chunk c in xiChunk.GetChildren()) { AddChunkToImage(c, xiBmp, xiPixelUsageMap); } } }
private void AddChunkToImage(Chunk c, Graphics g) { if (c is TIMChunk) AddChunkToImage((TIMChunk)c, g); foreach (Chunk child in c.GetChildren()) { if (child is TIMChunk) { AddChunkToImage((TIMChunk)child, g); } else { AddChunkToImage(child, g); } } }