private void framesList_SelectedIndexChanged(object sender, EventArgs e) { object item = framesList.SelectedItem; if (item is TkSpriteDefinition def) { int materialId = def.materialId; TkSpriteCollection col = def.parent; if (!col.textures.ContainsKey(materialId) || col.textures[materialId] == null) { col.textures[def.materialId] = GetTexture(col.textureExts[materialId]); } Bitmap pictureBoxBitmap; if (def.cropCache != null) { pictureBoxBitmap = def.cropCache; } else { pictureBoxBitmap = GetBitmap(def, true, false, false); } pictureBox.Image = pictureBoxBitmap; } }
private void spriteCollectionsList_SelectedIndexChanged(object sender, EventArgs e) { if (animationTimer != null) { StopAnimation(); } frameSlider.Value = 0; frameSlider.Enabled = false; object item = spriteCollectionsList.SelectedItem; if (item is TkSpriteCollection col) { if (col.baseTexture == null) { Text = TITLE_DEF + " [loading texture...]"; if (col.textureExts.Count > 0) { col.baseTexture = GetTexture(col.textureExts[0]); } else { col.baseTexture = null; } Text = TITLE_DEF; } activeCollection = col; List <TkSpriteAnimationClip> colAnis = animationClips.Where(a => a.parent.parents.Contains(col)).ToList(); framesList.Items.Clear(); framesList.Items.AddRange(col.sprites.OrderBy(s => s.name).ToArray()); animationsList.Items.Clear(); animationsList.Items.Add("[None]"); animationsList.Items.AddRange(colAnis.OrderBy(a => a.name).ToArray()); pictureBox.Image = col.baseTexture; } }
private Bitmap GetBitmap(TkSpriteDefinition def, bool bg, bool round, bool border) { TkSpriteCollection col = def.parent; Bitmap croppedBitmap = new Bitmap(def.width, def.height); using (Graphics graphics = Graphics.FromImage(croppedBitmap)) { graphics.DrawImage(GetTexture(col.textureExts[def.materialId]), new Rectangle(0, 0, def.width, def.height), new Rectangle(def.x, def.y, def.width, def.height), GraphicsUnit.Pixel); } Bitmap croppedBitmapGdiSafe; if (onMono) { //pretty crappy, but there's a bug with mono's internal //image format that won't let us rotate it after we drawimage it using (MemoryStream ms = new MemoryStream()) { croppedBitmap.Save(ms, ImageFormat.Png); croppedBitmapGdiSafe = new Bitmap(ms); } } else { croppedBitmapGdiSafe = croppedBitmap; } if (def.flipped) { croppedBitmapGdiSafe.RotateFlip(RotateFlipType.Rotate270FlipX); } Bitmap resizedBitmap = new Bitmap((int)def.fullWidth, (int)def.fullHeight); using (Graphics graphics = Graphics.FromImage(resizedBitmap)) { float drawX = def.xOff + def.fullWidth / 2; float drawY = def.yOff + def.fullHeight / 2; float drawXRound = (float)Math.Round(drawX, MidpointRounding.AwayFromZero); float drawYRound = (float)Math.Round(drawY, MidpointRounding.AwayFromZero); if (round) { drawX = drawXRound; drawY = drawYRound; } if (bg) { graphics.FillRectangle(Brushes.Gray, new Rectangle(0, 0, (int)def.fullWidth, (int)def.fullHeight)); } if (border) { graphics.DrawRectangle(Pens.Red, drawXRound - 1, drawYRound - 1, croppedBitmapGdiSafe.Width + 1, croppedBitmapGdiSafe.Height + 1); } graphics.DrawImage(croppedBitmapGdiSafe, drawX, drawY); croppedBitmapGdiSafe.Dispose(); } def.cropCache = resizedBitmap; return(resizedBitmap); }
private void GetTk2dSprites(AssetsFileInstance inst) { collections = new List <TkSpriteCollection>(); animations = new List <TkSpriteAnimation>(); animationClips = new List <TkSpriteAnimationClip>(); List <TkSpriteFrame> sprFrames = new List <TkSpriteFrame>(); string managedPath = Path.Combine(Path.GetDirectoryName(inst.path), "Managed"); Dictionary <AssetID, TkSpriteCollection> collectionLookup = new Dictionary <AssetID, TkSpriteCollection>(); int tk2dSCid = -1; int tk2dSAid = -1; foreach (AssetFileInfoEx mbInf in inst.table.GetAssetsOfType(0x72)) { string scriptName = null; ushort scriptIndex = AssetHelper.GetScriptIndex(inst.file, mbInf); if (tk2dSCid != -1 && scriptIndex == tk2dSCid) { scriptName = "tk2dSpriteCollectionData"; } else if (tk2dSAid != -1 && scriptIndex == tk2dSAid) { scriptName = "tk2dSpriteAnimation"; } if (tk2dSCid == -1 || tk2dSAid == -1) //still looking for script ids { AssetTypeValueField mbBase = am.GetATI(inst.file, mbInf).GetBaseField(); AssetTypeValueField scBase = am.GetExtAsset(inst, mbBase.Get("m_Script")).instance.GetBaseField(); scriptName = scBase.Get("m_Name").GetValue().AsString(); if (scriptName == "tk2dSpriteCollectionData") { tk2dSCid = scriptIndex; } else if (scriptName == "tk2dSpriteAnimation") { tk2dSAid = scriptIndex; } else { continue; //nope, nobody cares } } if (scriptName == null) { continue; } AssetTypeValueField mbSerialBase = am.GetMonoBaseFieldCached(inst, mbInf, managedPath); if (scriptName == "tk2dSpriteCollectionData") { AssetTypeValueField textures = mbSerialBase.Get("textures"); List <AssetExternal> textureExts = new List <AssetExternal>(); List <int> textureWidths = new List <int>(); List <int> textureHeights = new List <int>(); for (int i = 0; i < textures.childrenCount; i++) { AssetExternal textureExt = am.GetExtAsset(inst, mbSerialBase.Get("textures")[i], true); if (textureExt.info.curFileSize > 100000) { //bad news, unity probably stored the entire image into an array which is gonna //take up too much memory when we decode it, so we'll change the data to a byte array ClassDatabaseType textureType = AssetHelper.FindAssetClassByID(am.classFile, textureExt.info.curFileType); AssetTypeTemplateField textureTemp = new AssetTypeTemplateField(); textureTemp.FromClassDatabase(am.classFile, textureType, 0); AssetTypeTemplateField image_data = textureTemp.children[textureTemp.childrenCount - 1]; image_data.valueType = EnumValueTypes.ByteArray; //convert array to bytearray, much better AssetTypeInstance textureTypeInstance = new AssetTypeInstance(new[] { textureTemp }, inst.file.reader, textureExt.info.absoluteFilePos); AssetTypeValueField textureBase = textureTypeInstance.GetBaseField(); textureExt.instance = textureTypeInstance; textureExts.Add(textureExt); textureWidths.Add(textureBase.Get("m_Width").GetValue().AsInt()); textureHeights.Add(textureBase.Get("m_Height").GetValue().AsInt()); } else { textureExt = am.GetExtAsset(inst, mbSerialBase.Get("textures")[i]); AssetTypeValueField textureBase = textureExt.instance.GetBaseField(); textureExts.Add(textureExt); textureWidths.Add(textureBase.Get("m_Width").GetValue().AsInt()); textureHeights.Add(textureBase.Get("m_Height").GetValue().AsInt()); } } TkSpriteCollection collection = new TkSpriteCollection() { name = mbSerialBase.Get("spriteCollectionName").GetValue().AsString(), version = mbSerialBase.Get("version").GetValue().AsInt(), baseTexture = null, //do later textures = new Dictionary <int, Bitmap>(), //same textureExts = textureExts, sprites = new List <TkSpriteDefinition>() }; collectionLookup[new AssetID(inst.name, mbInf.index)] = collection; AssetTypeValueField spriteDefinitions = mbSerialBase.Get("spriteDefinitions"); foreach (AssetTypeValueField def in spriteDefinitions.children) { bool flipped = def.Get("flipped").GetValue().AsInt() == 1; int materialId = def.Get("materialId").GetValue().AsInt(); int textureWidth = textureWidths[materialId]; int textureHeight = textureHeights[materialId]; double uxn = double.MaxValue; double uxp = 0; double uyn = double.MaxValue; double uyp = 0; double pxn = double.MaxValue; double pyn = double.MaxValue; AssetTypeValueField positions = def.Get("positions"); AssetTypeValueField uvs = def.Get("uvs"); for (int i = 0; i < 4; i++) { AssetTypeValueField pos = positions[i]; AssetTypeValueField uv = uvs[i]; double posX = pos.Get("x").GetValue().AsFloat(); double posY = pos.Get("y").GetValue().AsFloat(); double uvX = Math.Round(uv.Get("x").GetValue().AsFloat() * textureWidth); double uvY = textureHeight - Math.Round(uv.Get("y").GetValue().AsFloat() * textureHeight); if (posX < pxn) { pxn = posX; } if (posY < pyn) { pyn = posY; } if (uvX < uxn) { uxn = uvX; } if (uvX > uxp) { uxp = uvX; } if (uvY < uyn) { uyn = uvY; } if (uvY > uyp) { uyp = uvY; } } int spriteX = (int)uxn; int spriteY = (int)uyn; int spriteWidth = (int)(uxp - uxn); int spriteHeight = (int)(uyp - uyn); AssetTypeValueField boundsData = def.Get("boundsData"); AssetTypeValueField untrimmedBoundsData = def.Get("untrimmedBoundsData"); AssetTypeValueField texelSize = def.Get("texelSize"); float texelX = texelSize.Get("x").GetValue().AsFloat(); float texelY = texelSize.Get("y").GetValue().AsFloat(); float realX = ((float)pxn) / texelX; float realY = -((flipped ? spriteWidth : spriteHeight) + ((float)pyn) / texelY); TkSpriteDefinition sprite = new TkSpriteDefinition() { parent = collection, name = def.Get("name").GetValue().AsString(), x = spriteX, y = spriteY, width = spriteWidth, height = spriteHeight, xOff = realX, yOff = realY, materialId = materialId, fullWidth = untrimmedBoundsData[1].Get("x").GetValue().AsFloat() / texelX, fullHeight = untrimmedBoundsData[1].Get("y").GetValue().AsFloat() / texelY, flipped = flipped }; collection.sprites.Add(sprite); } collections.Add(collection); } else if (scriptName == "tk2dSpriteAnimation") { AssetFileInfoEx gameObjectInfo = inst.table.GetAssetInfo(mbSerialBase.Get("m_GameObject").Get("m_PathID").GetValue().AsInt64()); TkSpriteAnimation animation = new TkSpriteAnimation() { parents = new List <TkSpriteCollection>(), //do later parentIds = new List <AssetID>(), gameObjectName = AssetHelper.GetAssetNameFast(inst.file, am.classFile, gameObjectInfo), clips = new List <TkSpriteAnimationClip>() }; AssetTypeValueField clips = mbSerialBase.Get("clips"); foreach (AssetTypeValueField clip in clips.children) { TkSpriteAnimationClip aniClip = new TkSpriteAnimationClip() { parent = animation, name = clip.Get("name").GetValue().AsString(), fps = clip.Get("fps").GetValue().AsFloat(), loopStart = clip.Get("loopStart").GetValue().AsInt(), wrapMode = (WrapMode)clip.Get("wrapMode").GetValue().AsInt(), frames = new List <TkSpriteFrame>() }; animation.clips.Add(aniClip); animationClips.Add(aniClip); AssetTypeValueField frames = clip.Get("frames"); foreach (AssetTypeValueField frame in frames.children) { AssetExternal collectionExt = am.GetExtAsset(inst, frame.Get("spriteCollection")); AssetID collectionId = new AssetID(collectionExt.file.name, collectionExt.info.index); if (!animation.parentIds.Contains(collectionId)) { animation.parentIds.Add(collectionId); } TkSpriteFrame sprFrame = new TkSpriteFrame() { collection = null, //do later collectionId = collectionId, spriteId = frame.Get("spriteId").GetValue().AsInt() }; sprFrames.Add(sprFrame); aniClip.frames.Add(sprFrame); } } animations.Add(animation); } } foreach (TkSpriteAnimation animation in animations) { foreach (AssetID parentId in animation.parentIds) { if (collectionLookup.ContainsKey(parentId)) { animation.parents.Add(collectionLookup[parentId]); } } } foreach (TkSpriteFrame frame in sprFrames) { if (collectionLookup.ContainsKey(frame.collectionId)) { frame.collection = collectionLookup[frame.collectionId]; } } }