/****************************************************************************** * Spine Runtimes License Agreement * Last updated January 1, 2020. Replaces all prior versions. * * Copyright (c) 2013-2020, Esoteric Software LLC * * Integration of the Spine Runtimes into software or otherwise creating * derivative works of the Spine Runtimes is permitted under the terms and * conditions of Section 2 of the Spine Editor License Agreement: * http://esotericsoftware.com/spine-editor-license * * Otherwise, it is permitted to integrate the Spine Runtimes into software * or otherwise create derivative works of the Spine Runtimes (collectively, * "Products"), provided that each user of the Products must obtain their own * Spine Editor license and redistribution of the Products in any form must * include this license and copyright notice. * * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ using UnityEngine; using System.Collections.Generic; using System.Collections; namespace Spine.Unity.AttachmentTools { public static class AttachmentCloneExtensions { /// /// Clones the attachment. public static Attachment GetCopy (this Attachment o, bool cloneMeshesAsLinked) { var meshAttachment = o as MeshAttachment; if (meshAttachment != null && cloneMeshesAsLinked) return meshAttachment.NewLinkedMesh(); return o.Copy(); } #region Runtime Linked MeshAttachments /// /// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to the AtlasRegion provided. public static MeshAttachment GetLinkedMesh (this MeshAttachment o, string newLinkedMeshName, AtlasRegion region) { if (region == null) throw new System.ArgumentNullException("region"); MeshAttachment mesh = o.NewLinkedMesh(); mesh.SetRegion(region, false); return mesh; } /// /// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to an AtlasRegion generated from a Sprite. The AtlasRegion will be mapped to a new Material based on the shader. /// For better caching and batching, use GetLinkedMesh(string, AtlasRegion, bool) public static MeshAttachment GetLinkedMesh (this MeshAttachment o, Sprite sprite, Shader shader, Material materialPropertySource = null) { var m = new Material(shader); if (materialPropertySource != null) { m.CopyPropertiesFromMaterial(materialPropertySource); m.shaderKeywords = materialPropertySource.shaderKeywords; } return o.GetLinkedMesh(sprite.name, sprite.ToAtlasRegion()); } /// /// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to an AtlasRegion generated from a Sprite. The AtlasRegion will be mapped to a new Material based on the shader. /// For better caching and batching, use GetLinkedMesh(string, AtlasRegion, bool) public static MeshAttachment GetLinkedMesh (this MeshAttachment o, Sprite sprite, Material materialPropertySource) { return o.GetLinkedMesh(sprite, materialPropertySource.shader, materialPropertySource); } #endregion #region RemappedClone Convenience Methods /// /// Gets a clone of the attachment remapped with a sprite image. /// The remapped clone. /// The original attachment. /// The sprite whose texture to use. /// The source material used to copy the shader and material properties from. /// If true, a premultiply alpha clone of the original texture will be created. /// See remarks below for additional info. /// If true MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment. /// If true the size of the original attachment will be followed, instead of using the Sprite size. /// If true and the original Attachment is a MeshAttachment, then /// a non-central sprite pivot will shift uv coords in the opposite direction. Vertices will not be offset in /// any case when the original Attachment is a MeshAttachment. /// If true and the original Attachment is a RegionAttachment, then /// the original region's scale value is used instead of the Sprite's pixels per unit property. Since uniform scale is used, /// x scale of the original attachment (width scale) is used, scale in y direction (height scale) is ignored. /// When parameter premultiplyAlpha is set to true, a premultiply alpha clone of the /// original texture will be created. Additionally, this PMA Texture clone is cached for later re-use, /// which might steadily increase the Texture memory footprint when used excessively. /// See on how to clear these cached textures. public static Attachment GetRemappedClone (this Attachment o, Sprite sprite, Material sourceMaterial, bool premultiplyAlpha = true, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false, bool pivotShiftsMeshUVCoords = true, bool useOriginalRegionScale = false) { var atlasRegion = premultiplyAlpha ? sprite.ToAtlasRegionPMAClone(sourceMaterial) : sprite.ToAtlasRegion(new Material(sourceMaterial) { mainTexture = sprite.texture } ); if (!pivotShiftsMeshUVCoords && o is MeshAttachment) { // prevent non-central sprite pivot setting offsetX/Y and shifting uv coords out of mesh bounds atlasRegion.offsetX = 0; atlasRegion.offsetY = 0; } float scale = 1f / sprite.pixelsPerUnit; if (useOriginalRegionScale) { var regionAttachment = o as RegionAttachment; if (regionAttachment != null) scale = regionAttachment.width / regionAttachment.regionOriginalWidth; } return o.GetRemappedClone(atlasRegion, cloneMeshAsLinked, useOriginalRegionSize, scale); } /// /// Gets a clone of the attachment remapped with an atlasRegion image. /// The remapped clone. /// The original attachment. /// Atlas region. /// If true MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment. /// If true the size of the original attachment will be followed, instead of using the Sprite size. /// Unity units per pixel scale used to scale the atlas region size when not using the original region size. public static Attachment GetRemappedClone (this Attachment o, AtlasRegion atlasRegion, bool cloneMeshAsLinked = true, bool useOriginalRegionSize = false, float scale = 0.01f) { var regionAttachment = o as RegionAttachment; if (regionAttachment != null) { RegionAttachment newAttachment = (RegionAttachment)regionAttachment.Copy(); newAttachment.SetRegion(atlasRegion, false); if (!useOriginalRegionSize) { newAttachment.width = atlasRegion.width * scale; newAttachment.height = atlasRegion.height * scale; } newAttachment.UpdateOffset(); return newAttachment; } else { var meshAttachment = o as MeshAttachment; if (meshAttachment != null) { MeshAttachment newAttachment = cloneMeshAsLinked ? meshAttachment.NewLinkedMesh() : (MeshAttachment)meshAttachment.Copy(); newAttachment.SetRegion(atlasRegion); return newAttachment; } } return o.GetCopy(true); // Non-renderable Attachments will return as normal cloned attachments. } #endregion } }