public void Lock() { if (m_locked) { throw new Exception("Bitmap already locked."); } // https://stackoverflow.com/questions/1563038/fast-work-with-bitmaps-in-c-sharp Rectangle rect = new Rectangle(0, 0, Width, Height); m_bitmapData = BitmapRef.LockBits(rect, ImageLockMode.ReadWrite, BitmapRef.PixelFormat); //int rgbValueLength = IsAlphaBitmap ? 4 : 3; int rgbValueLength = 4; // TODO fix this m_bitmapSizeBytes = (Width * Height) * rgbValueLength; #if !USE_UNSAFE_FUNCTIONS m_bitmapPtr = m_bitmapData.Scan0; if (m_bitmapDataCopy == null || m_bitmapDataCopy.Length != m_bitmapSizeBytes) { m_bitmapDataCopy = new byte [m_bitmapSizeBytes]; } Marshal.Copy(m_bitmapPtr, m_bitmapDataCopy, 0, m_bitmapDataCopy.Length); #endif m_locked = true; }
public void Lock() { if (m_locked) { throw new Exception("Bitmap already locked."); } // https://stackoverflow.com/questions/1563038/fast-work-with-bitmaps-in-c-sharp Rectangle rect = new Rectangle(0, 0, Width, Height); m_bitmapData = BitmapRef.LockBits(rect, ImageLockMode.ReadWrite, BitmapRef.PixelFormat); m_bitmapPtr = m_bitmapData.Scan0; int rgbValueLength = IsAlphaBitmap ? 4 : 3; int bytes = (Width * Height) * rgbValueLength; if (m_rgbValues == null || m_rgbValues.Length != (bytes - 1)) { m_rgbValues = new byte [bytes - 1]; } Marshal.Copy(m_bitmapPtr, m_rgbValues, 0, m_rgbValues.Length); m_locked = true; }
public void Unlock(bool writePixels = true) { if (!m_locked) { throw new Exception("Bitmap not locked."); } #if !USE_UNSAFE_FUNCTIONS // Write the color values back to the bitmap if (writePixels) { Marshal.Copy(m_bitmapDataCopy, 0, m_bitmapPtr, m_bitmapDataCopy.Length); } #endif // Unlock the bitmap BitmapRef.UnlockBits(m_bitmapData); m_bitmapData = null; m_bitmapSizeBytes = 0; #if !USE_UNSAFE_FUNCTIONS //m_rgbValues = null; // don't null this, keep this memory around for re-use m_bitmapPtr = (IntPtr)0; #endif m_locked = false; }
public TextureAtlasPosition this[string textureCode] { get { if (contentTextPos == null) { int textureSubId; textureSubId = ObjectCacheUtil.GetOrCreate <int>(capi, "contenttexture-" + contentTexture.ToString() + "-" + contentTexture.Alpha, () => { TextureAtlasPosition texPos; int id = 0; BitmapRef bmp = capi.Assets.TryGet(contentTexture.Base.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"))?.ToBitmap(capi); if (bmp != null) { if (contentTexture.Alpha != 255) { bmp.MulAlpha(contentTexture.Alpha); } capi.BlockTextureAtlas.InsertTexture(bmp, out id, out texPos); bmp.Dispose(); } return(id); }); contentTextPos = capi.BlockTextureAtlas.Positions[textureSubId]; } return(contentTextPos); } }
public static int LoadTextureArray(this ClientMain game, AssetLocation[] locations, int width, int height) { var Platform = game.GetField <ClientPlatformWindows>("Platform"); BitmapRef[] bmps = new BitmapRef[locations.Length]; for (int i = 0; i < locations.Length; i++) { var name = locations[i].WithPathPrefixOnce("textures/"); byte[] assetData = Platform.AssetManager.TryGet(name)?.Data; if (assetData == null) { return(0); } bmps[i] = Platform.BitmapCreateFromPng(assetData, assetData.Length); } int id = Platform.LoadTextureArray(bmps, width, height); for (int i = 0; i < bmps.Length; i++) { bmps[i].Dispose(); } return(id); }
public TextureAtlasPosition this[string textureCode] { get { AssetLocation texturePath = textureLocation; TextureAtlasPosition texpos; if (texturePath == null) { texpos = this.texPos; } else { texpos = api.BlockTextureAtlas[texturePath]; } if (texpos == null) { IAsset texAsset = api.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(api); api.BlockTextureAtlas.InsertTextureCached(texturePath, bmp, out _, out texpos); } else { texpos = api.BlockTextureAtlas.UnknownTexturePosition; } } return(texpos); } }
private void OnDraw(Context ctx, ImageSurface surface, ElementBounds currentBounds) { BitmapRef bmp = capi.Assets.Get("alchemy:textures/hud/alchemyhud.png").ToBitmap(capi); if (inactive) { bmp.MulAlpha(30); } Vintagestory.API.Common.SurfaceDrawImage.Image(surface, ((Vintagestory.API.Common.BitmapExternal)bmp), (int)currentBounds.drawX, (int)currentBounds.drawY, (int)currentBounds.InnerWidth, (int)currentBounds.InnerHeight); bmp.Dispose(); }
public TextureAtlasPosition this[string textureCode] { get { AssetLocation textureLoc = null; if (curContProps.Textures != null) { CompositeTexture compTex; if (curContProps.Textures.TryGetValue(textureCode, out compTex)) { textureLoc = compTex.Base; } } if (textureLoc == null && shapeTextures != null) { shapeTextures.TryGetValue(textureCode, out textureLoc); } if (textureLoc != null) { TextureAtlasPosition texPos = capi.BlockTextureAtlas[textureLoc]; if (texPos == null) { BitmapRef bmp = capi.Assets.TryGet(textureLoc.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"))?.ToBitmap(capi); if (bmp != null) { capi.BlockTextureAtlas.InsertTextureCached(textureLoc, bmp, out _, out texPos); bmp.Dispose(); } } return(texPos); } ItemStack content = GetContents(); if (content.Class == EnumItemClass.Item) { TextureAtlasPosition texPos; textureLoc = content.Item.Textures[textureCode].Base; BitmapRef bmp = capi.Assets.TryGet(textureLoc.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"))?.ToBitmap(capi); if (bmp != null) { capi.BlockTextureAtlas.InsertTextureCached(textureLoc, bmp, out _, out texPos); bmp.Dispose(); return(texPos); } } return(contentTexSource[textureCode]); } }
private void loadTexture(Shape entityShape, string code, AssetLocation location, int textureWidth, int textureHeight, string shapePathForLogging) { ICoreClientAPI api = entity.World.Api as ICoreClientAPI; CompositeTexture ctex = new CompositeTexture() { Base = location }; entityShape.TextureSizes[code] = new int[] { textureWidth, textureHeight }; AssetLocation shapeTexloc = location; // Weird backreference to the shaperenderer. Should be refactored. var texturesByLoc = (entity as EntityAgent).extraTextureByLocation; var texturesByName = (entity as EntityAgent).extraTexturesByTextureName; BakedCompositeTexture bakedCtex; if (!texturesByLoc.TryGetValue(shapeTexloc, out bakedCtex)) { int textureSubId = 0; TextureAtlasPosition texpos; IAsset texAsset = api.Assets.TryGet(location.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(api); api.EntityTextureAtlas.InsertTexture(bmp, out textureSubId, out texpos, -1); } else { api.World.Logger.Warning("Skin part shape {0} defined texture {1}, no such texture found.", shapePathForLogging, location); } ctex.Baked = new BakedCompositeTexture() { BakedName = location, TextureSubId = textureSubId }; texturesByName[code] = ctex; texturesByLoc[shapeTexloc] = ctex.Baked; } else { ctex.Baked = bakedCtex; texturesByName[code] = ctex; } }
public TextureAtlasPosition this[string textureCode] { get { AssetLocation texturePath = null; CompositeTexture tex; if (nowTesselatingItem.Textures.TryGetValue(textureCode, out tex)) { texturePath = tex.Baked.BakedName; } else { if (nowTesselatingItem.Textures.TryGetValue("all", out tex)) { texturePath = tex.Baked.BakedName; } else { nowTesselatingShape?.Textures.TryGetValue(textureCode, out texturePath); } } if (texturePath == null) { texturePath = new AssetLocation(textureCode); } TextureAtlasPosition texpos = capi.BlockTextureAtlas[texturePath]; if (texpos == null) { IAsset texAsset = capi.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); capi.BlockTextureAtlas.InsertTextureCached(texturePath, bmp, out _, out texpos); } else { capi.World.Logger.Warning("For render in block " + Block.Code + ", item {0} defined texture {1}, not no such texture found.", nowTesselatingItem.Code, texturePath); } } return(texpos); } }
bool RuntimeInsert(ICoreClientAPI capi, ITextureAtlasAPI intoAtlas, BakedCompositeTexture btex) { BitmapRef bmp = capi.Assets.Get(btex.BakedName).ToBitmap(capi); int textureSubId; TextureAtlasPosition texpos; if (intoAtlas.InsertTexture(bmp, out textureSubId, out texpos)) { btex.TextureSubId = textureSubId; capi.Render.RemoveTexture(btex.BakedName); return(true); } bmp.Dispose(); return(false); }
protected TextureAtlasPosition getOrCreateTexPos(AssetLocation texturePath) { TextureAtlasPosition texpos = capi.BlockTextureAtlas[texturePath]; if (texpos == null) { IAsset texAsset = capi.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); capi.BlockTextureAtlas.InsertTextureCached(texturePath, bmp, out _, out texpos); } else { capi.World.Logger.Warning("For render in block " + Block.Code + ", item {0} defined texture {1}, not no such texture found.", nowTesselatingObj.Code, texturePath); } } return(texpos); }
public TextureAtlasPosition this[string textureCode] { get { if (textureCode == "topper" && corkTextPos != null) { return(corkTextPos); } if (textureCode == "glass" && blockTextPos != null) { return(blockTextPos); } if (textureCode == "bracing" && bracingTextPos != null) { return(bracingTextPos); } if (contentTextPos == null) { int textureSubId; textureSubId = ObjectCacheUtil.GetOrCreate <int>(capi, "contenttexture-" + contentTexture.ToString(), () => { TextureAtlasPosition texPos; int id = 0; BitmapRef bmp = capi.Assets.TryGet(contentTexture.Base.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"))?.ToBitmap(capi); if (bmp != null) { capi.BlockTextureAtlas.InsertTexture(bmp, out id, out texPos); bmp.Dispose(); } return(id); }); contentTextPos = capi.BlockTextureAtlas.Positions[textureSubId]; } return(contentTextPos); } }
public TextureAtlasPosition this[string textureCode] { get { AssetLocation texturePath = crustTextureLoc; if (textureCode == "filling") { texturePath = fillingTextureLoc; } if (textureCode == "topcrust") { texturePath = topCrustTextureLoc; } if (texturePath == null) { capi.World.Logger.Warning("Missing texture path for pie mesh texture code {0}, seems like a missing texture definition or invalid pie block.", textureCode); return(capi.BlockTextureAtlas.UnknownTexturePosition); } TextureAtlasPosition texpos = capi.BlockTextureAtlas[texturePath]; if (texpos == null) { IAsset texAsset = capi.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); capi.BlockTextureAtlas.InsertTextureCached(texturePath, bmp, out _, out texpos); } else { capi.World.Logger.Warning("Pie mesh texture {1} not found.", nowTesselatingBlock.Code, texturePath); texpos = capi.BlockTextureAtlas.UnknownTexturePosition; } } return(texpos); } }
protected TextureAtlasPosition getOrCreateTexPos(AssetLocation texturePath) { var capi = api as ICoreClientAPI; TextureAtlasPosition texpos = curAtlas[texturePath]; if (texpos == null) { IAsset texAsset = capi.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); curAtlas.InsertTextureCached(texturePath, bmp, out _, out texpos, 0.1f); } else { capi.World.Logger.Warning("Item {0} defined texture {1}, not no such texture found.", Code, texturePath); } } return(texpos); }
public void Unlock(bool writePixels) { if (!m_locked) { throw new Exception("Bitmap not locked."); } // Write the color values back to the bitmap if (writePixels) { Marshal.Copy(m_rgbValues, 0, m_bitmapPtr, m_rgbValues.Length); } // Unlock the bitmap BitmapRef.UnlockBits(m_bitmapData); //m_rgbValues = null; // keep this memory around for re-use m_bitmapData = null; m_bitmapPtr = (IntPtr)0; m_locked = false; }
public override void reloadSkin() { if (skinTexPos == null) { GetTextureSource(); } TextureAtlasPosition origTexPos = capi.EntityTextureAtlas.Positions[entity.Properties.Client.FirstTexture.Baked.TextureSubId]; LoadedTexture entityAtlas = new LoadedTexture(null) { TextureId = origTexPos.atlasTextureId, Width = capi.EntityTextureAtlas.Size.Width, Height = capi.EntityTextureAtlas.Size.Height }; capi.Render.GlToggleBlend(true, EnumBlendMode.Overlay); string componentPath = "characters:textures/entity/skin/"; string[] skinParts = Enum.GetNames(typeof(EnumSkinPart)); for (int x = 0; x < skinParts.Length; x++) { AssetLocation componentLoc; string skinProperty = skinParts[x]; float alphaTest = 0.005f; if (skinProperty == "hairtype" || skinProperty == "facialhair") { if (entity.WatchedAttributes.GetString(skinProperty, "none") == "none") { continue; } } switch (skinProperty) { case "skincolor": componentLoc = new AssetLocation( componentPath + "skins/" + entity.WatchedAttributes.GetString("sex", "male") + "/" + entity.WatchedAttributes.GetString("skincolor", "tan") + ".png" ); alphaTest = -1f; break; case "eyecolor": componentLoc = new AssetLocation( componentPath + "eyes/" + entity.WatchedAttributes.GetString("eyecolor", "brown") + ".png" ); break; case "facialhair": componentLoc = new AssetLocation( componentPath + "facialhairs/" + entity.WatchedAttributes.GetString("facialhair", "full") + "-" + entity.WatchedAttributes.GetString("haircolor", "brown") + ".png" ); break; case "hairtype": componentLoc = new AssetLocation( componentPath + "hairs/" + entity.WatchedAttributes.GetString("hairtype", "m") + "-" + entity.WatchedAttributes.GetString("haircolor", "brown") + ".png" ); break; default: componentLoc = new AssetLocation( componentPath + "hairs/" + entity.WatchedAttributes.GetString("hairtype", "m") + "-" + entity.WatchedAttributes.GetString("haircolor", "brown") + ".png" ); break; } LoadedTexture componentTexture = new LoadedTexture(capi); BitmapRef bitMap = capi.Assets.Get(componentLoc).ToBitmap(capi); capi.Render.GetOrLoadTexture(componentLoc, bitMap, ref componentTexture); capi.Render.GlToggleBlend(false); capi.EntityTextureAtlas.RenderTextureIntoAtlas( componentTexture, 0, 0, 128, 128, skinTexPos.x1 * capi.EntityTextureAtlas.Size.Width, skinTexPos.y1 * capi.EntityTextureAtlas.Size.Height, alphaTest ); capi.Render.GlToggleBlend(true, EnumBlendMode.Overlay); } // Standard int[] renderOrder = new int[] { (int)EnumCharacterDressType.LowerBody, (int)EnumCharacterDressType.Foot, (int)EnumCharacterDressType.UpperBody, (int)EnumCharacterDressType.UpperBodyOver, (int)EnumCharacterDressType.Waist, (int)EnumCharacterDressType.Shoulder, (int)EnumCharacterDressType.Emblem, (int)EnumCharacterDressType.Neck, (int)EnumCharacterDressType.Head, (int)EnumCharacterDressType.Hand, (int)EnumCharacterDressType.Arm, (int)EnumCharacterDressType.Face }; if (gearInv == null && (eagent != null && eagent.GearInventory != null)) { eagent.GearInventory.SlotModified += gearSlotModified; gearInv = eagent.GearInventory; } if (gearInv == null) { return; } for (int i = 0; i < renderOrder.Length; i++) { int slotid = renderOrder[i]; if (gearInv[slotid] == null) { continue; } ItemStack stack = gearInv[slotid].Itemstack; if (stack == null) { continue; } int itemTextureSubId = stack.Item.FirstTexture.Baked.TextureSubId; TextureAtlasPosition itemTexPos = capi.ItemTextureAtlas.Positions[itemTextureSubId]; LoadedTexture itemAtlas = new LoadedTexture(null) { TextureId = itemTexPos.atlasTextureId, Width = capi.ItemTextureAtlas.Size.Width, Height = capi.ItemTextureAtlas.Size.Height }; capi.EntityTextureAtlas.RenderTextureIntoAtlas( itemAtlas, itemTexPos.x1 * capi.ItemTextureAtlas.Size.Width, itemTexPos.y1 * capi.ItemTextureAtlas.Size.Height, (itemTexPos.x2 - itemTexPos.x1) * capi.ItemTextureAtlas.Size.Width, (itemTexPos.y2 - itemTexPos.y1) * capi.ItemTextureAtlas.Size.Height, skinTexPos.x1 * capi.EntityTextureAtlas.Size.Width, skinTexPos.y1 * capi.EntityTextureAtlas.Size.Height ); } capi.Render.GlToggleBlend(true); capi.Render.BindTexture2d(skinTexPos.atlasTextureId); capi.Render.GlGenerateTex2DMipmaps(); }
private Shape addGearToShape(ItemSlot slot, Shape entityShape, string shapePathForLogging) { if (slot.Empty) { return(entityShape); } ItemStack stack = slot.Itemstack; JsonObject attrObj = stack.Collectible.Attributes; if (attrObj?["wearableAttachment"].Exists != true) { return(entityShape); } if (!hasArmorExtras) { // So we don't affect other players models Shape newShape = new Shape() { Elements = entityShape.CloneElements(), Animations = entityShape.Animations, AnimationsByCrc32 = entityShape.AnimationsByCrc32, AttachmentPointsByCode = entityShape.AttachmentPointsByCode, JointsById = entityShape.JointsById, TextureWidth = entityShape.TextureWidth, TextureHeight = entityShape.TextureHeight, TextureSizes = entityShape.TextureSizes, Textures = entityShape.Textures, }; newShape.ResolveAndLoadJoints("head"); entityShape = newShape; } hasArmorExtras = true; CompositeShape compArmorShape = !attrObj["attachShape"].Exists ? (stack.Class == EnumItemClass.Item ? stack.Item.Shape : stack.Block.Shape) : attrObj["attachShape"].AsObject <CompositeShape>(null, stack.Collectible.Code.Domain); AssetLocation shapePath = shapePath = compArmorShape.Base.CopyWithPath("shapes/" + compArmorShape.Base.Path + ".json"); string[] disableElements = attrObj["disableElements"].AsArray <string>(null); if (disableElements != null) { foreach (var val in disableElements) { entityShape.RemoveElementByName(val); } } IAsset asset = capi.Assets.TryGet(shapePath); if (asset == null) { capi.World.Logger.Warning("Entity armor shape {0} defined in {1} {2} not found, was supposed to be at {3}. Armor piece will be invisible.", compArmorShape.Base, stack.Class, stack.Collectible.Code, shapePath); return(null); } Shape armorShape; try { armorShape = asset.ToObject <Shape>(); } catch (Exception e) { capi.World.Logger.Warning("Exception thrown when trying to load entity armor shape {0} defined in {1} {2}. Armor piece will be invisible. Exception: {3}", compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code, e); return(null); } bool added = false; foreach (var val in armorShape.Elements) { ShapeElement elem; if (val.StepParentName != null) { elem = entityShape.GetElementByName(val.StepParentName, StringComparison.InvariantCultureIgnoreCase); if (elem == null) { capi.World.Logger.Warning("Entity armor shape {0} defined in {1} {2} requires step parent element with name {3}, but no such element was found in shape {3}. Will not be visible.", compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code, val.StepParentName, shapePathForLogging); continue; } } else { capi.World.Logger.Warning("Entity armor shape element {0} in shape {1} defined in {2} {3} did not define a step parent element. Will not be visible.", val.Name, compArmorShape.Base, slot.Itemstack.Class, slot.Itemstack.Collectible.Code); continue; } if (elem.Children == null) { elem.Children = new ShapeElement[] { val }; } else { elem.Children = elem.Children.Append(val); } val.SetJointIdRecursive(elem.JointId); val.WalkRecursive((el) => { foreach (var face in el.Faces) { face.Value.Texture = "#" + stack.Collectible.Code + "-" + face.Value.Texture.TrimStart('#'); } }); added = true; } if (added && armorShape.Textures != null) { Dictionary <string, AssetLocation> newdict = new Dictionary <string, AssetLocation>(); foreach (var val in armorShape.Textures) { newdict[stack.Collectible.Code + "-" + val.Key] = val.Value; } // Item overrides var collDict = stack.Class == EnumItemClass.Block ? stack.Block.Textures : stack.Item.Textures; foreach (var val in collDict) { newdict[stack.Collectible.Code + "-" + val.Key] = val.Value.Base; } armorShape.Textures = newdict; foreach (var val in armorShape.Textures) { CompositeTexture ctex = new CompositeTexture() { Base = val.Value }; //ctex.Bake(capi.Assets); /*if (ctex.Baked.BakedVariants != null) * { * for (int i = 0; i < ctex.Baked.BakedVariants.Length; i++) * { * AddTextureLocation(new AssetLocationAndSource(ctex.Baked.BakedVariants[i].BakedName, "Shape file " + clientConf.Shape.Base)); * } * continue; * }*/ entityShape.TextureSizes[val.Key] = new int[] { armorShape.TextureWidth, armorShape.TextureHeight }; AssetLocation armorTexLoc = val.Value; var texturesByLoc = extraTextureByLocation; var texturesByName = extraTexturesByTextureName; BakedCompositeTexture bakedCtex; if (!texturesByLoc.TryGetValue(armorTexLoc, out bakedCtex)) { int textureSubId = 0; TextureAtlasPosition texpos; IAsset texAsset = capi.Assets.TryGet(val.Value.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); capi.EntityTextureAtlas.InsertTexture(bmp, out textureSubId, out texpos); } else { capi.World.Logger.Warning("Entity armor shape {0} defined texture {1}, not no such texture found.", shapePath, val.Value); } ctex.Baked = new BakedCompositeTexture() { BakedName = val.Value, TextureSubId = textureSubId }; texturesByName[val.Key] = ctex; texturesByLoc[armorTexLoc] = ctex.Baked; } else { ctex.Baked = bakedCtex; texturesByName[val.Key] = ctex; } } foreach (var val in armorShape.TextureSizes) { entityShape.TextureSizes[val.Key] = val.Value; } } return(entityShape); }
public override void Initialize(EntityProperties properties, JsonObject attributes) { base.Initialize(properties, attributes); skintree = entity.WatchedAttributes.GetTreeAttribute("skinConfig"); if (skintree == null) { entity.WatchedAttributes["skinConfig"] = skintree = new TreeAttribute(); } entity.WatchedAttributes.RegisterModifiedListener("skinConfig", onSkinConfigChanged); AvailableSkinParts = properties.Attributes["skinnableParts"].AsObject <SkinnablePart[]>(); foreach (var val in AvailableSkinParts) { string partCode = val.Code; val.VariantsByCode = new Dictionary <string, SkinnablePartVariant>(); AvailableSkinPartsByCode[val.Code] = val; if (val.Type == EnumSkinnableType.Texture && entity.Api.Side == EnumAppSide.Client) { ICoreClientAPI capi = entity.Api as ICoreClientAPI; LoadedTexture texture = new LoadedTexture(capi); foreach (var variant in val.Variants) { AssetLocation textureLoc; if (val.TextureTemplate != null) { textureLoc = val.TextureTemplate.Clone(); textureLoc.Path = textureLoc.Path.Replace("{code}", variant.Code); } else { textureLoc = variant.Texture; } IAsset asset = capi.Assets.TryGet(textureLoc.Clone().WithPathAppendixOnce(".png").WithPathPrefixOnce("textures/"), true); int r = 0, g = 0, b = 0; float c = 0; BitmapRef bmp = asset.ToBitmap(capi); for (int i = 0; i < 8; i++) { Vec2d vec = GameMath.R2Sequence2D(i); Color col2 = bmp.GetPixelRel((float)vec.X, (float)vec.Y); if (col2.A > 0.5) { r += col2.R; g += col2.G; b += col2.B; c++; } } bmp.Dispose(); c = Math.Max(1, c); variant.Color = ColorUtil.ColorFromRgba((int)(r / c), (int)(g / c), (int)(b / c), 255); val.VariantsByCode[variant.Code] = variant; } } else { foreach (var variant in val.Variants) { val.VariantsByCode[variant.Code] = variant; } } } if (entity.Api.Side == EnumAppSide.Server && AppliedSkinParts.Count == 0) { foreach (var val in AvailableSkinParts) { string partCode = val.Code; string variantCode = val.Variants[entity.World.Rand.Next(val.Variants.Length)].Code; selectSkinPart(partCode, variantCode, false); } } }
public TextureAtlasPosition this[string textureCode] { get { AssetLocation texturePath; if (textureCode == "ropedcloth" || type == null || type == "") { texturePath = new AssetLocation("block/cloth/ropedcloth"); } else { texturePath = new AssetLocation("block/cloth/tapestry/" + type); } AssetLocation cachedPath = texturePath.Clone(); AssetLocation rotLoc = null; if (rotten) { rotLoc = new AssetLocation("block/cloth/tapestryoverlay/rotten" + rotVariant); cachedPath.Path += "++" + rotLoc.Path; } TextureAtlasPosition texpos = capi.BlockTextureAtlas[cachedPath]; if (texpos == null) { IAsset texAsset = capi.Assets.TryGet(texturePath.Clone().WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png")); if (texAsset != null) { BitmapRef bmp = texAsset.ToBitmap(capi); if (rotten) { BakedBitmap bakedBmp = new BakedBitmap() { Width = bmp.Width, Height = bmp.Height }; bakedBmp.TexturePixels = bmp.Pixels; int[] texturePixelsOverlay = capi.Assets.TryGet(rotLoc.WithPathPrefixOnce("textures/").WithPathAppendixOnce(".png"))?.ToBitmap(capi)?.Pixels; if (texturePixelsOverlay == null) { throw new Exception("Texture file " + rotLoc + " is missing"); } for (int p = 0; p < bakedBmp.TexturePixels.Length; p++) { bakedBmp.TexturePixels[p] = ColorUtil.ColorOver(texturePixelsOverlay[p], bakedBmp.TexturePixels[p]); } capi.BlockTextureAtlas.InsertTextureCached(cachedPath, bakedBmp, out _, out texpos); } else { capi.BlockTextureAtlas.InsertTextureCached(cachedPath, bmp, out _, out texpos); } } else { capi.World.Logger.Warning("Tapestry type '{0}' defined texture '{1}', but no such texture found.", type, texturePath); } } if (texpos == null) { return(capi.BlockTextureAtlas.UnknownTexturePosition); } return(texpos); } }