1
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb7099b9c6ce91740b7041dabb0752c2
|
||||
timeCreated: 1456265156
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec2f0e7143c8a174994595883f4b1e33
|
||||
timeCreated: 1456265155
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,114 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine {
|
||||
|
||||
/// <summary>Stores mix (crossfade) durations to be applied when AnimationState animations are changed.</summary>
|
||||
public class AnimationStateData {
|
||||
internal SkeletonData skeletonData;
|
||||
readonly Dictionary<AnimationPair, float> animationToMixTime = new Dictionary<AnimationPair, float>(AnimationPairComparer.Instance);
|
||||
internal float defaultMix;
|
||||
|
||||
/// <summary>The SkeletonData to look up animations when they are specified by name.</summary>
|
||||
public SkeletonData SkeletonData { get { return skeletonData; } }
|
||||
|
||||
/// <summary>
|
||||
/// The mix duration to use when no mix duration has been specifically defined between two animations.</summary>
|
||||
public float DefaultMix { get { return defaultMix; } set { defaultMix = value; } }
|
||||
|
||||
public AnimationStateData (SkeletonData skeletonData) {
|
||||
if (skeletonData == null) throw new ArgumentException("skeletonData cannot be null.", "skeletonData");
|
||||
this.skeletonData = skeletonData;
|
||||
}
|
||||
|
||||
/// <summary>Sets a mix duration by animation names.</summary>
|
||||
public void SetMix (string fromName, string toName, float duration) {
|
||||
Animation from = skeletonData.FindAnimation(fromName);
|
||||
if (from == null) throw new ArgumentException("Animation not found: " + fromName, "fromName");
|
||||
Animation to = skeletonData.FindAnimation(toName);
|
||||
if (to == null) throw new ArgumentException("Animation not found: " + toName, "toName");
|
||||
SetMix(from, to, duration);
|
||||
}
|
||||
|
||||
/// <summary>Sets a mix duration when changing from the specified animation to the other.
|
||||
/// See TrackEntry.MixDuration.</summary>
|
||||
public void SetMix (Animation from, Animation to, float duration) {
|
||||
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
||||
if (to == null) throw new ArgumentNullException("to", "to cannot be null.");
|
||||
AnimationPair key = new AnimationPair(from, to);
|
||||
animationToMixTime.Remove(key);
|
||||
animationToMixTime.Add(key, duration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The mix duration to use when changing from the specified animation to the other,
|
||||
/// or the DefaultMix if no mix duration has been set.
|
||||
/// </summary>
|
||||
public float GetMix (Animation from, Animation to) {
|
||||
if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
|
||||
if (to == null) throw new ArgumentNullException("to", "to cannot be null.");
|
||||
AnimationPair key = new AnimationPair(from, to);
|
||||
float duration;
|
||||
if (animationToMixTime.TryGetValue(key, out duration)) return duration;
|
||||
return defaultMix;
|
||||
}
|
||||
|
||||
public struct AnimationPair {
|
||||
public readonly Animation a1;
|
||||
public readonly Animation a2;
|
||||
|
||||
public AnimationPair (Animation a1, Animation a2) {
|
||||
this.a1 = a1;
|
||||
this.a2 = a2;
|
||||
}
|
||||
|
||||
public override string ToString () {
|
||||
return a1.name + "->" + a2.name;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoids boxing in the dictionary.
|
||||
public class AnimationPairComparer : IEqualityComparer<AnimationPair> {
|
||||
public static readonly AnimationPairComparer Instance = new AnimationPairComparer();
|
||||
|
||||
bool IEqualityComparer<AnimationPair>.Equals (AnimationPair x, AnimationPair y) {
|
||||
return ReferenceEquals(x.a1, y.a1) && ReferenceEquals(x.a2, y.a2);
|
||||
}
|
||||
|
||||
int IEqualityComparer<AnimationPair>.GetHashCode (AnimationPair obj) {
|
||||
// from Tuple.CombineHashCodes // return (((h1 << 5) + h1) ^ h2);
|
||||
int h1 = obj.a1.GetHashCode();
|
||||
return (((h1 << 5) + h1) ^ obj.a2.GetHashCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e03d60c517d9b974db35b9fd144a1d09
|
||||
timeCreated: 1456265155
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,330 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
|
||||
#define IS_UNITY
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
#if WINDOWS_STOREAPP
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
#endif
|
||||
|
||||
namespace Spine {
|
||||
public class Atlas : IEnumerable<AtlasRegion> {
|
||||
readonly List<AtlasPage> pages = new List<AtlasPage>();
|
||||
List<AtlasRegion> regions = new List<AtlasRegion>();
|
||||
TextureLoader textureLoader;
|
||||
|
||||
#region IEnumerable implementation
|
||||
public IEnumerator<AtlasRegion> GetEnumerator () {
|
||||
return regions.GetEnumerator();
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () {
|
||||
return regions.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public List<AtlasRegion> Regions { get { return regions; } }
|
||||
public List<AtlasPage> Pages { get { return pages; } }
|
||||
|
||||
#if !(IS_UNITY)
|
||||
#if WINDOWS_STOREAPP
|
||||
private async Task ReadFile(string path, TextureLoader textureLoader) {
|
||||
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
|
||||
var file = await folder.GetFileAsync(path).AsTask().ConfigureAwait(false);
|
||||
using (var reader = new StreamReader(await file.OpenStreamForReadAsync().ConfigureAwait(false))) {
|
||||
try {
|
||||
Load(reader, Path.GetDirectoryName(path), textureLoader);
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Error reading atlas file: " + path, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Atlas(string path, TextureLoader textureLoader) {
|
||||
this.ReadFile(path, textureLoader).Wait();
|
||||
}
|
||||
#else
|
||||
|
||||
public Atlas (string path, TextureLoader textureLoader) {
|
||||
|
||||
#if WINDOWS_PHONE
|
||||
Stream stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(path);
|
||||
using (StreamReader reader = new StreamReader(stream)) {
|
||||
#else
|
||||
using (StreamReader reader = new StreamReader(path)) {
|
||||
#endif // WINDOWS_PHONE
|
||||
|
||||
try {
|
||||
Load(reader, Path.GetDirectoryName(path), textureLoader);
|
||||
} catch (Exception ex) {
|
||||
throw new Exception("Error reading atlas file: " + path, ex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // WINDOWS_STOREAPP
|
||||
|
||||
#endif
|
||||
|
||||
public Atlas (TextReader reader, string dir, TextureLoader textureLoader) {
|
||||
Load(reader, dir, textureLoader);
|
||||
}
|
||||
|
||||
public Atlas (List<AtlasPage> pages, List<AtlasRegion> regions) {
|
||||
this.pages = pages;
|
||||
this.regions = regions;
|
||||
this.textureLoader = null;
|
||||
}
|
||||
|
||||
private void Load (TextReader reader, string imagesDir, TextureLoader textureLoader) {
|
||||
if (textureLoader == null) throw new ArgumentNullException("textureLoader", "textureLoader cannot be null.");
|
||||
this.textureLoader = textureLoader;
|
||||
|
||||
string[] tuple = new string[4];
|
||||
AtlasPage page = null;
|
||||
while (true) {
|
||||
string line = reader.ReadLine();
|
||||
if (line == null) break;
|
||||
if (line.Trim().Length == 0)
|
||||
page = null;
|
||||
else if (page == null) {
|
||||
page = new AtlasPage();
|
||||
page.name = line;
|
||||
|
||||
if (ReadTuple(reader, tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker.
|
||||
page.width = int.Parse(tuple[0], CultureInfo.InvariantCulture);
|
||||
page.height = int.Parse(tuple[1], CultureInfo.InvariantCulture);
|
||||
ReadTuple(reader, tuple);
|
||||
}
|
||||
page.format = (Format)Enum.Parse(typeof(Format), tuple[0], false);
|
||||
|
||||
ReadTuple(reader, tuple);
|
||||
page.minFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0], false);
|
||||
page.magFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1], false);
|
||||
|
||||
string direction = ReadValue(reader);
|
||||
page.uWrap = TextureWrap.ClampToEdge;
|
||||
page.vWrap = TextureWrap.ClampToEdge;
|
||||
if (direction == "x")
|
||||
page.uWrap = TextureWrap.Repeat;
|
||||
else if (direction == "y")
|
||||
page.vWrap = TextureWrap.Repeat;
|
||||
else if (direction == "xy")
|
||||
page.uWrap = page.vWrap = TextureWrap.Repeat;
|
||||
|
||||
textureLoader.Load(page, Path.Combine(imagesDir, line));
|
||||
|
||||
pages.Add(page);
|
||||
|
||||
} else {
|
||||
AtlasRegion region = new AtlasRegion();
|
||||
region.name = line;
|
||||
region.page = page;
|
||||
|
||||
string rotateValue = ReadValue(reader);
|
||||
if (rotateValue == "true")
|
||||
region.degrees = 90;
|
||||
else if (rotateValue == "false")
|
||||
region.degrees = 0;
|
||||
else
|
||||
region.degrees = int.Parse(rotateValue);
|
||||
region.rotate = region.degrees == 90;
|
||||
|
||||
ReadTuple(reader, tuple);
|
||||
int x = int.Parse(tuple[0], CultureInfo.InvariantCulture);
|
||||
int y = int.Parse(tuple[1], CultureInfo.InvariantCulture);
|
||||
|
||||
ReadTuple(reader, tuple);
|
||||
int width = int.Parse(tuple[0], CultureInfo.InvariantCulture);
|
||||
int height = int.Parse(tuple[1], CultureInfo.InvariantCulture);
|
||||
|
||||
region.u = x / (float)page.width;
|
||||
region.v = y / (float)page.height;
|
||||
if (region.rotate) {
|
||||
region.u2 = (x + height) / (float)page.width;
|
||||
region.v2 = (y + width) / (float)page.height;
|
||||
} else {
|
||||
region.u2 = (x + width) / (float)page.width;
|
||||
region.v2 = (y + height) / (float)page.height;
|
||||
}
|
||||
region.x = x;
|
||||
region.y = y;
|
||||
region.width = Math.Abs(width);
|
||||
region.height = Math.Abs(height);
|
||||
|
||||
if (ReadTuple(reader, tuple) == 4) { // split is optional
|
||||
region.splits = new [] {int.Parse(tuple[0], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[1], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[2], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[3], CultureInfo.InvariantCulture)};
|
||||
|
||||
if (ReadTuple(reader, tuple) == 4) { // pad is optional, but only present with splits
|
||||
region.pads = new [] {int.Parse(tuple[0], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[1], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[2], CultureInfo.InvariantCulture),
|
||||
int.Parse(tuple[3], CultureInfo.InvariantCulture)};
|
||||
|
||||
ReadTuple(reader, tuple);
|
||||
}
|
||||
}
|
||||
|
||||
region.originalWidth = int.Parse(tuple[0], CultureInfo.InvariantCulture);
|
||||
region.originalHeight = int.Parse(tuple[1], CultureInfo.InvariantCulture);
|
||||
|
||||
ReadTuple(reader, tuple);
|
||||
region.offsetX = int.Parse(tuple[0], CultureInfo.InvariantCulture);
|
||||
region.offsetY = int.Parse(tuple[1], CultureInfo.InvariantCulture);
|
||||
|
||||
region.index = int.Parse(ReadValue(reader), CultureInfo.InvariantCulture);
|
||||
|
||||
regions.Add(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static string ReadValue (TextReader reader) {
|
||||
string line = reader.ReadLine();
|
||||
int colon = line.IndexOf(':');
|
||||
if (colon == -1) throw new Exception("Invalid line: " + line);
|
||||
return line.Substring(colon + 1).Trim();
|
||||
}
|
||||
|
||||
/// <summary>Returns the number of tuple values read (1, 2 or 4).</summary>
|
||||
static int ReadTuple (TextReader reader, string[] tuple) {
|
||||
string line = reader.ReadLine();
|
||||
int colon = line.IndexOf(':');
|
||||
if (colon == -1) throw new Exception("Invalid line: " + line);
|
||||
int i = 0, lastMatch = colon + 1;
|
||||
for (; i < 3; i++) {
|
||||
int comma = line.IndexOf(',', lastMatch);
|
||||
if (comma == -1) break;
|
||||
tuple[i] = line.Substring(lastMatch, comma - lastMatch).Trim();
|
||||
lastMatch = comma + 1;
|
||||
}
|
||||
tuple[i] = line.Substring(lastMatch).Trim();
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
public void FlipV () {
|
||||
for (int i = 0, n = regions.Count; i < n; i++) {
|
||||
AtlasRegion region = regions[i];
|
||||
region.v = 1 - region.v;
|
||||
region.v2 = 1 - region.v2;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returns the first region found with the specified name. This method uses string comparison to find the region, so the result
|
||||
/// should be cached rather than calling this method multiple times.</summary>
|
||||
/// <returns>The region, or null.</returns>
|
||||
public AtlasRegion FindRegion (string name) {
|
||||
for (int i = 0, n = regions.Count; i < n; i++)
|
||||
if (regions[i].name == name) return regions[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Dispose () {
|
||||
if (textureLoader == null) return;
|
||||
for (int i = 0, n = pages.Count; i < n; i++)
|
||||
textureLoader.Unload(pages[i].rendererObject);
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format {
|
||||
Alpha,
|
||||
Intensity,
|
||||
LuminanceAlpha,
|
||||
RGB565,
|
||||
RGBA4444,
|
||||
RGB888,
|
||||
RGBA8888
|
||||
}
|
||||
|
||||
public enum TextureFilter {
|
||||
Nearest,
|
||||
Linear,
|
||||
MipMap,
|
||||
MipMapNearestNearest,
|
||||
MipMapLinearNearest,
|
||||
MipMapNearestLinear,
|
||||
MipMapLinearLinear
|
||||
}
|
||||
|
||||
public enum TextureWrap {
|
||||
MirroredRepeat,
|
||||
ClampToEdge,
|
||||
Repeat
|
||||
}
|
||||
|
||||
public class AtlasPage {
|
||||
public string name;
|
||||
public Format format;
|
||||
public TextureFilter minFilter;
|
||||
public TextureFilter magFilter;
|
||||
public TextureWrap uWrap;
|
||||
public TextureWrap vWrap;
|
||||
public object rendererObject;
|
||||
public int width, height;
|
||||
|
||||
public AtlasPage Clone () {
|
||||
return MemberwiseClone() as AtlasPage;
|
||||
}
|
||||
}
|
||||
|
||||
public class AtlasRegion {
|
||||
public AtlasPage page;
|
||||
public string name;
|
||||
public int x, y, width, height;
|
||||
public float u, v, u2, v2;
|
||||
public float offsetX, offsetY;
|
||||
public int originalWidth, originalHeight;
|
||||
public int index;
|
||||
public bool rotate;
|
||||
public int degrees;
|
||||
public int[] splits;
|
||||
public int[] pads;
|
||||
|
||||
public AtlasRegion Clone () {
|
||||
return MemberwiseClone() as AtlasRegion;
|
||||
}
|
||||
}
|
||||
|
||||
public interface TextureLoader {
|
||||
void Load (AtlasPage page, string path);
|
||||
void Unload (Object texture);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60626307629cc034bafd42c53a901fff
|
||||
timeCreated: 1456265154
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2afe1c6b912aac54abb5925ca4ac52c2
|
||||
folderAsset: yes
|
||||
timeCreated: 1456265152
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,109 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
|
||||
/// <summary>
|
||||
/// An AttachmentLoader that configures attachments using texture regions from an Atlas.
|
||||
/// See <a href='http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data'>Loading Skeleton Data</a> in the Spine Runtimes Guide.
|
||||
/// </summary>
|
||||
public class AtlasAttachmentLoader : AttachmentLoader {
|
||||
private Atlas[] atlasArray;
|
||||
|
||||
public AtlasAttachmentLoader (params Atlas[] atlasArray) {
|
||||
if (atlasArray == null) throw new ArgumentNullException("atlas array cannot be null.");
|
||||
this.atlasArray = atlasArray;
|
||||
}
|
||||
|
||||
public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
|
||||
AtlasRegion region = FindRegion(path);
|
||||
if (region == null) throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
|
||||
RegionAttachment attachment = new RegionAttachment(name);
|
||||
attachment.RendererObject = region;
|
||||
attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
|
||||
attachment.regionOffsetX = region.offsetX;
|
||||
attachment.regionOffsetY = region.offsetY;
|
||||
attachment.regionWidth = region.width;
|
||||
attachment.regionHeight = region.height;
|
||||
attachment.regionOriginalWidth = region.originalWidth;
|
||||
attachment.regionOriginalHeight = region.originalHeight;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
|
||||
AtlasRegion region = FindRegion(path);
|
||||
if (region == null) throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
|
||||
MeshAttachment attachment = new MeshAttachment(name);
|
||||
attachment.RendererObject = region;
|
||||
attachment.RegionU = region.u;
|
||||
attachment.RegionV = region.v;
|
||||
attachment.RegionU2 = region.u2;
|
||||
attachment.RegionV2 = region.v2;
|
||||
attachment.RegionRotate = region.rotate;
|
||||
attachment.RegionDegrees = region.degrees;
|
||||
attachment.regionOffsetX = region.offsetX;
|
||||
attachment.regionOffsetY = region.offsetY;
|
||||
attachment.regionWidth = region.width;
|
||||
attachment.regionHeight = region.height;
|
||||
attachment.regionOriginalWidth = region.originalWidth;
|
||||
attachment.regionOriginalHeight = region.originalHeight;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
|
||||
return new BoundingBoxAttachment(name);
|
||||
}
|
||||
|
||||
public PathAttachment NewPathAttachment (Skin skin, string name) {
|
||||
return new PathAttachment(name);
|
||||
}
|
||||
|
||||
public PointAttachment NewPointAttachment (Skin skin, string name) {
|
||||
return new PointAttachment(name);
|
||||
}
|
||||
|
||||
public ClippingAttachment NewClippingAttachment(Skin skin, string name) {
|
||||
return new ClippingAttachment(name);
|
||||
}
|
||||
|
||||
public AtlasRegion FindRegion (string name) {
|
||||
AtlasRegion region;
|
||||
|
||||
for (int i = 0; i < atlasArray.Length; i++) {
|
||||
region = atlasArray[i].FindRegion(name);
|
||||
if (region != null)
|
||||
return region;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e6ff30e27c28344bad3e67d308c94cd
|
||||
timeCreated: 1466772712
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,52 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
abstract public class Attachment {
|
||||
public string Name { get; private set; }
|
||||
|
||||
protected Attachment (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null");
|
||||
Name = name;
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return Name;
|
||||
}
|
||||
|
||||
///<summary>Returns a copy of the attachment.</summary>
|
||||
public abstract Attachment Copy ();
|
||||
}
|
||||
|
||||
public interface IHasRendererObject {
|
||||
object RendererObject { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05b56321b2ddd8145a888746bc6ab917
|
||||
timeCreated: 1456265153
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,48 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
public interface AttachmentLoader {
|
||||
/// <return>May be null to not load any attachment.</return>
|
||||
RegionAttachment NewRegionAttachment (Skin skin, string name, string path);
|
||||
|
||||
/// <return>May be null to not load any attachment.</return>
|
||||
MeshAttachment NewMeshAttachment (Skin skin, string name, string path);
|
||||
|
||||
/// <return>May be null to not load any attachment.</return>
|
||||
BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name);
|
||||
|
||||
/// <returns>May be null to not load any attachment</returns>
|
||||
PathAttachment NewPathAttachment (Skin skin, string name);
|
||||
|
||||
PointAttachment NewPointAttachment (Skin skin, string name);
|
||||
|
||||
ClippingAttachment NewClippingAttachment (Skin skin, string name);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95466a4f5a30dca4aa69e8ee7df8ae85
|
||||
timeCreated: 1466772712
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,34 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
public enum AttachmentType {
|
||||
Region, Boundingbox, Mesh, Linkedmesh, Path, Point, Clipping
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6b1941960a9f6f47be3e865554d8695
|
||||
timeCreated: 1466772712
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,45 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>Attachment that has a polygon for bounds checking.</summary>
|
||||
public class BoundingBoxAttachment : VertexAttachment {
|
||||
public BoundingBoxAttachment (string name)
|
||||
: base(name) {
|
||||
}
|
||||
|
||||
public override Attachment Copy () {
|
||||
BoundingBoxAttachment copy = new BoundingBoxAttachment(this.Name);
|
||||
CopyTo(copy);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd8ad8fc0f5bce448ba26d096ab32e85
|
||||
timeCreated: 1466772712
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,48 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
public class ClippingAttachment : VertexAttachment {
|
||||
internal SlotData endSlot;
|
||||
|
||||
public SlotData EndSlot { get { return endSlot; } set { endSlot = value; } }
|
||||
|
||||
public ClippingAttachment(string name) : base(name) {
|
||||
}
|
||||
|
||||
public override Attachment Copy () {
|
||||
ClippingAttachment copy = new ClippingAttachment(this.Name);
|
||||
CopyTo(copy);
|
||||
copy.endSlot = endSlot;
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3380954b107f38b4c85a4cdfeceace42
|
||||
timeCreated: 1492744746
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,34 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
namespace Spine {
|
||||
public enum BlendMode {
|
||||
Normal, Additive, Multiply, Screen
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b08ef68b8e39f40498ef24ef12cca281
|
||||
timeCreated: 1456265155
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,366 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
/// <summary>
|
||||
/// Stores a bone's current pose.
|
||||
/// <para>
|
||||
/// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a
|
||||
/// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a
|
||||
/// constraint or application code modifies the world transform after it was computed from the local transform.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public class Bone : IUpdatable {
|
||||
static public bool yDown;
|
||||
|
||||
internal BoneData data;
|
||||
internal Skeleton skeleton;
|
||||
internal Bone parent;
|
||||
internal ExposedList<Bone> children = new ExposedList<Bone>();
|
||||
internal float x, y, rotation, scaleX, scaleY, shearX, shearY;
|
||||
internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
|
||||
internal bool appliedValid;
|
||||
|
||||
internal float a, b, worldX;
|
||||
internal float c, d, worldY;
|
||||
|
||||
internal bool sorted, active;
|
||||
|
||||
public BoneData Data { get { return data; } }
|
||||
public Skeleton Skeleton { get { return skeleton; } }
|
||||
public Bone Parent { get { return parent; } }
|
||||
public ExposedList<Bone> Children { get { return children; } }
|
||||
/// <summary>Returns false when the bone has not been computed because <see cref="BoneData.SkinRequired"/> is true and the
|
||||
/// <see cref="Skeleton.Skin">active skin</see> does not <see cref="Skin.Bones">contain</see> this bone.</summary>
|
||||
public bool Active { get { return active; } }
|
||||
/// <summary>The local X translation.</summary>
|
||||
public float X { get { return x; } set { x = value; } }
|
||||
/// <summary>The local Y translation.</summary>
|
||||
public float Y { get { return y; } set { y = value; } }
|
||||
/// <summary>The local rotation.</summary>
|
||||
public float Rotation { get { return rotation; } set { rotation = value; } }
|
||||
|
||||
/// <summary>The local scaleX.</summary>
|
||||
public float ScaleX { get { return scaleX; } set { scaleX = value; } }
|
||||
|
||||
/// <summary>The local scaleY.</summary>
|
||||
public float ScaleY { get { return scaleY; } set { scaleY = value; } }
|
||||
|
||||
/// <summary>The local shearX.</summary>
|
||||
public float ShearX { get { return shearX; } set { shearX = value; } }
|
||||
|
||||
/// <summary>The local shearY.</summary>
|
||||
public float ShearY { get { return shearY; } set { shearY = value; } }
|
||||
|
||||
/// <summary>The rotation, as calculated by any constraints.</summary>
|
||||
public float AppliedRotation { get { return arotation; } set { arotation = value; } }
|
||||
|
||||
/// <summary>The applied local x translation.</summary>
|
||||
public float AX { get { return ax; } set { ax = value; } }
|
||||
|
||||
/// <summary>The applied local y translation.</summary>
|
||||
public float AY { get { return ay; } set { ay = value; } }
|
||||
|
||||
/// <summary>The applied local scaleX.</summary>
|
||||
public float AScaleX { get { return ascaleX; } set { ascaleX = value; } }
|
||||
|
||||
/// <summary>The applied local scaleY.</summary>
|
||||
public float AScaleY { get { return ascaleY; } set { ascaleY = value; } }
|
||||
|
||||
/// <summary>The applied local shearX.</summary>
|
||||
public float AShearX { get { return ashearX; } set { ashearX = value; } }
|
||||
|
||||
/// <summary>The applied local shearY.</summary>
|
||||
public float AShearY { get { return ashearY; } set { ashearY = value; } }
|
||||
|
||||
public float A { get { return a; } }
|
||||
public float B { get { return b; } }
|
||||
public float C { get { return c; } }
|
||||
public float D { get { return d; } }
|
||||
|
||||
public float WorldX { get { return worldX; } }
|
||||
public float WorldY { get { return worldY; } }
|
||||
public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } }
|
||||
public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } }
|
||||
|
||||
/// <summary>Returns the magnitide (always positive) of the world scale X.</summary>
|
||||
public float WorldScaleX { get { return (float)Math.Sqrt(a * a + c * c); } }
|
||||
/// <summary>Returns the magnitide (always positive) of the world scale Y.</summary>
|
||||
public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d); } }
|
||||
|
||||
/// <param name="parent">May be null.</param>
|
||||
public Bone (BoneData data, Skeleton skeleton, Bone parent) {
|
||||
if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
|
||||
if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
|
||||
this.data = data;
|
||||
this.skeleton = skeleton;
|
||||
this.parent = parent;
|
||||
SetToSetupPose();
|
||||
}
|
||||
|
||||
/// <summary>Same as <see cref="UpdateWorldTransform"/>. This method exists for Bone to implement <see cref="Spine.IUpdatable"/>.</summary>
|
||||
public void Update () {
|
||||
UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
|
||||
}
|
||||
|
||||
/// <summary>Computes the world transform using the parent bone and this bone's local transform.</summary>
|
||||
public void UpdateWorldTransform () {
|
||||
UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
|
||||
}
|
||||
|
||||
/// <summary>Computes the world transform using the parent bone and the specified local transform.</summary>
|
||||
public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
|
||||
ax = x;
|
||||
ay = y;
|
||||
arotation = rotation;
|
||||
ascaleX = scaleX;
|
||||
ascaleY = scaleY;
|
||||
ashearX = shearX;
|
||||
ashearY = shearY;
|
||||
appliedValid = true;
|
||||
Skeleton skeleton = this.skeleton;
|
||||
|
||||
Bone parent = this.parent;
|
||||
if (parent == null) { // Root bone.
|
||||
float rotationY = rotation + 90 + shearY, sx = skeleton.ScaleX, sy = skeleton.ScaleY;
|
||||
a = MathUtils.CosDeg(rotation + shearX) * scaleX * sx;
|
||||
b = MathUtils.CosDeg(rotationY) * scaleY * sx;
|
||||
c = MathUtils.SinDeg(rotation + shearX) * scaleX * sy;
|
||||
d = MathUtils.SinDeg(rotationY) * scaleY * sy;
|
||||
worldX = x * sx + skeleton.x;
|
||||
worldY = y * sy + skeleton.y;
|
||||
return;
|
||||
}
|
||||
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||
worldX = pa * x + pb * y + parent.worldX;
|
||||
worldY = pc * x + pd * y + parent.worldY;
|
||||
|
||||
switch (data.transformMode) {
|
||||
case TransformMode.Normal: {
|
||||
float rotationY = rotation + 90 + shearY;
|
||||
float la = MathUtils.CosDeg(rotation + shearX) * scaleX;
|
||||
float lb = MathUtils.CosDeg(rotationY) * scaleY;
|
||||
float lc = MathUtils.SinDeg(rotation + shearX) * scaleX;
|
||||
float ld = MathUtils.SinDeg(rotationY) * scaleY;
|
||||
a = pa * la + pb * lc;
|
||||
b = pa * lb + pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
return;
|
||||
}
|
||||
case TransformMode.OnlyTranslation: {
|
||||
float rotationY = rotation + 90 + shearY;
|
||||
a = MathUtils.CosDeg(rotation + shearX) * scaleX;
|
||||
b = MathUtils.CosDeg(rotationY) * scaleY;
|
||||
c = MathUtils.SinDeg(rotation + shearX) * scaleX;
|
||||
d = MathUtils.SinDeg(rotationY) * scaleY;
|
||||
break;
|
||||
}
|
||||
case TransformMode.NoRotationOrReflection: {
|
||||
float s = pa * pa + pc * pc, prx;
|
||||
if (s > 0.0001f) {
|
||||
s = Math.Abs(pa * pd - pb * pc) / s;
|
||||
pa /= skeleton.ScaleX;
|
||||
pc /= skeleton.ScaleY;
|
||||
pb = pc * s;
|
||||
pd = pa * s;
|
||||
prx = MathUtils.Atan2(pc, pa) * MathUtils.RadDeg;
|
||||
} else {
|
||||
pa = 0;
|
||||
pc = 0;
|
||||
prx = 90 - MathUtils.Atan2(pd, pb) * MathUtils.RadDeg;
|
||||
}
|
||||
float rx = rotation + shearX - prx;
|
||||
float ry = rotation + shearY - prx + 90;
|
||||
float la = MathUtils.CosDeg(rx) * scaleX;
|
||||
float lb = MathUtils.CosDeg(ry) * scaleY;
|
||||
float lc = MathUtils.SinDeg(rx) * scaleX;
|
||||
float ld = MathUtils.SinDeg(ry) * scaleY;
|
||||
a = pa * la - pb * lc;
|
||||
b = pa * lb - pb * ld;
|
||||
c = pc * la + pd * lc;
|
||||
d = pc * lb + pd * ld;
|
||||
break;
|
||||
}
|
||||
case TransformMode.NoScale:
|
||||
case TransformMode.NoScaleOrReflection: {
|
||||
float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation);
|
||||
float za = (pa * cos + pb * sin) / skeleton.ScaleX;
|
||||
float zc = (pc * cos + pd * sin) / skeleton.ScaleY;
|
||||
float s = (float)Math.Sqrt(za * za + zc * zc);
|
||||
if (s > 0.00001f) s = 1 / s;
|
||||
za *= s;
|
||||
zc *= s;
|
||||
s = (float)Math.Sqrt(za * za + zc * zc);
|
||||
if (data.transformMode == TransformMode.NoScale
|
||||
&& (pa * pd - pb * pc < 0) != (skeleton.ScaleX < 0 != skeleton.ScaleY < 0)) s = -s;
|
||||
|
||||
float r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za);
|
||||
float zb = MathUtils.Cos(r) * s;
|
||||
float zd = MathUtils.Sin(r) * s;
|
||||
float la = MathUtils.CosDeg(shearX) * scaleX;
|
||||
float lb = MathUtils.CosDeg(90 + shearY) * scaleY;
|
||||
float lc = MathUtils.SinDeg(shearX) * scaleX;
|
||||
float ld = MathUtils.SinDeg(90 + shearY) * scaleY;
|
||||
a = za * la + zb * lc;
|
||||
b = za * lb + zb * ld;
|
||||
c = zc * la + zd * lc;
|
||||
d = zc * lb + zd * ld;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
a *= skeleton.ScaleX;
|
||||
b *= skeleton.ScaleX;
|
||||
c *= skeleton.ScaleY;
|
||||
d *= skeleton.ScaleY;
|
||||
}
|
||||
|
||||
public void SetToSetupPose () {
|
||||
BoneData data = this.data;
|
||||
x = data.x;
|
||||
y = data.y;
|
||||
rotation = data.rotation;
|
||||
scaleX = data.scaleX;
|
||||
scaleY = data.scaleY;
|
||||
shearX = data.shearX;
|
||||
shearY = data.shearY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the individual applied transform values from the world transform. This can be useful to perform processing using
|
||||
/// the applied transform after the world transform has been modified directly (eg, by a constraint)..
|
||||
///
|
||||
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation.
|
||||
/// </summary>
|
||||
internal void UpdateAppliedTransform () {
|
||||
appliedValid = true;
|
||||
Bone parent = this.parent;
|
||||
if (parent == null) {
|
||||
ax = worldX;
|
||||
ay = worldY;
|
||||
arotation = MathUtils.Atan2(c, a) * MathUtils.RadDeg;
|
||||
ascaleX = (float)Math.Sqrt(a * a + c * c);
|
||||
ascaleY = (float)Math.Sqrt(b * b + d * d);
|
||||
ashearX = 0;
|
||||
ashearY = MathUtils.Atan2(a * b + c * d, a * d - b * c) * MathUtils.RadDeg;
|
||||
return;
|
||||
}
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
||||
float pid = 1 / (pa * pd - pb * pc);
|
||||
float dx = worldX - parent.worldX, dy = worldY - parent.worldY;
|
||||
ax = (dx * pd * pid - dy * pb * pid);
|
||||
ay = (dy * pa * pid - dx * pc * pid);
|
||||
float ia = pid * pd;
|
||||
float id = pid * pa;
|
||||
float ib = pid * pb;
|
||||
float ic = pid * pc;
|
||||
float ra = ia * a - ib * c;
|
||||
float rb = ia * b - ib * d;
|
||||
float rc = id * c - ic * a;
|
||||
float rd = id * d - ic * b;
|
||||
ashearX = 0;
|
||||
ascaleX = (float)Math.Sqrt(ra * ra + rc * rc);
|
||||
if (ascaleX > 0.0001f) {
|
||||
float det = ra * rd - rb * rc;
|
||||
ascaleY = det / ascaleX;
|
||||
ashearY = MathUtils.Atan2(ra * rb + rc * rd, det) * MathUtils.RadDeg;
|
||||
arotation = MathUtils.Atan2(rc, ra) * MathUtils.RadDeg;
|
||||
} else {
|
||||
ascaleX = 0;
|
||||
ascaleY = (float)Math.Sqrt(rb * rb + rd * rd);
|
||||
ashearY = 0;
|
||||
arotation = 90 - MathUtils.Atan2(rd, rb) * MathUtils.RadDeg;
|
||||
}
|
||||
}
|
||||
|
||||
public void WorldToLocal (float worldX, float worldY, out float localX, out float localY) {
|
||||
float a = this.a, b = this.b, c = this.c, d = this.d;
|
||||
float invDet = 1 / (a * d - b * c);
|
||||
float x = worldX - this.worldX, y = worldY - this.worldY;
|
||||
localX = (x * d * invDet - y * b * invDet);
|
||||
localY = (y * a * invDet - x * c * invDet);
|
||||
}
|
||||
|
||||
public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) {
|
||||
worldX = localX * a + localY * b + this.worldX;
|
||||
worldY = localX * c + localY * d + this.worldY;
|
||||
}
|
||||
|
||||
public float WorldToLocalRotationX {
|
||||
get {
|
||||
Bone parent = this.parent;
|
||||
if (parent == null) return arotation;
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c;
|
||||
return MathUtils.Atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.RadDeg;
|
||||
}
|
||||
}
|
||||
|
||||
public float WorldToLocalRotationY {
|
||||
get {
|
||||
Bone parent = this.parent;
|
||||
if (parent == null) return arotation;
|
||||
float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d;
|
||||
return MathUtils.Atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.RadDeg;
|
||||
}
|
||||
}
|
||||
|
||||
public float WorldToLocalRotation (float worldRotation) {
|
||||
float sin = MathUtils.SinDeg(worldRotation), cos = MathUtils.CosDeg(worldRotation);
|
||||
return MathUtils.Atan2(a * sin - c * cos, d * cos - b * sin) * MathUtils.RadDeg + rotation - shearX;
|
||||
}
|
||||
|
||||
public float LocalToWorldRotation (float localRotation) {
|
||||
localRotation -= rotation - shearX;
|
||||
float sin = MathUtils.SinDeg(localRotation), cos = MathUtils.CosDeg(localRotation);
|
||||
return MathUtils.Atan2(cos * c + sin * d, cos * a + sin * b) * MathUtils.RadDeg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the world transform the specified amount and sets isAppliedValid to false.
|
||||
/// </summary>
|
||||
/// <param name="degrees">Degrees.</param>
|
||||
public void RotateWorld (float degrees) {
|
||||
float a = this.a, b = this.b, c = this.c, d = this.d;
|
||||
float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees);
|
||||
this.a = cos * a - sin * c;
|
||||
this.b = cos * b - sin * d;
|
||||
this.c = sin * a + cos * c;
|
||||
this.d = sin * b + cos * d;
|
||||
appliedValid = false;
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return data.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed00e3a4b386a964fb0f1c7ffd5544e5
|
||||
timeCreated: 1456265155
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,105 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
|
||||
namespace Spine {
|
||||
public class BoneData {
|
||||
internal int index;
|
||||
internal string name;
|
||||
internal BoneData parent;
|
||||
internal float length;
|
||||
internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
|
||||
internal TransformMode transformMode = TransformMode.Normal;
|
||||
internal bool skinRequired;
|
||||
|
||||
/// <summary>The index of the bone in Skeleton.Bones</summary>
|
||||
public int Index { get { return index; } }
|
||||
|
||||
/// <summary>The name of the bone, which is unique across all bones in the skeleton.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
/// <summary>May be null.</summary>
|
||||
public BoneData Parent { get { return parent; } }
|
||||
|
||||
public float Length { get { return length; } set { length = value; } }
|
||||
|
||||
/// <summary>Local X translation.</summary>
|
||||
public float X { get { return x; } set { x = value; } }
|
||||
|
||||
/// <summary>Local Y translation.</summary>
|
||||
public float Y { get { return y; } set { y = value; } }
|
||||
|
||||
/// <summary>Local rotation.</summary>
|
||||
public float Rotation { get { return rotation; } set { rotation = value; } }
|
||||
|
||||
/// <summary>Local scaleX.</summary>
|
||||
public float ScaleX { get { return scaleX; } set { scaleX = value; } }
|
||||
|
||||
/// <summary>Local scaleY.</summary>
|
||||
public float ScaleY { get { return scaleY; } set { scaleY = value; } }
|
||||
|
||||
/// <summary>Local shearX.</summary>
|
||||
public float ShearX { get { return shearX; } set { shearX = value; } }
|
||||
|
||||
/// <summary>Local shearY.</summary>
|
||||
public float ShearY { get { return shearY; } set { shearY = value; } }
|
||||
|
||||
/// <summary>The transform mode for how parent world transforms affect this bone.</summary>
|
||||
public TransformMode TransformMode { get { return transformMode; } set { transformMode = value; } }
|
||||
|
||||
///<summary>When true, <see cref="Skeleton.UpdateWorldTransform()"/> only updates this bone if the <see cref="Skeleton.Skin"/> contains this
|
||||
/// bone.</summary>
|
||||
/// <seealso cref="Skin.Bones"/>
|
||||
public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
|
||||
|
||||
/// <param name="parent">May be null.</param>
|
||||
public BoneData (int index, string name, BoneData parent) {
|
||||
if (index < 0) throw new ArgumentException("index must be >= 0", "index");
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum TransformMode {
|
||||
//0000 0 Flip Scale Rotation
|
||||
Normal = 0, // 0000
|
||||
OnlyTranslation = 7, // 0111
|
||||
NoRotationOrReflection = 1, // 0001
|
||||
NoScale = 2, // 0010
|
||||
NoScaleOrReflection = 6, // 0110
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cf831005966832449a5de742752e578
|
||||
timeCreated: 1456265153
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b41ddd57048a62b41951dbbfd453ab98
|
||||
folderAsset: yes
|
||||
timeCreated: 1565181882
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,62 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine
|
||||
{
|
||||
/// <summary>The base class for all constraint datas.</summary>
|
||||
public abstract class ConstraintData {
|
||||
internal readonly string name;
|
||||
internal int order;
|
||||
internal bool skinRequired;
|
||||
|
||||
public ConstraintData (string name) {
|
||||
if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/// <summary> The constraint's name, which is unique across all constraints in the skeleton of the same type.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
///<summary>The ordinal of this constraint for the order a skeleton's constraints will be applied by
|
||||
/// <see cref="Skeleton.UpdateWorldTransform()"/>.</summary>
|
||||
public int Order { get { return order; } set { order = value; } }
|
||||
|
||||
///<summary>When true, <see cref="Skeleton.UpdateWorldTransform()"/> only updates this constraint if the <see cref="Skeleton.Skin"/> contains
|
||||
/// this constraint.</summary>
|
||||
///<seealso cref="Skin.Constraints"/>
|
||||
public bool SkinRequired { get { return skinRequired; } set { skinRequired = value; } }
|
||||
|
||||
override public string ToString () {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55d3827079aca3a4687535c3ede7ec5f
|
||||
timeCreated: 1636570216
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dc4b7c23385e8c43ad19d01cbed78ce
|
||||
folderAsset: yes
|
||||
timeCreated: 1455489521
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,66 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#define AUTOINIT_SPINEREFERENCE
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[CreateAssetMenu(menuName = "Spine/Animation Reference Asset", order = 100)]
|
||||
public class AnimationReferenceAsset : ScriptableObject, IHasSkeletonDataAsset {
|
||||
const bool QuietSkeletonData = true;
|
||||
|
||||
[SerializeField] protected SkeletonDataAsset skeletonDataAsset;
|
||||
[SerializeField, SpineAnimation] protected string animationName;
|
||||
private Animation animation;
|
||||
|
||||
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } }
|
||||
|
||||
public Animation Animation {
|
||||
get {
|
||||
#if AUTOINIT_SPINEREFERENCE
|
||||
if (animation == null)
|
||||
Initialize();
|
||||
#endif
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
if (skeletonDataAsset == null) return;
|
||||
this.animation = skeletonDataAsset.GetSkeletonData(AnimationReferenceAsset.QuietSkeletonData).FindAnimation(animationName);
|
||||
if (this.animation == null) Debug.LogWarningFormat("Animation '{0}' not found in SkeletonData : {1}.", animationName, skeletonDataAsset.name);
|
||||
}
|
||||
|
||||
public static implicit operator Animation (AnimationReferenceAsset asset) {
|
||||
return asset.Animation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e3e95a05e4c9774397eeeb7bdee8ccb
|
||||
timeCreated: 1523328498
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 52b12ec801461494185a4d3dc66f3d1d, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,44 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
public abstract class AtlasAssetBase : ScriptableObject {
|
||||
public abstract Material PrimaryMaterial { get; }
|
||||
public abstract IEnumerable<Material> Materials { get; }
|
||||
public abstract int MaterialCount { get; }
|
||||
|
||||
public abstract bool IsLoaded { get; }
|
||||
public abstract void Clear ();
|
||||
public abstract Atlas GetAtlas ();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 787a36933c1c6e14db2104c01ed92dcb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,144 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[System.Serializable]
|
||||
public class BlendModeMaterials {
|
||||
|
||||
[System.Serializable]
|
||||
public class ReplacementMaterial {
|
||||
public string pageName;
|
||||
public Material material;
|
||||
}
|
||||
|
||||
[SerializeField, HideInInspector] protected bool requiresBlendModeMaterials = false;
|
||||
public bool applyAdditiveMaterial = false;
|
||||
|
||||
public List<ReplacementMaterial> additiveMaterials = new List<ReplacementMaterial>();
|
||||
public List<ReplacementMaterial> multiplyMaterials = new List<ReplacementMaterial>();
|
||||
public List<ReplacementMaterial> screenMaterials = new List<ReplacementMaterial>();
|
||||
|
||||
public bool RequiresBlendModeMaterials { get { return requiresBlendModeMaterials; } set { requiresBlendModeMaterials = value; } }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void TransferSettingsFrom (BlendModeMaterialsAsset modifierAsset) {
|
||||
applyAdditiveMaterial = modifierAsset.applyAdditiveMaterial;
|
||||
}
|
||||
|
||||
public bool UpdateBlendmodeMaterialsRequiredState (SkeletonData skeletonData) {
|
||||
requiresBlendModeMaterials = false;
|
||||
|
||||
if (skeletonData == null) throw new ArgumentNullException("skeletonData");
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.blendMode == BlendMode.Normal) continue;
|
||||
if (!applyAdditiveMaterial && slot.blendMode == BlendMode.Additive) continue;
|
||||
|
||||
skinEntries.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
if (entry.Attachment is IHasRendererObject) {
|
||||
requiresBlendModeMaterials = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
public void ApplyMaterials (SkeletonData skeletonData) {
|
||||
if (skeletonData == null) throw new ArgumentNullException("skeletonData");
|
||||
if (!requiresBlendModeMaterials)
|
||||
return;
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.blendMode == BlendMode.Normal) continue;
|
||||
if (!applyAdditiveMaterial && slot.blendMode == BlendMode.Additive) continue;
|
||||
|
||||
List<ReplacementMaterial> replacementMaterials = null;
|
||||
switch (slot.blendMode) {
|
||||
case BlendMode.Multiply:
|
||||
replacementMaterials = multiplyMaterials;
|
||||
break;
|
||||
case BlendMode.Screen:
|
||||
replacementMaterials = screenMaterials;
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
replacementMaterials = additiveMaterials;
|
||||
break;
|
||||
}
|
||||
if (replacementMaterials == null)
|
||||
continue;
|
||||
|
||||
skinEntries.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
var renderableAttachment = entry.Attachment as IHasRendererObject;
|
||||
if (renderableAttachment != null) {
|
||||
renderableAttachment.RendererObject = CloneAtlasRegionWithMaterial(
|
||||
(AtlasRegion)renderableAttachment.RendererObject, replacementMaterials);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected AtlasRegion CloneAtlasRegionWithMaterial (AtlasRegion originalRegion, List<ReplacementMaterial> replacementMaterials) {
|
||||
var newRegion = originalRegion.Clone();
|
||||
Material material = null;
|
||||
foreach (var replacement in replacementMaterials) {
|
||||
if (replacement.pageName == originalRegion.page.name) {
|
||||
material = replacement.material;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AtlasPage originalPage = originalRegion.page;
|
||||
var newPage = originalPage.Clone();
|
||||
newPage.rendererObject = material;
|
||||
newRegion.page = newPage;
|
||||
return newRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d03ca55657e89b949a4c07bc9207beac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 954179821df28404683b8289f05d0c6f
|
||||
folderAsset: yes
|
||||
timeCreated: 1518344191
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,217 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[AddComponentMenu("Spine/BoneFollower")]
|
||||
[HelpURL("http://esotericsoftware.com/spine-unity#BoneFollower")]
|
||||
public class BoneFollower : MonoBehaviour {
|
||||
|
||||
#region Inspector
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
public SkeletonRenderer SkeletonRenderer {
|
||||
get { return skeletonRenderer; }
|
||||
set {
|
||||
skeletonRenderer = value;
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>If a bone isn't set in code, boneName is used to find the bone at the beginning. For runtime switching by name, use SetBoneByName. You can also set the BoneFollower.bone field directly.</summary>
|
||||
[SpineBone(dataField: "skeletonRenderer")]
|
||||
public string boneName;
|
||||
|
||||
public bool followXYPosition = true;
|
||||
public bool followZPosition = true;
|
||||
public bool followBoneRotation = true;
|
||||
|
||||
[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
|
||||
public bool followSkeletonFlip = true;
|
||||
|
||||
[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
|
||||
public bool followLocalScale = false;
|
||||
|
||||
public enum AxisOrientation {
|
||||
XAxis = 1,
|
||||
YAxis
|
||||
}
|
||||
[Tooltip("Applies when 'Follow Skeleton Flip' is disabled but 'Follow Bone Rotation' is enabled."
|
||||
+ " When flipping the skeleton by scaling its Transform, this follower's rotation is adjusted"
|
||||
+ " instead of its scale to follow the bone orientation. When one of the axes is flipped, "
|
||||
+ " only one axis can be followed, either the X or the Y axis, which is selected here.")]
|
||||
public AxisOrientation maintainedAxisOrientation = AxisOrientation.XAxis;
|
||||
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("resetOnAwake")]
|
||||
public bool initializeOnAwake = true;
|
||||
#endregion
|
||||
|
||||
[NonSerialized] public bool valid;
|
||||
[NonSerialized] public Bone bone;
|
||||
|
||||
Transform skeletonTransform;
|
||||
bool skeletonTransformIsParent;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the target bone by its bone name. Returns false if no bone was found. To set the bone by reference, use BoneFollower.bone directly.</summary>
|
||||
public bool SetBone (string name) {
|
||||
bone = skeletonRenderer.skeleton.FindBone(name);
|
||||
if (bone == null) {
|
||||
Debug.LogError("Bone not found: " + name, this);
|
||||
return false;
|
||||
}
|
||||
boneName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Awake () {
|
||||
if (initializeOnAwake) Initialize();
|
||||
}
|
||||
|
||||
public void HandleRebuildRenderer (SkeletonRenderer skeletonRenderer) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
bone = null;
|
||||
valid = skeletonRenderer != null && skeletonRenderer.valid;
|
||||
if (!valid) return;
|
||||
|
||||
skeletonTransform = skeletonRenderer.transform;
|
||||
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
|
||||
skeletonRenderer.OnRebuild += HandleRebuildRenderer;
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
|
||||
if (!string.IsNullOrEmpty(boneName))
|
||||
bone = skeletonRenderer.skeleton.FindBone(boneName);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor)
|
||||
LateUpdate();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (skeletonRenderer != null)
|
||||
skeletonRenderer.OnRebuild -= HandleRebuildRenderer;
|
||||
}
|
||||
|
||||
public void LateUpdate () {
|
||||
if (!valid) {
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
#endif
|
||||
|
||||
if (bone == null) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = skeletonRenderer.skeleton.FindBone(boneName);
|
||||
if (!SetBone(boneName)) return;
|
||||
}
|
||||
|
||||
Transform thisTransform = this.transform;
|
||||
float additionalFlipScale = 1;
|
||||
if (skeletonTransformIsParent) {
|
||||
// Recommended setup: Use local transform properties if Spine GameObject is the immediate parent
|
||||
thisTransform.localPosition = new Vector3(followXYPosition ? bone.worldX : thisTransform.localPosition.x,
|
||||
followXYPosition ? bone.worldY : thisTransform.localPosition.y,
|
||||
followZPosition ? 0f : thisTransform.localPosition.z);
|
||||
if (followBoneRotation) {
|
||||
float halfRotation = Mathf.Atan2(bone.c, bone.a) * 0.5f;
|
||||
if (followLocalScale && bone.scaleX < 0) // Negate rotation from negative scaleX. Don't use negative determinant. local scaleY doesn't factor into used rotation.
|
||||
halfRotation += Mathf.PI * 0.5f;
|
||||
|
||||
var q = default(Quaternion);
|
||||
q.z = Mathf.Sin(halfRotation);
|
||||
q.w = Mathf.Cos(halfRotation);
|
||||
thisTransform.localRotation = q;
|
||||
}
|
||||
} else {
|
||||
// For special cases: Use transform world properties if transform relationship is complicated
|
||||
Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
|
||||
if (!followZPosition) targetWorldPosition.z = thisTransform.position.z;
|
||||
if (!followXYPosition) {
|
||||
targetWorldPosition.x = thisTransform.position.x;
|
||||
targetWorldPosition.y = thisTransform.position.y;
|
||||
}
|
||||
|
||||
Vector3 skeletonLossyScale = skeletonTransform.lossyScale;
|
||||
Transform transformParent = thisTransform.parent;
|
||||
Vector3 parentLossyScale = transformParent != null ? transformParent.lossyScale : Vector3.one;
|
||||
if (followBoneRotation) {
|
||||
float boneWorldRotation = bone.WorldRotationX;
|
||||
|
||||
if ((skeletonLossyScale.x * skeletonLossyScale.y) < 0)
|
||||
boneWorldRotation = -boneWorldRotation;
|
||||
|
||||
if (followSkeletonFlip || maintainedAxisOrientation == AxisOrientation.XAxis) {
|
||||
if ((skeletonLossyScale.x * parentLossyScale.x < 0))
|
||||
boneWorldRotation += 180f;
|
||||
}
|
||||
else {
|
||||
if ((skeletonLossyScale.y * parentLossyScale.y < 0))
|
||||
boneWorldRotation += 180f;
|
||||
}
|
||||
|
||||
Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
|
||||
if (followLocalScale && bone.scaleX < 0) boneWorldRotation += 180f;
|
||||
thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + boneWorldRotation));
|
||||
} else {
|
||||
thisTransform.position = targetWorldPosition;
|
||||
}
|
||||
|
||||
additionalFlipScale = Mathf.Sign(skeletonLossyScale.x * parentLossyScale.x
|
||||
* skeletonLossyScale.y * parentLossyScale.y);
|
||||
}
|
||||
|
||||
Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f);
|
||||
if (followSkeletonFlip)
|
||||
localScale.y *= Mathf.Sign(bone.skeleton.ScaleX * bone.skeleton.ScaleY) * additionalFlipScale;
|
||||
|
||||
thisTransform.localScale = localScale;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1fd8daaed7b64148a34acb96ba14ce1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,196 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Spine.Unity {
|
||||
using AxisOrientation = BoneFollower.AxisOrientation;
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[RequireComponent(typeof(RectTransform)), DisallowMultipleComponent]
|
||||
[AddComponentMenu("Spine/UI/BoneFollowerGraphic")]
|
||||
[HelpURL("http://esotericsoftware.com/spine-unity#BoneFollowerGraphic")]
|
||||
public class BoneFollowerGraphic : MonoBehaviour {
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public SkeletonGraphic SkeletonGraphic {
|
||||
get { return skeletonGraphic; }
|
||||
set {
|
||||
skeletonGraphic = value;
|
||||
Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public bool initializeOnAwake = true;
|
||||
|
||||
/// <summary>If a bone isn't set in code, boneName is used to find the bone at the beginning. For runtime switching by name, use SetBoneByName. You can also set the BoneFollower.bone field directly.</summary>
|
||||
[SpineBone(dataField: "skeletonGraphic")]
|
||||
public string boneName;
|
||||
|
||||
public bool followBoneRotation = true;
|
||||
[Tooltip("Follows the skeleton's flip state by controlling this Transform's local scale.")]
|
||||
public bool followSkeletonFlip = true;
|
||||
[Tooltip("Follows the target bone's local scale. BoneFollower cannot inherit world/skewed scale because of UnityEngine.Transform property limitations.")]
|
||||
public bool followLocalScale = false;
|
||||
public bool followXYPosition = true;
|
||||
public bool followZPosition = true;
|
||||
[Tooltip("Applies when 'Follow Skeleton Flip' is disabled but 'Follow Bone Rotation' is enabled."
|
||||
+ " When flipping the skeleton by scaling its Transform, this follower's rotation is adjusted"
|
||||
+ " instead of its scale to follow the bone orientation. When one of the axes is flipped, "
|
||||
+ " only one axis can be followed, either the X or the Y axis, which is selected here.")]
|
||||
public AxisOrientation maintainedAxisOrientation = AxisOrientation.XAxis;
|
||||
|
||||
[System.NonSerialized] public Bone bone;
|
||||
|
||||
Transform skeletonTransform;
|
||||
bool skeletonTransformIsParent;
|
||||
|
||||
[System.NonSerialized] public bool valid;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the target bone by its bone name. Returns false if no bone was found.</summary>
|
||||
public bool SetBone (string name) {
|
||||
bone = skeletonGraphic.Skeleton.FindBone(name);
|
||||
if (bone == null) {
|
||||
Debug.LogError("Bone not found: " + name, this);
|
||||
return false;
|
||||
}
|
||||
boneName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Awake () {
|
||||
if (initializeOnAwake) Initialize();
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
bone = null;
|
||||
valid = skeletonGraphic != null && skeletonGraphic.IsValid;
|
||||
if (!valid) return;
|
||||
|
||||
skeletonTransform = skeletonGraphic.transform;
|
||||
// skeletonGraphic.OnRebuild -= HandleRebuildRenderer;
|
||||
// skeletonGraphic.OnRebuild += HandleRebuildRenderer;
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
|
||||
if (!string.IsNullOrEmpty(boneName))
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor) {
|
||||
LateUpdate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void LateUpdate () {
|
||||
if (!valid) {
|
||||
Initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
skeletonTransformIsParent = Transform.ReferenceEquals(skeletonTransform, transform.parent);
|
||||
#endif
|
||||
|
||||
if (bone == null) {
|
||||
if (string.IsNullOrEmpty(boneName)) return;
|
||||
bone = skeletonGraphic.Skeleton.FindBone(boneName);
|
||||
if (!SetBone(boneName)) return;
|
||||
}
|
||||
|
||||
var thisTransform = this.transform as RectTransform;
|
||||
if (thisTransform == null) return;
|
||||
|
||||
var canvas = skeletonGraphic.canvas;
|
||||
if (canvas == null) canvas = skeletonGraphic.GetComponentInParent<Canvas>();
|
||||
float scale = canvas != null ? canvas.referencePixelsPerUnit : 100.0f;
|
||||
|
||||
float additionalFlipScale = 1;
|
||||
if (skeletonTransformIsParent) {
|
||||
// Recommended setup: Use local transform properties if Spine GameObject is the immediate parent
|
||||
thisTransform.localPosition = new Vector3(followXYPosition ? bone.worldX * scale : thisTransform.localPosition.x,
|
||||
followXYPosition ? bone.worldY * scale : thisTransform.localPosition.y,
|
||||
followZPosition ? 0f : thisTransform.localPosition.z);
|
||||
if (followBoneRotation) thisTransform.localRotation = bone.GetQuaternion();
|
||||
} else {
|
||||
// For special cases: Use transform world properties if transform relationship is complicated
|
||||
Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX * scale, bone.worldY * scale, 0f));
|
||||
if (!followZPosition) targetWorldPosition.z = thisTransform.position.z;
|
||||
if (!followXYPosition) {
|
||||
targetWorldPosition.x = thisTransform.position.x;
|
||||
targetWorldPosition.y = thisTransform.position.y;
|
||||
}
|
||||
|
||||
Vector3 skeletonLossyScale = skeletonTransform.lossyScale;
|
||||
Transform transformParent = thisTransform.parent;
|
||||
Vector3 parentLossyScale = transformParent != null ? transformParent.lossyScale : Vector3.one;
|
||||
if (followBoneRotation) {
|
||||
float boneWorldRotation = bone.WorldRotationX;
|
||||
|
||||
if ((skeletonLossyScale.x * skeletonLossyScale.y) < 0)
|
||||
boneWorldRotation = -boneWorldRotation;
|
||||
|
||||
if (followSkeletonFlip || maintainedAxisOrientation == AxisOrientation.XAxis) {
|
||||
if ((skeletonLossyScale.x * parentLossyScale.x < 0))
|
||||
boneWorldRotation += 180f;
|
||||
}
|
||||
else {
|
||||
if ((skeletonLossyScale.y * parentLossyScale.y < 0))
|
||||
boneWorldRotation += 180f;
|
||||
}
|
||||
|
||||
Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
|
||||
if (followLocalScale && bone.scaleX < 0) boneWorldRotation += 180f;
|
||||
thisTransform.SetPositionAndRotation(targetWorldPosition, Quaternion.Euler(worldRotation.x, worldRotation.y, worldRotation.z + boneWorldRotation));
|
||||
} else {
|
||||
thisTransform.position = targetWorldPosition;
|
||||
}
|
||||
|
||||
additionalFlipScale = Mathf.Sign(skeletonLossyScale.x * parentLossyScale.x
|
||||
* skeletonLossyScale.y * parentLossyScale.y);
|
||||
}
|
||||
|
||||
Vector3 localScale = followLocalScale ? new Vector3(bone.scaleX, bone.scaleY, 1f) : new Vector3(1f, 1f, 1f);
|
||||
if (followSkeletonFlip)
|
||||
localScale.y *= Mathf.Sign(bone.skeleton.ScaleX * bone.skeleton.ScaleY) * additionalFlipScale;
|
||||
thisTransform.localScale = localScale;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b42a195b47491d34b9bcbc40898bcb29
|
||||
timeCreated: 1499211965
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,253 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[HelpURL("http://esotericsoftware.com/spine-unity#BoundingBoxFollower")]
|
||||
public class BoundingBoxFollower : MonoBehaviour {
|
||||
internal static bool DebugMessages = true;
|
||||
|
||||
#region Inspector
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
[SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
|
||||
public string slotName;
|
||||
public bool isTrigger;
|
||||
public bool clearStateOnDisable = true;
|
||||
#endregion
|
||||
|
||||
Slot slot;
|
||||
BoundingBoxAttachment currentAttachment;
|
||||
string currentAttachmentName;
|
||||
PolygonCollider2D currentCollider;
|
||||
|
||||
public readonly Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
|
||||
public readonly Dictionary<BoundingBoxAttachment, string> nameTable = new Dictionary<BoundingBoxAttachment, string>();
|
||||
|
||||
public Slot Slot { get { return slot; } }
|
||||
public BoundingBoxAttachment CurrentAttachment { get { return currentAttachment; } }
|
||||
public string CurrentAttachmentName { get { return currentAttachmentName; } }
|
||||
public PolygonCollider2D CurrentCollider { get { return currentCollider; } }
|
||||
public bool IsTrigger { get { return isTrigger; } }
|
||||
|
||||
void Start () {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
if (skeletonRenderer != null) {
|
||||
skeletonRenderer.OnRebuild -= HandleRebuild;
|
||||
skeletonRenderer.OnRebuild += HandleRebuild;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void HandleRebuild (SkeletonRenderer sr) {
|
||||
//if (BoundingBoxFollower.DebugMessages) Debug.Log("Skeleton was rebuilt. Repopulating BoundingBoxFollower.");
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize and instantiate the BoundingBoxFollower colliders. This is method checks if the BoundingBoxFollower has already been initialized for the skeleton instance and slotName and prevents overwriting unless it detects a new setup.</summary>
|
||||
public void Initialize (bool overwrite = false) {
|
||||
if (skeletonRenderer == null)
|
||||
return;
|
||||
|
||||
skeletonRenderer.Initialize(false);
|
||||
|
||||
if (string.IsNullOrEmpty(slotName))
|
||||
return;
|
||||
|
||||
// Don't reinitialize if the setup did not change.
|
||||
if (!overwrite
|
||||
&&
|
||||
colliderTable.Count > 0 && slot != null // Slot is set and colliders already populated.
|
||||
&&
|
||||
skeletonRenderer.skeleton == slot.Skeleton // Skeleton object did not change.
|
||||
&&
|
||||
slotName == slot.data.name // Slot object did not change.
|
||||
)
|
||||
return;
|
||||
|
||||
slot = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
colliderTable.Clear();
|
||||
nameTable.Clear();
|
||||
|
||||
var skeleton = skeletonRenderer.skeleton;
|
||||
if (skeleton == null)
|
||||
return;
|
||||
slot = skeleton.FindSlot(slotName);
|
||||
int slotIndex = skeleton.FindSlotIndex(slotName);
|
||||
|
||||
if (slot == null) {
|
||||
if (BoundingBoxFollower.DebugMessages)
|
||||
Debug.LogWarning(string.Format("Slot '{0}' not found for BoundingBoxFollower on '{1}'. (Previous colliders were disposed.)", slotName, this.gameObject.name));
|
||||
return;
|
||||
}
|
||||
|
||||
int requiredCollidersCount = 0;
|
||||
var colliders = GetComponents<PolygonCollider2D>();
|
||||
if (this.gameObject.activeInHierarchy) {
|
||||
foreach (var skin in skeleton.Data.Skins)
|
||||
AddCollidersForSkin(skin, slotIndex, colliders, ref requiredCollidersCount);
|
||||
|
||||
if (skeleton.skin != null)
|
||||
AddCollidersForSkin(skeleton.skin, slotIndex, colliders, ref requiredCollidersCount);
|
||||
}
|
||||
DisposeExcessCollidersAfter(requiredCollidersCount);
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages) {
|
||||
bool valid = colliderTable.Count != 0;
|
||||
if (!valid) {
|
||||
if (this.gameObject.activeInHierarchy)
|
||||
Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
|
||||
else
|
||||
Debug.LogWarning("Bounding Box Follower tried to rebuild as a prefab.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddCollidersForSkin (Skin skin, int slotIndex, PolygonCollider2D[] previousColliders, ref int collidersCount) {
|
||||
if (skin == null) return;
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
var attachment = skin.GetAttachment(slotIndex, entry.Name);
|
||||
var boundingBoxAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages && attachment != null && boundingBoxAttachment == null)
|
||||
Debug.Log("BoundingBoxFollower tried to follow a slot that contains non-boundingbox attachments: " + slotName);
|
||||
|
||||
if (boundingBoxAttachment != null) {
|
||||
if (!colliderTable.ContainsKey(boundingBoxAttachment)) {
|
||||
var bbCollider = collidersCount < previousColliders.Length ?
|
||||
previousColliders[collidersCount] : gameObject.AddComponent<PolygonCollider2D>();
|
||||
++collidersCount;
|
||||
SkeletonUtility.SetColliderPointsLocal(bbCollider, slot, boundingBoxAttachment);
|
||||
bbCollider.isTrigger = isTrigger;
|
||||
bbCollider.enabled = false;
|
||||
bbCollider.hideFlags = HideFlags.NotEditable;
|
||||
bbCollider.isTrigger = IsTrigger;
|
||||
colliderTable.Add(boundingBoxAttachment, bbCollider);
|
||||
nameTable.Add(boundingBoxAttachment, entry.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (clearStateOnDisable)
|
||||
ClearState();
|
||||
|
||||
if (skeletonRenderer != null)
|
||||
skeletonRenderer.OnRebuild -= HandleRebuild;
|
||||
}
|
||||
|
||||
public void ClearState () {
|
||||
if (colliderTable != null)
|
||||
foreach (var col in colliderTable.Values)
|
||||
col.enabled = false;
|
||||
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
}
|
||||
|
||||
void DisposeExcessCollidersAfter (int requiredCount) {
|
||||
var colliders = GetComponents<PolygonCollider2D>();
|
||||
if (colliders.Length == 0) return;
|
||||
|
||||
for (int i = requiredCount; i < colliders.Length; ++i) {
|
||||
var collider = colliders[i];
|
||||
if (collider != null) {
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor && !Application.isPlaying)
|
||||
DestroyImmediate(collider);
|
||||
else
|
||||
#endif
|
||||
Destroy(collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
if (slot != null && slot.Attachment != currentAttachment)
|
||||
MatchAttachment(slot.Attachment);
|
||||
}
|
||||
|
||||
/// <summary>Sets the current collider to match attachment.</summary>
|
||||
/// <param name="attachment">If the attachment is not a bounding box, it will be treated as null.</param>
|
||||
void MatchAttachment (Attachment attachment) {
|
||||
var bbAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollower.DebugMessages && attachment != null && bbAttachment == null)
|
||||
Debug.LogWarning("BoundingBoxFollower tried to match a non-boundingbox attachment. It will treat it as null.");
|
||||
|
||||
if (currentCollider != null)
|
||||
currentCollider.enabled = false;
|
||||
|
||||
if (bbAttachment == null) {
|
||||
currentCollider = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
} else {
|
||||
PolygonCollider2D foundCollider;
|
||||
colliderTable.TryGetValue(bbAttachment, out foundCollider);
|
||||
if (foundCollider != null) {
|
||||
currentCollider = foundCollider;
|
||||
currentCollider.enabled = true;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = nameTable[bbAttachment];
|
||||
} else {
|
||||
currentCollider = null;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = null;
|
||||
if (BoundingBoxFollower.DebugMessages) Debug.LogFormat("Collider for BoundingBoxAttachment named '{0}' was not initialized. It is possibly from a new skin. currentAttachmentName will be null. You may need to call BoundingBoxFollower.Initialize(overwrite: true);", bbAttachment.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0317ee9ba6e1b1e49a030268e026d372
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -1,257 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2018_3 || UNITY_2019 || UNITY_2018_3_OR_NEWER
|
||||
#define NEW_PREFAB_SYSTEM
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
#if NEW_PREFAB_SYSTEM
|
||||
[ExecuteAlways]
|
||||
#else
|
||||
[ExecuteInEditMode]
|
||||
#endif
|
||||
[HelpURL("http://esotericsoftware.com/spine-unity#BoundingBoxFollowerGraphic")]
|
||||
public class BoundingBoxFollowerGraphic : MonoBehaviour {
|
||||
internal static bool DebugMessages = true;
|
||||
|
||||
#region Inspector
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
[SpineSlot(dataField: "skeletonGraphic", containsBoundingBoxes: true)]
|
||||
public string slotName;
|
||||
public bool isTrigger;
|
||||
public bool clearStateOnDisable = true;
|
||||
#endregion
|
||||
|
||||
Slot slot;
|
||||
BoundingBoxAttachment currentAttachment;
|
||||
string currentAttachmentName;
|
||||
PolygonCollider2D currentCollider;
|
||||
|
||||
public readonly Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
|
||||
public readonly Dictionary<BoundingBoxAttachment, string> nameTable = new Dictionary<BoundingBoxAttachment, string>();
|
||||
|
||||
public Slot Slot { get { return slot; } }
|
||||
public BoundingBoxAttachment CurrentAttachment { get { return currentAttachment; } }
|
||||
public string CurrentAttachmentName { get { return currentAttachmentName; } }
|
||||
public PolygonCollider2D CurrentCollider { get { return currentCollider; } }
|
||||
public bool IsTrigger { get { return isTrigger; } }
|
||||
|
||||
void Start () {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
if (skeletonGraphic != null) {
|
||||
skeletonGraphic.OnRebuild -= HandleRebuild;
|
||||
skeletonGraphic.OnRebuild += HandleRebuild;
|
||||
}
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void HandleRebuild (SkeletonGraphic sr) {
|
||||
//if (BoundingBoxFollowerGraphic.DebugMessages) Debug.Log("Skeleton was rebuilt. Repopulating BoundingBoxFollowerGraphic.");
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize and instantiate the BoundingBoxFollowerGraphic colliders. This is method checks if the BoundingBoxFollowerGraphic has already been initialized for the skeleton instance and slotName and prevents overwriting unless it detects a new setup.</summary>
|
||||
public void Initialize (bool overwrite = false) {
|
||||
if (skeletonGraphic == null)
|
||||
return;
|
||||
|
||||
skeletonGraphic.Initialize(false);
|
||||
|
||||
if (string.IsNullOrEmpty(slotName))
|
||||
return;
|
||||
|
||||
// Don't reinitialize if the setup did not change.
|
||||
if (!overwrite
|
||||
&&
|
||||
colliderTable.Count > 0 && slot != null // Slot is set and colliders already populated.
|
||||
&&
|
||||
skeletonGraphic.Skeleton == slot.Skeleton // Skeleton object did not change.
|
||||
&&
|
||||
slotName == slot.data.name // Slot object did not change.
|
||||
)
|
||||
return;
|
||||
|
||||
slot = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
colliderTable.Clear();
|
||||
nameTable.Clear();
|
||||
|
||||
var skeleton = skeletonGraphic.Skeleton;
|
||||
if (skeleton == null)
|
||||
return;
|
||||
slot = skeleton.FindSlot(slotName);
|
||||
int slotIndex = skeleton.FindSlotIndex(slotName);
|
||||
|
||||
if (slot == null) {
|
||||
if (BoundingBoxFollowerGraphic.DebugMessages)
|
||||
Debug.LogWarning(string.Format("Slot '{0}' not found for BoundingBoxFollowerGraphic on '{1}'. (Previous colliders were disposed.)", slotName, this.gameObject.name));
|
||||
return;
|
||||
}
|
||||
|
||||
int requiredCollidersCount = 0;
|
||||
var colliders = GetComponents<PolygonCollider2D>();
|
||||
if (this.gameObject.activeInHierarchy) {
|
||||
var canvas = skeletonGraphic.canvas;
|
||||
if (canvas == null) canvas = skeletonGraphic.GetComponentInParent<Canvas>();
|
||||
float scale = canvas != null ? canvas.referencePixelsPerUnit : 100.0f;
|
||||
|
||||
foreach (var skin in skeleton.Data.Skins)
|
||||
AddCollidersForSkin(skin, slotIndex, colliders, scale, ref requiredCollidersCount);
|
||||
|
||||
if (skeleton.skin != null)
|
||||
AddCollidersForSkin(skeleton.skin, slotIndex, colliders, scale, ref requiredCollidersCount);
|
||||
}
|
||||
DisposeExcessCollidersAfter(requiredCollidersCount);
|
||||
|
||||
if (BoundingBoxFollowerGraphic.DebugMessages) {
|
||||
bool valid = colliderTable.Count != 0;
|
||||
if (!valid) {
|
||||
if (this.gameObject.activeInHierarchy)
|
||||
Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
|
||||
else
|
||||
Debug.LogWarning("Bounding Box Follower tried to rebuild as a prefab.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddCollidersForSkin (Skin skin, int slotIndex, PolygonCollider2D[] previousColliders, float scale, ref int collidersCount) {
|
||||
if (skin == null) return;
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
var attachment = skin.GetAttachment(slotIndex, entry.Name);
|
||||
var boundingBoxAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollowerGraphic.DebugMessages && attachment != null && boundingBoxAttachment == null)
|
||||
Debug.Log("BoundingBoxFollowerGraphic tried to follow a slot that contains non-boundingbox attachments: " + slotName);
|
||||
|
||||
if (boundingBoxAttachment != null) {
|
||||
if (!colliderTable.ContainsKey(boundingBoxAttachment)) {
|
||||
var bbCollider = collidersCount < previousColliders.Length ?
|
||||
previousColliders[collidersCount] : gameObject.AddComponent<PolygonCollider2D>();
|
||||
++collidersCount;
|
||||
SkeletonUtility.SetColliderPointsLocal(bbCollider, slot, boundingBoxAttachment, scale);
|
||||
bbCollider.isTrigger = isTrigger;
|
||||
bbCollider.enabled = false;
|
||||
bbCollider.hideFlags = HideFlags.NotEditable;
|
||||
bbCollider.isTrigger = IsTrigger;
|
||||
colliderTable.Add(boundingBoxAttachment, bbCollider);
|
||||
nameTable.Add(boundingBoxAttachment, entry.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
if (clearStateOnDisable)
|
||||
ClearState();
|
||||
|
||||
if (skeletonGraphic != null)
|
||||
skeletonGraphic.OnRebuild -= HandleRebuild;
|
||||
}
|
||||
|
||||
public void ClearState () {
|
||||
if (colliderTable != null)
|
||||
foreach (var col in colliderTable.Values)
|
||||
col.enabled = false;
|
||||
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
currentCollider = null;
|
||||
}
|
||||
|
||||
void DisposeExcessCollidersAfter (int requiredCount) {
|
||||
var colliders = GetComponents<PolygonCollider2D>();
|
||||
if (colliders.Length == 0) return;
|
||||
|
||||
for (int i = requiredCount; i < colliders.Length; ++i) {
|
||||
var collider = colliders[i];
|
||||
if (collider != null) {
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor && !Application.isPlaying)
|
||||
DestroyImmediate(collider);
|
||||
else
|
||||
#endif
|
||||
Destroy(collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate () {
|
||||
if (slot != null && slot.Attachment != currentAttachment)
|
||||
MatchAttachment(slot.Attachment);
|
||||
}
|
||||
|
||||
/// <summary>Sets the current collider to match attachment.</summary>
|
||||
/// <param name="attachment">If the attachment is not a bounding box, it will be treated as null.</param>
|
||||
void MatchAttachment (Attachment attachment) {
|
||||
var bbAttachment = attachment as BoundingBoxAttachment;
|
||||
|
||||
if (BoundingBoxFollowerGraphic.DebugMessages && attachment != null && bbAttachment == null)
|
||||
Debug.LogWarning("BoundingBoxFollowerGraphic tried to match a non-boundingbox attachment. It will treat it as null.");
|
||||
|
||||
if (currentCollider != null)
|
||||
currentCollider.enabled = false;
|
||||
|
||||
if (bbAttachment == null) {
|
||||
currentCollider = null;
|
||||
currentAttachment = null;
|
||||
currentAttachmentName = null;
|
||||
} else {
|
||||
PolygonCollider2D foundCollider;
|
||||
colliderTable.TryGetValue(bbAttachment, out foundCollider);
|
||||
if (foundCollider != null) {
|
||||
currentCollider = foundCollider;
|
||||
currentCollider.enabled = true;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = nameTable[bbAttachment];
|
||||
} else {
|
||||
currentCollider = null;
|
||||
currentAttachment = bbAttachment;
|
||||
currentAttachmentName = null;
|
||||
if (BoundingBoxFollowerGraphic.DebugMessages) Debug.LogFormat("Collider for BoundingBoxAttachment named '{0}' was not initialized. It is possibly from a new skin. currentAttachmentName will be null. You may need to call BoundingBoxFollowerGraphic.Initialize(overwrite: true);", bbAttachment.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c0bf7b497af9f74280040d96cdf88da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,92 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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;
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
/// <summary>
|
||||
/// Utility component to support flipping of 2D hinge chains (chains of HingeJoint2D objects) along
|
||||
/// with the parent skeleton by activating the respective mirrored versions of the hinge chain.
|
||||
/// Note: This component is automatically attached when calling "Create Hinge Chain 2D" at <see cref="SkeletonUtilityBone"/>,
|
||||
/// do not attempt to use this component for other purposes.
|
||||
/// </summary>
|
||||
public class ActivateBasedOnFlipDirection : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderer skeletonRenderer;
|
||||
public SkeletonGraphic skeletonGraphic;
|
||||
public GameObject activeOnNormalX;
|
||||
public GameObject activeOnFlippedX;
|
||||
HingeJoint2D[] jointsNormalX;
|
||||
HingeJoint2D[] jointsFlippedX;
|
||||
ISkeletonComponent skeletonComponent;
|
||||
|
||||
bool wasFlippedXBefore = false;
|
||||
|
||||
private void Start () {
|
||||
jointsNormalX = activeOnNormalX.GetComponentsInChildren<HingeJoint2D>();
|
||||
jointsFlippedX = activeOnFlippedX.GetComponentsInChildren<HingeJoint2D>();
|
||||
skeletonComponent = skeletonRenderer != null ? (ISkeletonComponent)skeletonRenderer : (ISkeletonComponent)skeletonGraphic;
|
||||
}
|
||||
|
||||
private void FixedUpdate () {
|
||||
bool isFlippedX = (skeletonComponent.Skeleton.ScaleX < 0);
|
||||
if (isFlippedX != wasFlippedXBefore) {
|
||||
HandleFlip(isFlippedX);
|
||||
}
|
||||
wasFlippedXBefore = isFlippedX;
|
||||
}
|
||||
|
||||
void HandleFlip (bool isFlippedX) {
|
||||
GameObject gameObjectToActivate = isFlippedX ? activeOnFlippedX : activeOnNormalX;
|
||||
GameObject gameObjectToDeactivate = isFlippedX ? activeOnNormalX : activeOnFlippedX;
|
||||
|
||||
gameObjectToActivate.SetActive(true);
|
||||
gameObjectToDeactivate.SetActive(false);
|
||||
|
||||
ResetJointPositions(isFlippedX ? jointsFlippedX : jointsNormalX);
|
||||
ResetJointPositions(isFlippedX ? jointsNormalX : jointsFlippedX);
|
||||
CompensateMovementAfterFlipX(gameObjectToActivate.transform, gameObjectToDeactivate.transform);
|
||||
}
|
||||
|
||||
void ResetJointPositions (HingeJoint2D[] joints) {
|
||||
for (int i = 0; i < joints.Length; ++i) {
|
||||
var joint = joints[i];
|
||||
var parent = joint.connectedBody.transform;
|
||||
joint.transform.position = parent.TransformPoint(joint.connectedAnchor);
|
||||
}
|
||||
}
|
||||
|
||||
void CompensateMovementAfterFlipX (Transform toActivate, Transform toDeactivate) {
|
||||
Transform targetLocation = toDeactivate.GetChild(0);
|
||||
Transform currentLocation = toActivate.GetChild(0);
|
||||
toActivate.position += targetLocation.position - currentLocation.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70ae96e4f2feb654681a2f16e4effeec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04817e31b917de6489f349dd332d7468
|
||||
folderAsset: yes
|
||||
timeCreated: 1563295668
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: baf1d09e18b500d41a714f6207ddda2d
|
||||
folderAsset: yes
|
||||
timeCreated: 1536402197
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 511f90ee1fe01c146836d5ed23f2e70f
|
||||
folderAsset: yes
|
||||
timeCreated: 1564083752
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a7bd28c2cf2e41499693d9f8f9e2e1a
|
||||
folderAsset: yes
|
||||
timeCreated: 1573829102
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 329bda94bce571446a1a149b53ccf45c
|
||||
folderAsset: yes
|
||||
timeCreated: 1574096529
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b6fb48f295cd8248a7566315212a3c2
|
||||
folderAsset: yes
|
||||
timeCreated: 1494092464
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,522 +0,0 @@
|
||||
Shader "Hidden/Sprite-CameraDepthNormalsTexture" {
|
||||
|
||||
// Use this shader to render a DepthNormals texture for a camera with correct sprite normals (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _FixedNormal;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = getFixedNormal();
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
|
||||
float3 normal = getFixedNormal();
|
||||
//Only do this if backface is enabled :/
|
||||
normal *= calculateBackfacingSign(worldPos.xyz);
|
||||
//
|
||||
o.nz.xyz = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, normal));
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = -COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.nz.xyz = float3(0,0,1);
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return EncodeDepthNormal (i.nz.w, i.nz.xyz);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4794ea6b2d07cc546ba97a809b5f9ada
|
||||
timeCreated: 1494092583
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,518 +0,0 @@
|
||||
Shader "Hidden/Sprite-CameraDepthTexture" {
|
||||
|
||||
// Use this shader to render a Depth texture for a camera with soft edged Sprites (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
// Note the depth is encoded into the pixels RGB not the full RGBA (alpha is needed for blending)
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), alpha);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderMaths.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float depth : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.depth = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return fixed4(EncodeFloatRGB (i.depth), 1);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f768a57e040cc48489ad8c7392a31154
|
||||
timeCreated: 1494092586
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,522 +0,0 @@
|
||||
Shader "Hidden/Sprite-CameraNormalsTexture" {
|
||||
|
||||
// Use this shader to render a Normals texture for a camera with correct sprite normals (using camera.RenderWithShader with replacement tag "RenderType")
|
||||
|
||||
Properties {
|
||||
_MainTex ("", 2D) = "white" {}
|
||||
_Cutoff ("", Float) = 0.5
|
||||
_Color ("", Color) = (1,1,1,1)
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Sprite" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _FixedNormal;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteViewSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
o.nz.xyz = getFixedNormal();
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="SpriteModelSpaceFixedNormal" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "CGIncludes/ShaderShared.cginc"
|
||||
#include "CGIncludes/SpriteLighting.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = calculateTextureCoord(v.texcoord);
|
||||
float3 worldPos = mul(unity_ObjectToWorld, v.vertex);
|
||||
float3 normal = getFixedNormal();
|
||||
//Only do this if backface is enabled :/
|
||||
normal *= calculateBackfacingSign(worldPos.xyz);
|
||||
//
|
||||
o.nz.xyz = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, normal));
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = calculateTexturePixel(i.uv );
|
||||
float alpha = texcol.a*_Color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Opaque" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TransparentCutout" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
uniform float4 _MainTex_ST;
|
||||
v2f vert( appdata_base v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
uniform fixed4 _Color;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a*_Color.a - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBark" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertBark(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeLeaf" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "Lighting.cginc"
|
||||
#include "UnityBuiltin3xTreeLibrary.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert( appdata_full v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TreeVertLeaf(v);
|
||||
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag( v2f i ) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeOpaque" "DisableBatching"="True" }
|
||||
Pass {
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 nz : TEXCOORD0;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeTransparentCutout" "DisableBatching"="True" }
|
||||
Pass {
|
||||
Cull Back
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
half alpha = tex2D(_MainTex, i.uv).a;
|
||||
|
||||
clip (alpha - _Cutoff);
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
Pass {
|
||||
Cull Front
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
struct appdata {
|
||||
float4 vertex : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
fixed4 color : COLOR;
|
||||
float4 texcoord : TEXCOORD0;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
v2f vert( appdata v ) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainAnimateTree(v.vertex, v.color.w);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = -COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="TreeBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
v2f vert (appdata_tree_billboard v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
TerrainBillboardTree(v.vertex, v.texcoord1.xy, v.texcoord.y);
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv.x = v.texcoord.x;
|
||||
o.uv.y = v.texcoord.y > 0;
|
||||
o.nz.xyz = float3(0,0,1);
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
clip( texcol.a - 0.001 );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="GrassBillboard" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassBillboardVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord.xy;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
SubShader {
|
||||
Tags { "RenderType"="Grass" }
|
||||
Pass {
|
||||
Cull Off
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
#include "TerrainEngine.cginc"
|
||||
struct v2f {
|
||||
float4 pos : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 nz : TEXCOORD1;
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
};
|
||||
|
||||
v2f vert (appdata_full v) {
|
||||
v2f o;
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
WavingGrassVert (v);
|
||||
o.color = v.color;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
o.uv = v.texcoord;
|
||||
o.nz.xyz = COMPUTE_VIEW_NORMAL;
|
||||
o.nz.w = COMPUTE_DEPTH_01;
|
||||
return o;
|
||||
}
|
||||
uniform sampler2D _MainTex;
|
||||
uniform fixed _Cutoff;
|
||||
fixed4 frag(v2f i) : SV_Target {
|
||||
fixed4 texcol = tex2D( _MainTex, i.uv );
|
||||
fixed alpha = texcol.a * i.color.a;
|
||||
clip( alpha - _Cutoff );
|
||||
return i.nz;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
|
||||
Fallback Off
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 537141eca02c6df4bb8b4f77567e9de2
|
||||
timeCreated: 1494092584
|
||||
licenseType: Free
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 16fbcfb5e341ff44bb99593fff04539d
|
||||
folderAsset: yes
|
||||
timeCreated: 1563298958
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,129 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using Spine;
|
||||
using Spine.Unity;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[CreateAssetMenu(menuName = "Spine/SkeletonData Modifiers/Blend Mode Materials", order = 200)]
|
||||
public class BlendModeMaterialsAsset : SkeletonDataModifierAsset {
|
||||
public Material multiplyMaterialTemplate;
|
||||
public Material screenMaterialTemplate;
|
||||
public Material additiveMaterialTemplate;
|
||||
|
||||
public bool applyAdditiveMaterial = true;
|
||||
|
||||
public override void Apply (SkeletonData skeletonData) {
|
||||
ApplyMaterials(skeletonData, multiplyMaterialTemplate, screenMaterialTemplate, additiveMaterialTemplate, applyAdditiveMaterial);
|
||||
}
|
||||
|
||||
public static void ApplyMaterials (SkeletonData skeletonData, Material multiplyTemplate, Material screenTemplate, Material additiveTemplate, bool includeAdditiveSlots) {
|
||||
if (skeletonData == null) throw new ArgumentNullException("skeletonData");
|
||||
|
||||
using (var materialCache = new AtlasMaterialCache()) {
|
||||
var entryBuffer = new List<Skin.SkinEntry>();
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.blendMode == BlendMode.Normal) continue;
|
||||
if (!includeAdditiveSlots && slot.blendMode == BlendMode.Additive) continue;
|
||||
|
||||
entryBuffer.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, entryBuffer);
|
||||
|
||||
Material templateMaterial = null;
|
||||
switch (slot.blendMode) {
|
||||
case BlendMode.Multiply:
|
||||
templateMaterial = multiplyTemplate;
|
||||
break;
|
||||
case BlendMode.Screen:
|
||||
templateMaterial = screenTemplate;
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
templateMaterial = additiveTemplate;
|
||||
break;
|
||||
}
|
||||
if (templateMaterial == null) continue;
|
||||
|
||||
foreach (var entry in entryBuffer) {
|
||||
var renderableAttachment = entry.Attachment as IHasRendererObject;
|
||||
if (renderableAttachment != null) {
|
||||
renderableAttachment.RendererObject = materialCache.CloneAtlasRegionWithMaterial((AtlasRegion)renderableAttachment.RendererObject, templateMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//attachmentBuffer.Clear();
|
||||
}
|
||||
|
||||
class AtlasMaterialCache : IDisposable {
|
||||
readonly Dictionary<KeyValuePair<AtlasPage, Material>, AtlasPage> cache = new Dictionary<KeyValuePair<AtlasPage, Material>, AtlasPage>();
|
||||
|
||||
/// <summary>Creates a clone of an AtlasRegion that uses different Material settings, while retaining the original texture.</summary>
|
||||
public AtlasRegion CloneAtlasRegionWithMaterial (AtlasRegion originalRegion, Material materialTemplate) {
|
||||
var newRegion = originalRegion.Clone();
|
||||
newRegion.page = GetAtlasPageWithMaterial(originalRegion.page, materialTemplate);
|
||||
return newRegion;
|
||||
}
|
||||
|
||||
AtlasPage GetAtlasPageWithMaterial (AtlasPage originalPage, Material materialTemplate) {
|
||||
if (originalPage == null) throw new ArgumentNullException("originalPage");
|
||||
|
||||
AtlasPage newPage = null;
|
||||
var key = new KeyValuePair<AtlasPage, Material>(originalPage, materialTemplate);
|
||||
cache.TryGetValue(key, out newPage);
|
||||
|
||||
if (newPage == null) {
|
||||
newPage = originalPage.Clone();
|
||||
var originalMaterial = originalPage.rendererObject as Material;
|
||||
newPage.rendererObject = new Material(materialTemplate) {
|
||||
name = originalMaterial.name + " " + materialTemplate.name,
|
||||
mainTexture = originalMaterial.mainTexture
|
||||
};
|
||||
cache.Add(key, newPage);
|
||||
}
|
||||
|
||||
return newPage;
|
||||
}
|
||||
|
||||
public void Dispose () {
|
||||
cache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12b0b98acbcda44468a7ae4e35000abe
|
||||
timeCreated: 1536404384
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- multiplyMaterialTemplate: {fileID: 2100000, guid: 53bf0ab317d032d418cf1252d68f51df,
|
||||
type: 2}
|
||||
- screenMaterialTemplate: {fileID: 2100000, guid: 73f0f46d3177c614baf0fa48d646a9be,
|
||||
type: 2}
|
||||
- additiveMaterialTemplate: {fileID: 2100000, guid: 4deba332d47209e4780b3c5fcf0e3745,
|
||||
type: 2}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,20 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 12b0b98acbcda44468a7ae4e35000abe, type: 3}
|
||||
m_Name: Default BlendModeMaterials
|
||||
m_EditorClassIdentifier:
|
||||
multiplyMaterialTemplate: {fileID: 2100000, guid: 53bf0ab317d032d418cf1252d68f51df,
|
||||
type: 2}
|
||||
screenMaterialTemplate: {fileID: 2100000, guid: 73f0f46d3177c614baf0fa48d646a9be,
|
||||
type: 2}
|
||||
additiveMaterialTemplate: {fileID: 2100000, guid: 4deba332d47209e4780b3c5fcf0e3745,
|
||||
type: 2}
|
||||
applyAdditiveMaterial: 1
|
||||
@@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22c0225612a65ee4fb15bad49f644762
|
||||
timeCreated: 1536404361
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,808 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define CONFIGURABLE_ENTER_PLAY_MODE
|
||||
#endif
|
||||
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
|
||||
namespace Spine.Unity.AttachmentTools {
|
||||
|
||||
public static class AtlasUtilities {
|
||||
internal const TextureFormat SpineTextureFormat = TextureFormat.RGBA32;
|
||||
internal const float DefaultMipmapBias = -0.5f;
|
||||
internal const bool UseMipMaps = false;
|
||||
internal const float DefaultScale = 0.01f;
|
||||
|
||||
const int NonrenderingRegion = -1;
|
||||
|
||||
#if CONFIGURABLE_ENTER_PLAY_MODE
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
static void Init () {
|
||||
// handle disabled domain reload
|
||||
AtlasUtilities.ClearCache();
|
||||
}
|
||||
#endif
|
||||
|
||||
public static AtlasRegion ToAtlasRegion (this Texture2D t, Material materialPropertySource, float scale = DefaultScale) {
|
||||
return t.ToAtlasRegion(materialPropertySource.shader, scale, materialPropertySource);
|
||||
}
|
||||
|
||||
public static AtlasRegion ToAtlasRegion (this Texture2D t, Shader shader, float scale = DefaultScale, Material materialPropertySource = null) {
|
||||
var material = new Material(shader);
|
||||
if (materialPropertySource != null) {
|
||||
material.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
material.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
|
||||
material.mainTexture = t;
|
||||
var page = material.ToSpineAtlasPage();
|
||||
|
||||
float width = t.width;
|
||||
float height = t.height;
|
||||
|
||||
var region = new AtlasRegion();
|
||||
region.name = t.name;
|
||||
region.index = -1;
|
||||
region.rotate = false;
|
||||
|
||||
// World space units
|
||||
Vector2 boundsMin = Vector2.zero, boundsMax = new Vector2(width, height) * scale;
|
||||
|
||||
// Texture space/pixel units
|
||||
region.width = (int)width;
|
||||
region.originalWidth = (int)width;
|
||||
region.height = (int)height;
|
||||
region.originalHeight = (int)height;
|
||||
region.offsetX = width * (0.5f - InverseLerp(boundsMin.x, boundsMax.x, 0));
|
||||
region.offsetY = height * (0.5f - InverseLerp(boundsMin.y, boundsMax.y, 0));
|
||||
|
||||
// Use the full area of the texture.
|
||||
region.u = 0;
|
||||
region.v = 1;
|
||||
region.u2 = 1;
|
||||
region.v2 = 0;
|
||||
region.x = 0;
|
||||
region.y = 0;
|
||||
|
||||
region.page = page;
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate of the Sprite's texture data.</summary>
|
||||
public static AtlasRegion ToAtlasRegionPMAClone (this Texture2D t, Material materialPropertySource, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps) {
|
||||
return t.ToAtlasRegionPMAClone(materialPropertySource.shader, textureFormat, mipmaps, materialPropertySource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate of the Sprite's texture data.</summary>
|
||||
public static AtlasRegion ToAtlasRegionPMAClone (this Texture2D t, Shader shader, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, Material materialPropertySource = null) {
|
||||
var material = new Material(shader);
|
||||
if (materialPropertySource != null) {
|
||||
material.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
material.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
var newTexture = t.GetClone(textureFormat, mipmaps, applyPMA : true);
|
||||
|
||||
newTexture.name = t.name + "-pma-";
|
||||
material.name = t.name + shader.name;
|
||||
|
||||
material.mainTexture = newTexture;
|
||||
var page = material.ToSpineAtlasPage();
|
||||
|
||||
var region = newTexture.ToAtlasRegion(shader);
|
||||
region.page = page;
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Spine.AtlasPage from a UnityEngine.Material. If the material has a preassigned texture, the page width and height will be set.</summary>
|
||||
public static AtlasPage ToSpineAtlasPage (this Material m) {
|
||||
var newPage = new AtlasPage {
|
||||
rendererObject = m,
|
||||
name = m.name
|
||||
};
|
||||
|
||||
var t = m.mainTexture;
|
||||
if (t != null) {
|
||||
newPage.width = t.width;
|
||||
newPage.height = t.height;
|
||||
}
|
||||
|
||||
return newPage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion from a UnityEngine.Sprite.</summary>
|
||||
public static AtlasRegion ToAtlasRegion (this Sprite s, AtlasPage page) {
|
||||
if (page == null) throw new System.ArgumentNullException("page", "page cannot be null. AtlasPage determines which texture region belongs and how it should be rendered. You can use material.ToSpineAtlasPage() to get a shareable AtlasPage from a Material, or use the sprite.ToAtlasRegion(material) overload.");
|
||||
var region = s.ToAtlasRegion();
|
||||
region.page = page;
|
||||
return region;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion from a UnityEngine.Sprite. This creates a new AtlasPage object for every AtlasRegion you create. You can centralize Material control by creating a shared atlas page using Material.ToSpineAtlasPage and using the sprite.ToAtlasRegion(AtlasPage) overload.</summary>
|
||||
public static AtlasRegion ToAtlasRegion (this Sprite s, Material material) {
|
||||
var region = s.ToAtlasRegion();
|
||||
region.page = material.ToSpineAtlasPage();
|
||||
return region;
|
||||
}
|
||||
|
||||
public static AtlasRegion ToAtlasRegionPMAClone (this Sprite s, Material materialPropertySource, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps) {
|
||||
return s.ToAtlasRegionPMAClone(materialPropertySource.shader, textureFormat, mipmaps, materialPropertySource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate of the Sprite's texture data.</summary>
|
||||
public static AtlasRegion ToAtlasRegionPMAClone (this Sprite s, Shader shader, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, Material materialPropertySource = null) {
|
||||
var material = new Material(shader);
|
||||
if (materialPropertySource != null) {
|
||||
material.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
material.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
|
||||
var tex = s.ToTexture(textureFormat, mipmaps, applyPMA : true);
|
||||
tex.name = s.name + "-pma-";
|
||||
material.name = tex.name + shader.name;
|
||||
|
||||
material.mainTexture = tex;
|
||||
var page = material.ToSpineAtlasPage();
|
||||
|
||||
var region = s.ToAtlasRegion(true);
|
||||
region.page = page;
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
internal static AtlasRegion ToAtlasRegion (this Sprite s, bool isolatedTexture = false) {
|
||||
var region = new AtlasRegion();
|
||||
region.name = s.name;
|
||||
region.index = -1;
|
||||
region.rotate = s.packed && s.packingRotation != SpritePackingRotation.None;
|
||||
|
||||
// World space units
|
||||
Bounds bounds = s.bounds;
|
||||
Vector2 boundsMin = bounds.min, boundsMax = bounds.max;
|
||||
|
||||
// Texture space/pixel units
|
||||
Rect spineRect = s.rect.SpineUnityFlipRect(s.texture.height);
|
||||
region.width = (int)spineRect.width;
|
||||
region.originalWidth = (int)spineRect.width;
|
||||
region.height = (int)spineRect.height;
|
||||
region.originalHeight = (int)spineRect.height;
|
||||
region.offsetX = spineRect.width * (0.5f - InverseLerp(boundsMin.x, boundsMax.x, 0));
|
||||
region.offsetY = spineRect.height * (0.5f - InverseLerp(boundsMin.y, boundsMax.y, 0));
|
||||
|
||||
if (isolatedTexture) {
|
||||
region.u = 0;
|
||||
region.v = 1;
|
||||
region.u2 = 1;
|
||||
region.v2 = 0;
|
||||
region.x = 0;
|
||||
region.y = 0;
|
||||
} else {
|
||||
Texture2D tex = s.texture;
|
||||
Rect uvRect = TextureRectToUVRect(s.textureRect, tex.width, tex.height);
|
||||
region.u = uvRect.xMin;
|
||||
region.v = uvRect.yMax;
|
||||
region.u2 = uvRect.xMax;
|
||||
region.v2 = uvRect.yMin;
|
||||
region.x = (int)spineRect.x;
|
||||
region.y = (int)spineRect.y;
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
#region Runtime Repacking
|
||||
static readonly Dictionary<AtlasRegion, int> existingRegions = new Dictionary<AtlasRegion, int>();
|
||||
static readonly List<int> regionIndices = new List<int>();
|
||||
static readonly List<Texture2D> texturesToPack = new List<Texture2D>();
|
||||
static readonly List<AtlasRegion> originalRegions = new List<AtlasRegion>();
|
||||
static readonly List<AtlasRegion> repackedRegions = new List<AtlasRegion>();
|
||||
static readonly List<Attachment> repackedAttachments = new List<Attachment>();
|
||||
static List<Texture2D>[] texturesToPackAtParam = new List<Texture2D>[1];
|
||||
|
||||
/// <summary>
|
||||
/// Fills the outputAttachments list with new attachment objects based on the attachments in sourceAttachments,
|
||||
/// but mapped to a new single texture using the same material.</summary>
|
||||
/// <remarks>Returned <c>Material</c> and <c>Texture</c> behave like <c>new Texture2D()</c>, thus you need to call <c>Destroy()</c>
|
||||
/// to free resources.
|
||||
/// This method caches necessary Texture copies for later re-use, which might steadily increase the texture memory
|
||||
/// footprint when used excessively. Set <paramref name="clearCache"/> to <c>true</c>
|
||||
/// or call <see cref="AtlasUtilities.ClearCache()"/> to clear this texture cache.
|
||||
/// You may want to call <c>Resources.UnloadUnusedAssets()</c> after that.
|
||||
/// </remarks>
|
||||
/// <param name="sourceAttachments">The list of attachments to be repacked.</param>
|
||||
/// <param name = "outputAttachments">The List(Attachment) to populate with the newly created Attachment objects.</param>
|
||||
/// <param name="materialPropertySource">May be null. If no Material property source is provided, no special </param>
|
||||
/// <param name="clearCache">When set to <c>true</c>, <see cref="AtlasUtilities.ClearCache()"/> is called after
|
||||
/// repacking to clear the texture cache. See remarks for additional info.</param>
|
||||
public static void GetRepackedAttachments (List<Attachment> sourceAttachments, List<Attachment> outputAttachments, Material materialPropertySource, out Material outputMaterial, out Texture2D outputTexture, int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps, string newAssetName = "Repacked Attachments", bool clearCache = false, bool useOriginalNonrenderables = true) {
|
||||
if (sourceAttachments == null) throw new System.ArgumentNullException("sourceAttachments");
|
||||
if (outputAttachments == null) throw new System.ArgumentNullException("outputAttachments");
|
||||
|
||||
// Use shared lists to detect and use shared regions.
|
||||
existingRegions.Clear();
|
||||
regionIndices.Clear();
|
||||
texturesToPack.Clear();
|
||||
originalRegions.Clear();
|
||||
|
||||
outputAttachments.Clear();
|
||||
outputAttachments.AddRange(sourceAttachments);
|
||||
|
||||
int newRegionIndex = 0;
|
||||
for (int i = 0, n = sourceAttachments.Count; i < n; i++) {
|
||||
var originalAttachment = sourceAttachments[i];
|
||||
|
||||
if (IsRenderable(originalAttachment)) {
|
||||
var newAttachment = originalAttachment.GetCopy(true);
|
||||
var region = newAttachment.GetRegion();
|
||||
int existingIndex;
|
||||
if (existingRegions.TryGetValue(region, out existingIndex)) {
|
||||
regionIndices.Add(existingIndex); // Store the region index for the eventual new attachment.
|
||||
} else {
|
||||
originalRegions.Add(region);
|
||||
texturesToPack.Add(region.ToTexture(textureFormat, mipmaps)); // Add the texture to the PackTextures argument
|
||||
existingRegions.Add(region, newRegionIndex); // Add the region to the dictionary of known regions
|
||||
regionIndices.Add(newRegionIndex); // Store the region index for the eventual new attachment.
|
||||
newRegionIndex++;
|
||||
}
|
||||
|
||||
outputAttachments[i] = newAttachment;
|
||||
} else {
|
||||
outputAttachments[i] = useOriginalNonrenderables ? originalAttachment : originalAttachment.GetCopy(true);
|
||||
regionIndices.Add(NonrenderingRegion); // Output attachments pairs with regionIndexes list 1:1. Pad with a sentinel if the attachment doesn't have a region.
|
||||
}
|
||||
}
|
||||
|
||||
// Fill a new texture with the collected attachment textures.
|
||||
var newTexture = new Texture2D(maxAtlasSize, maxAtlasSize, textureFormat, mipmaps);
|
||||
newTexture.mipMapBias = AtlasUtilities.DefaultMipmapBias;
|
||||
newTexture.name = newAssetName;
|
||||
// Copy settings
|
||||
if (texturesToPack.Count > 0) {
|
||||
var sourceTexture = texturesToPack[0];
|
||||
newTexture.CopyTextureAttributesFrom(sourceTexture);
|
||||
}
|
||||
var rects = newTexture.PackTextures(texturesToPack.ToArray(), padding, maxAtlasSize);
|
||||
|
||||
// Rehydrate the repacked textures as a Material, Spine atlas and Spine.AtlasAttachments
|
||||
Shader shader = materialPropertySource == null ? Shader.Find("Spine/Skeleton") : materialPropertySource.shader;
|
||||
var newMaterial = new Material(shader);
|
||||
if (materialPropertySource != null) {
|
||||
newMaterial.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
newMaterial.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
|
||||
newMaterial.name = newAssetName;
|
||||
newMaterial.mainTexture = newTexture;
|
||||
var page = newMaterial.ToSpineAtlasPage();
|
||||
page.name = newAssetName;
|
||||
|
||||
repackedRegions.Clear();
|
||||
for (int i = 0, n = originalRegions.Count; i < n; i++) {
|
||||
var oldRegion = originalRegions[i];
|
||||
var newRegion = UVRectToAtlasRegion(rects[i], oldRegion, page);
|
||||
repackedRegions.Add(newRegion);
|
||||
}
|
||||
|
||||
// Map the cloned attachments to the repacked atlas.
|
||||
for (int i = 0, n = outputAttachments.Count; i < n; i++) {
|
||||
var a = outputAttachments[i];
|
||||
if (IsRenderable(a))
|
||||
a.SetRegion(repackedRegions[regionIndices[i]]);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
if (clearCache)
|
||||
AtlasUtilities.ClearCache();
|
||||
|
||||
outputTexture = newTexture;
|
||||
outputMaterial = newMaterial;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a duplicate skin with cloned attachments that are backed by a new packed texture atlas
|
||||
/// comprised of all the regions from the original skin.</summary>
|
||||
/// <remarks>GetRepackedSkin is an expensive operation, preferably call it at level load time.
|
||||
/// No Spine.Atlas object is created so there is no way to find AtlasRegions except through the Attachments using them.
|
||||
/// Returned <c>Material</c> and <c>Texture</c> behave like <c>new Texture2D()</c>, thus you need to call <c>Destroy()</c>
|
||||
/// to free resources.
|
||||
/// This method caches necessary Texture copies for later re-use, which might steadily increase the texture memory
|
||||
/// footprint when used excessively. Set <paramref name="clearCache"/> to <c>true</c>
|
||||
/// or call <see cref="AtlasUtilities.ClearCache()"/> to clear this texture cache.
|
||||
/// You may want to call <c>Resources.UnloadUnusedAssets()</c> after that.
|
||||
/// </remarks>
|
||||
/// <param name="clearCache">When set to <c>true</c>, <see cref="AtlasUtilities.ClearCache()"/> is called after
|
||||
/// repacking to clear the texture cache. See remarks for additional info.</param>
|
||||
/// <param name="additionalTexturePropertyIDsToCopy">Optional additional textures (such as normal maps) to copy while repacking.
|
||||
/// To copy e.g. the main texture and normal maps, pass 'new int[] { Shader.PropertyToID("_BumpMap") }' at this parameter.</param>
|
||||
/// <param name="additionalOutputTextures">When <c>additionalTexturePropertyIDsToCopy</c> is non-null,
|
||||
/// this array will be filled with the resulting repacked texture for every property,
|
||||
/// just as the main repacked texture is assigned to <c>outputTexture</c>.</param>
|
||||
/// <param name="additionalTextureFormats">When <c>additionalTexturePropertyIDsToCopy</c> is non-null,
|
||||
/// this array will be used as <c>TextureFormat</c> at the Texture at the respective property.
|
||||
/// When <c>additionalTextureFormats</c> is <c>null</c> or when its array size is smaller,
|
||||
/// <c>textureFormat</c> is used where there exists no corresponding array item.</param>
|
||||
/// <param name="additionalTextureIsLinear">When <c>additionalTexturePropertyIDsToCopy</c> is non-null,
|
||||
/// this array will be used to determine whether <c>linear</c> or <c>sRGB</c> color space is used at the
|
||||
/// Texture at the respective property. When <c>additionalTextureIsLinear</c> is <c>null</c>, <c>linear</c> color space
|
||||
/// is assumed at every additional Texture element.
|
||||
/// When e.g. packing the main texture and normal maps, pass 'new bool[] { true }' at this parameter, because normal maps use
|
||||
/// linear color space.</param>
|
||||
public static Skin GetRepackedSkin (this Skin o, string newName, Material materialPropertySource, out Material outputMaterial, out Texture2D outputTexture,
|
||||
int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps,
|
||||
bool useOriginalNonrenderables = true, bool clearCache = false,
|
||||
int[] additionalTexturePropertyIDsToCopy = null, Texture2D[] additionalOutputTextures = null,
|
||||
TextureFormat[] additionalTextureFormats = null, bool[] additionalTextureIsLinear = null) {
|
||||
|
||||
return GetRepackedSkin(o, newName, materialPropertySource.shader, out outputMaterial, out outputTexture,
|
||||
maxAtlasSize, padding, textureFormat, mipmaps, materialPropertySource,
|
||||
clearCache, useOriginalNonrenderables, additionalTexturePropertyIDsToCopy, additionalOutputTextures,
|
||||
additionalTextureFormats, additionalTextureIsLinear);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a duplicate skin with cloned attachments that are backed by a new packed texture atlas
|
||||
/// comprised of all the regions from the original skin.</summary>
|
||||
/// See documentation of <see cref="GetRepackedSkin"/> for details.
|
||||
public static Skin GetRepackedSkin (this Skin o, string newName, Shader shader, out Material outputMaterial, out Texture2D outputTexture,
|
||||
int maxAtlasSize = 1024, int padding = 2, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps,
|
||||
Material materialPropertySource = null, bool clearCache = false, bool useOriginalNonrenderables = true,
|
||||
int[] additionalTexturePropertyIDsToCopy = null, Texture2D[] additionalOutputTextures = null,
|
||||
TextureFormat[] additionalTextureFormats = null, bool[] additionalTextureIsLinear = null) {
|
||||
|
||||
outputTexture = null;
|
||||
if (additionalTexturePropertyIDsToCopy != null && additionalTextureIsLinear == null) {
|
||||
additionalTextureIsLinear = new bool[additionalTexturePropertyIDsToCopy.Length];
|
||||
for (int i = 0; i < additionalTextureIsLinear.Length; ++i) {
|
||||
additionalTextureIsLinear[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (o == null) throw new System.NullReferenceException("Skin was null");
|
||||
var skinAttachments = o.Attachments;
|
||||
var newSkin = new Skin(newName);
|
||||
|
||||
newSkin.bones.AddRange(o.bones);
|
||||
newSkin.constraints.AddRange(o.constraints);
|
||||
|
||||
// Use these to detect and use shared regions.
|
||||
existingRegions.Clear();
|
||||
regionIndices.Clear();
|
||||
|
||||
// Collect all textures from the attachments of the original skin.
|
||||
repackedAttachments.Clear();
|
||||
int numTextureParamsToRepack = 1 + (additionalTexturePropertyIDsToCopy == null ? 0 : additionalTexturePropertyIDsToCopy.Length);
|
||||
additionalOutputTextures = (additionalTexturePropertyIDsToCopy == null ? null : new Texture2D[additionalTexturePropertyIDsToCopy.Length]);
|
||||
if (texturesToPackAtParam.Length < numTextureParamsToRepack)
|
||||
Array.Resize(ref texturesToPackAtParam, numTextureParamsToRepack);
|
||||
for (int i = 0; i < numTextureParamsToRepack; ++i) {
|
||||
if (texturesToPackAtParam[i] != null)
|
||||
texturesToPackAtParam[i].Clear();
|
||||
else
|
||||
texturesToPackAtParam[i] = new List<Texture2D>();
|
||||
}
|
||||
originalRegions.Clear();
|
||||
int newRegionIndex = 0;
|
||||
|
||||
foreach (var skinEntry in skinAttachments) {
|
||||
var originalKey = skinEntry.Key;
|
||||
var originalAttachment = skinEntry.Value;
|
||||
|
||||
Attachment newAttachment;
|
||||
if (IsRenderable(originalAttachment)) {
|
||||
newAttachment = originalAttachment.GetCopy(true);
|
||||
var region = newAttachment.GetRegion();
|
||||
int existingIndex;
|
||||
if (existingRegions.TryGetValue(region, out existingIndex)) {
|
||||
regionIndices.Add(existingIndex); // Store the region index for the eventual new attachment.
|
||||
} else {
|
||||
originalRegions.Add(region);
|
||||
for (int i = 0; i < numTextureParamsToRepack; ++i) {
|
||||
Texture2D regionTexture = (i == 0 ?
|
||||
region.ToTexture(textureFormat, mipmaps) :
|
||||
region.ToTexture((additionalTextureFormats != null && i - 1 < additionalTextureFormats.Length) ?
|
||||
additionalTextureFormats[i - 1] : textureFormat,
|
||||
mipmaps, additionalTexturePropertyIDsToCopy[i - 1], additionalTextureIsLinear[i - 1]));
|
||||
texturesToPackAtParam[i].Add(regionTexture); // Add the texture to the PackTextures argument
|
||||
}
|
||||
existingRegions.Add(region, newRegionIndex); // Add the region to the dictionary of known regions
|
||||
regionIndices.Add(newRegionIndex); // Store the region index for the eventual new attachment.
|
||||
newRegionIndex++;
|
||||
}
|
||||
|
||||
repackedAttachments.Add(newAttachment);
|
||||
newSkin.SetAttachment(originalKey.SlotIndex, originalKey.Name, newAttachment);
|
||||
} else {
|
||||
newSkin.SetAttachment(originalKey.SlotIndex, originalKey.Name, useOriginalNonrenderables ? originalAttachment : originalAttachment.GetCopy(true));
|
||||
}
|
||||
}
|
||||
|
||||
// Rehydrate the repacked textures as a Material, Spine atlas and Spine.AtlasAttachments
|
||||
var newMaterial = new Material(shader);
|
||||
if (materialPropertySource != null) {
|
||||
newMaterial.CopyPropertiesFromMaterial(materialPropertySource);
|
||||
newMaterial.shaderKeywords = materialPropertySource.shaderKeywords;
|
||||
}
|
||||
newMaterial.name = newName;
|
||||
|
||||
Rect[] rects = null;
|
||||
for (int i = 0; i < numTextureParamsToRepack; ++i) {
|
||||
// Fill a new texture with the collected attachment textures.
|
||||
var newTexture = new Texture2D(maxAtlasSize, maxAtlasSize,
|
||||
(i > 0 && additionalTextureFormats != null && i - 1 < additionalTextureFormats.Length) ?
|
||||
additionalTextureFormats[i - 1] : textureFormat,
|
||||
mipmaps,
|
||||
(i > 0) ? additionalTextureIsLinear[i - 1] : false);
|
||||
newTexture.mipMapBias = AtlasUtilities.DefaultMipmapBias;
|
||||
var texturesToPack = texturesToPackAtParam[i];
|
||||
if (texturesToPack.Count > 0) {
|
||||
var sourceTexture = texturesToPack[0];
|
||||
newTexture.CopyTextureAttributesFrom(sourceTexture);
|
||||
}
|
||||
newTexture.name = newName;
|
||||
var rectsForTexParam = newTexture.PackTextures(texturesToPack.ToArray(), padding, maxAtlasSize);
|
||||
if (i == 0) {
|
||||
rects = rectsForTexParam;
|
||||
newMaterial.mainTexture = newTexture;
|
||||
outputTexture = newTexture;
|
||||
}
|
||||
else {
|
||||
newMaterial.SetTexture(additionalTexturePropertyIDsToCopy[i - 1], newTexture);
|
||||
additionalOutputTextures[i - 1] = newTexture;
|
||||
}
|
||||
}
|
||||
|
||||
var page = newMaterial.ToSpineAtlasPage();
|
||||
page.name = newName;
|
||||
|
||||
repackedRegions.Clear();
|
||||
for (int i = 0, n = originalRegions.Count; i < n; i++) {
|
||||
var oldRegion = originalRegions[i];
|
||||
var newRegion = UVRectToAtlasRegion(rects[i], oldRegion, page);
|
||||
repackedRegions.Add(newRegion);
|
||||
}
|
||||
|
||||
// Map the cloned attachments to the repacked atlas.
|
||||
for (int i = 0, n = repackedAttachments.Count; i < n; i++) {
|
||||
var a = repackedAttachments[i];
|
||||
if (IsRenderable(a))
|
||||
a.SetRegion(repackedRegions[regionIndices[i]]);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
if (clearCache)
|
||||
AtlasUtilities.ClearCache();
|
||||
|
||||
outputMaterial = newMaterial;
|
||||
return newSkin;
|
||||
}
|
||||
|
||||
public static Sprite ToSprite (this AtlasRegion ar, float pixelsPerUnit = 100) {
|
||||
return Sprite.Create(ar.GetMainTexture(), ar.GetUnityRect(), new Vector2(0.5f, 0.5f), pixelsPerUnit);
|
||||
}
|
||||
|
||||
struct IntAndAtlasRegionKey {
|
||||
int i;
|
||||
AtlasRegion region;
|
||||
|
||||
public IntAndAtlasRegionKey(int i, AtlasRegion region) {
|
||||
this.i = i;
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public override int GetHashCode () {
|
||||
return i.GetHashCode() * 23 ^ region.GetHashCode();
|
||||
}
|
||||
}
|
||||
static Dictionary<IntAndAtlasRegionKey, Texture2D> CachedRegionTextures = new Dictionary<IntAndAtlasRegionKey, Texture2D>();
|
||||
static List<Texture2D> CachedRegionTexturesList = new List<Texture2D>();
|
||||
|
||||
/// <summary>
|
||||
/// Frees up textures cached by repacking and remapping operations.
|
||||
///
|
||||
/// Calling <see cref="AttachmentCloneExtensions.GetRemappedClone"/> with parameter <c>premultiplyAlpha=true</c>,
|
||||
/// <see cref="GetRepackedAttachments"/> or <see cref="GetRepackedSkin"/> will cache textures for later re-use,
|
||||
/// which might steadily increase the texture memory footprint when used excessively.
|
||||
/// You can clear this Texture cache by calling <see cref="AtlasUtilities.ClearCache()"/>.
|
||||
/// You may also want to call <c>Resources.UnloadUnusedAssets()</c> after that. Be aware that while this cleanup
|
||||
/// frees up memory, it is also a costly operation and will likely cause a spike in the framerate.
|
||||
/// Thus it is recommended to perform costly repacking and cleanup operations after e.g. a character customization
|
||||
/// screen has been exited, and if required additionally after a certain number of <c>GetRemappedClone()</c> calls.
|
||||
/// </summary>
|
||||
public static void ClearCache () {
|
||||
foreach (var t in CachedRegionTexturesList) {
|
||||
UnityEngine.Object.Destroy(t);
|
||||
}
|
||||
CachedRegionTextures.Clear();
|
||||
CachedRegionTexturesList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Creates a new Texture2D object based on an AtlasRegion.
|
||||
/// If applyImmediately is true, Texture2D.Apply is called immediately after the Texture2D is filled with data.</summary>
|
||||
public static Texture2D ToTexture (this AtlasRegion ar, TextureFormat textureFormat = SpineTextureFormat, bool mipmaps = UseMipMaps,
|
||||
int texturePropertyId = 0, bool linear = false, bool applyPMA = false) {
|
||||
|
||||
Texture2D output;
|
||||
|
||||
IntAndAtlasRegionKey cacheKey = new IntAndAtlasRegionKey(texturePropertyId, ar);
|
||||
CachedRegionTextures.TryGetValue(cacheKey, out output);
|
||||
if (output == null) {
|
||||
Texture2D sourceTexture = texturePropertyId == 0 ? ar.GetMainTexture() : ar.GetTexture(texturePropertyId);
|
||||
Rect r = ar.GetUnityRect();
|
||||
// Compensate any image resizing due to Texture 'Max Size' import settings.
|
||||
// sourceTexture.width returns the resized image dimensions, at least in newer Unity versions.
|
||||
if (sourceTexture.width < ar.page.width) {
|
||||
float scaleX = (float)(sourceTexture.width) / (float)(ar.page.width);
|
||||
float scaleY = (float)(sourceTexture.height) / (float)(ar.page.height);
|
||||
var scale = new Vector2(scaleX, scaleY);
|
||||
r = new Rect(Vector2.Scale(r.position, scale), Vector2.Scale(r.size, scale));
|
||||
}
|
||||
|
||||
int width = (int)r.width;
|
||||
int height = (int)r.height;
|
||||
output = new Texture2D(width, height, textureFormat, mipmaps, linear) { name = ar.name };
|
||||
output.CopyTextureAttributesFrom(sourceTexture);
|
||||
if (applyPMA)
|
||||
AtlasUtilities.CopyTextureApplyPMA(sourceTexture, r, output);
|
||||
else
|
||||
AtlasUtilities.CopyTexture(sourceTexture, r, output);
|
||||
CachedRegionTextures.Add(cacheKey, output);
|
||||
CachedRegionTexturesList.Add(output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static Texture2D ToTexture (this Sprite s, TextureFormat textureFormat = SpineTextureFormat,
|
||||
bool mipmaps = UseMipMaps, bool linear = false, bool applyPMA = false) {
|
||||
|
||||
var spriteTexture = s.texture;
|
||||
Rect r;
|
||||
if (!s.packed || s.packingMode == SpritePackingMode.Rectangle) {
|
||||
r = s.textureRect;
|
||||
}
|
||||
else {
|
||||
r = new Rect();
|
||||
r.xMin = Math.Min(s.uv[0].x, s.uv[1].x) * spriteTexture.width;
|
||||
r.xMax = Math.Max(s.uv[0].x, s.uv[1].x) * spriteTexture.width;
|
||||
r.yMin = Math.Min(s.uv[0].y, s.uv[2].y) * spriteTexture.height;
|
||||
r.yMax = Math.Max(s.uv[0].y, s.uv[2].y) * spriteTexture.height;
|
||||
#if UNITY_EDITOR
|
||||
if (s.uv.Length > 4) {
|
||||
Debug.LogError("When using a tightly packed SpriteAtlas with Spine, you may only access Sprites that are packed as 'FullRect' from it! " +
|
||||
"You can either disable 'Tight Packing' at the whole SpriteAtlas, or change the single Sprite's TextureImporter Setting 'MeshType' to 'Full Rect'." +
|
||||
"Sprite Asset: " + s.name, s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
var newTexture = new Texture2D((int)r.width, (int)r.height, textureFormat, mipmaps, linear);
|
||||
newTexture.CopyTextureAttributesFrom(spriteTexture);
|
||||
if (applyPMA)
|
||||
AtlasUtilities.CopyTextureApplyPMA(spriteTexture, r, newTexture);
|
||||
else
|
||||
AtlasUtilities.CopyTexture(spriteTexture, r, newTexture);
|
||||
return newTexture;
|
||||
}
|
||||
|
||||
static Texture2D GetClone (this Texture2D t, TextureFormat textureFormat = SpineTextureFormat,
|
||||
bool mipmaps = UseMipMaps, bool linear = false, bool applyPMA = false) {
|
||||
|
||||
var newTexture = new Texture2D((int)t.width, (int)t.height, textureFormat, mipmaps, linear);
|
||||
newTexture.CopyTextureAttributesFrom(t);
|
||||
if (applyPMA)
|
||||
AtlasUtilities.CopyTextureApplyPMA(t, new Rect(0, 0, t.width, t.height), newTexture);
|
||||
else
|
||||
AtlasUtilities.CopyTexture(t, new Rect(0, 0, t.width, t.height), newTexture);
|
||||
return newTexture;
|
||||
}
|
||||
|
||||
static void CopyTexture (Texture2D source, Rect sourceRect, Texture2D destination) {
|
||||
if (SystemInfo.copyTextureSupport == UnityEngine.Rendering.CopyTextureSupport.None) {
|
||||
// GetPixels fallback for old devices.
|
||||
Color[] pixelBuffer = source.GetPixels((int)sourceRect.x, (int)sourceRect.y, (int)sourceRect.width, (int)sourceRect.height);
|
||||
destination.SetPixels(pixelBuffer);
|
||||
destination.Apply();
|
||||
} else {
|
||||
Graphics.CopyTexture(source, 0, 0, (int)sourceRect.x, (int)sourceRect.y, (int)sourceRect.width, (int)sourceRect.height, destination, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyTextureApplyPMA (Texture2D source, Rect sourceRect, Texture2D destination) {
|
||||
Color[] pixelBuffer = source.GetPixels((int)sourceRect.x, (int)sourceRect.y, (int)sourceRect.width, (int)sourceRect.height);
|
||||
for (int i = 0, n = pixelBuffer.Length; i < n; i++) {
|
||||
Color p = pixelBuffer[i];
|
||||
float a = p.a;
|
||||
p.r = p.r * a;
|
||||
p.g = p.g * a;
|
||||
p.b = p.b * a;
|
||||
pixelBuffer[i] = p;
|
||||
}
|
||||
destination.SetPixels(pixelBuffer);
|
||||
destination.Apply();
|
||||
}
|
||||
|
||||
static bool IsRenderable (Attachment a) {
|
||||
return a is IHasRendererObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a rect with flipped Y so that a Spine atlas rect gets converted to a Unity Sprite rect and vice versa.</summary>
|
||||
static Rect SpineUnityFlipRect (this Rect rect, int textureHeight) {
|
||||
rect.y = textureHeight - rect.y - rect.height;
|
||||
return rect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rect of an AtlasRegion according to Unity texture coordinates (x-right, y-up).
|
||||
/// This overload relies on region.page.height being correctly set.</summary>
|
||||
static Rect GetUnityRect (this AtlasRegion region) {
|
||||
return region.GetSpineAtlasRect().SpineUnityFlipRect(region.page.height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Rect of an AtlasRegion according to Unity texture coordinates (x-right, y-up).</summary>
|
||||
static Rect GetUnityRect (this AtlasRegion region, int textureHeight) {
|
||||
return region.GetSpineAtlasRect().SpineUnityFlipRect(textureHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Rect of the AtlasRegion according to Spine texture coordinates. (x-right, y-down)</summary>
|
||||
static Rect GetSpineAtlasRect (this AtlasRegion region, bool includeRotate = true) {
|
||||
if (includeRotate && (region.degrees == 90 || region.degrees == 270))
|
||||
return new Rect(region.x, region.y, region.height, region.width);
|
||||
else
|
||||
return new Rect(region.x, region.y, region.width, region.height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Denormalize a uvRect into a texture-space Rect.</summary>
|
||||
static Rect UVRectToTextureRect (Rect uvRect, int texWidth, int texHeight) {
|
||||
uvRect.x *= texWidth;
|
||||
uvRect.width *= texWidth;
|
||||
uvRect.y *= texHeight;
|
||||
uvRect.height *= texHeight;
|
||||
return uvRect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize a texture Rect into UV coordinates.</summary>
|
||||
static Rect TextureRectToUVRect (Rect textureRect, int texWidth, int texHeight) {
|
||||
textureRect.x = Mathf.InverseLerp(0, texWidth, textureRect.x);
|
||||
textureRect.y = Mathf.InverseLerp(0, texHeight, textureRect.y);
|
||||
textureRect.width = Mathf.InverseLerp(0, texWidth, textureRect.width);
|
||||
textureRect.height = Mathf.InverseLerp(0, texHeight, textureRect.height);
|
||||
return textureRect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Spine AtlasRegion according to a Unity UV Rect (x-right, y-up, uv-normalized).</summary>
|
||||
static AtlasRegion UVRectToAtlasRegion (Rect uvRect, AtlasRegion referenceRegion, AtlasPage page) {
|
||||
var tr = UVRectToTextureRect(uvRect, page.width, page.height);
|
||||
var rr = tr.SpineUnityFlipRect(page.height);
|
||||
|
||||
int x = (int)rr.x, y = (int)rr.y;
|
||||
int w, h;
|
||||
if (referenceRegion.degrees == 90 || referenceRegion.degrees == 270) {
|
||||
w = (int)rr.height;
|
||||
h = (int)rr.width;
|
||||
} else {
|
||||
w = (int)rr.width;
|
||||
h = (int)rr.height;
|
||||
}
|
||||
|
||||
int originalW = Mathf.RoundToInt((float)w * ((float)referenceRegion.originalWidth / (float)referenceRegion.width));
|
||||
int originalH = Mathf.RoundToInt((float)h * ((float)referenceRegion.originalHeight / (float)referenceRegion.height));
|
||||
int offsetX = Mathf.RoundToInt((float)referenceRegion.offsetX * ((float)w / (float)referenceRegion.width));
|
||||
int offsetY = Mathf.RoundToInt((float)referenceRegion.offsetY * ((float)h / (float)referenceRegion.height));
|
||||
|
||||
if (referenceRegion.degrees == 270) {
|
||||
w = (int)rr.width;
|
||||
h = (int)rr.height;
|
||||
}
|
||||
|
||||
float u = uvRect.xMin;
|
||||
float u2 = uvRect.xMax;
|
||||
float v = uvRect.yMax;
|
||||
float v2 = uvRect.yMin;
|
||||
|
||||
return new AtlasRegion {
|
||||
page = page,
|
||||
name = referenceRegion.name,
|
||||
|
||||
u = u,
|
||||
u2 = u2,
|
||||
v = v,
|
||||
v2 = v2,
|
||||
|
||||
index = -1,
|
||||
|
||||
width = w,
|
||||
originalWidth = originalW,
|
||||
height = h,
|
||||
originalHeight = originalH,
|
||||
offsetX = offsetX,
|
||||
offsetY = offsetY,
|
||||
x = x,
|
||||
y = y,
|
||||
|
||||
rotate = referenceRegion.rotate,
|
||||
degrees = referenceRegion.degrees
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method for getting the main texture of the material of the page of the region.</summary>
|
||||
static Texture2D GetMainTexture (this AtlasRegion region) {
|
||||
var material = (region.page.rendererObject as Material);
|
||||
return material.mainTexture as Texture2D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method for getting any texture of the material of the page of the region by texture property name.</summary>
|
||||
static Texture2D GetTexture (this AtlasRegion region, string texturePropertyName) {
|
||||
var material = (region.page.rendererObject as Material);
|
||||
return material.GetTexture(texturePropertyName) as Texture2D;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method for getting any texture of the material of the page of the region by texture property id.</summary>
|
||||
static Texture2D GetTexture (this AtlasRegion region, int texturePropertyId) {
|
||||
var material = (region.page.rendererObject as Material);
|
||||
return material.GetTexture(texturePropertyId) as Texture2D;
|
||||
}
|
||||
|
||||
static void CopyTextureAttributesFrom(this Texture2D destination, Texture2D source) {
|
||||
destination.filterMode = source.filterMode;
|
||||
destination.anisoLevel = source.anisoLevel;
|
||||
#if UNITY_EDITOR
|
||||
destination.alphaIsTransparency = source.alphaIsTransparency;
|
||||
#endif
|
||||
destination.wrapModeU = source.wrapModeU;
|
||||
destination.wrapModeV = source.wrapModeV;
|
||||
destination.wrapModeW = source.wrapModeW;
|
||||
}
|
||||
#endregion
|
||||
|
||||
static float InverseLerp (float a, float b, float value) {
|
||||
return (value - a) / (b - a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25ceef568a3dad448bf8a14fcc326964
|
||||
timeCreated: 1563321428
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,147 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 {
|
||||
/// <summary>
|
||||
/// Clones the attachment.</summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// Returns a new linked mesh linked to this MeshAttachment. It will be mapped to the AtlasRegion provided.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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)</summary>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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)</summary>
|
||||
public static MeshAttachment GetLinkedMesh (this MeshAttachment o, Sprite sprite, Material materialPropertySource) {
|
||||
return o.GetLinkedMesh(sprite, materialPropertySource.shader, materialPropertySource);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemappedClone Convenience Methods
|
||||
/// <summary>
|
||||
/// Gets a clone of the attachment remapped with a sprite image.</summary>
|
||||
/// <returns>The remapped clone.</returns>
|
||||
/// <param name="o">The original attachment.</param>
|
||||
/// <param name="sprite">The sprite whose texture to use.</param>
|
||||
/// <param name="sourceMaterial">The source material used to copy the shader and material properties from.</param>
|
||||
/// <param name="premultiplyAlpha">If <c>true</c>, a premultiply alpha clone of the original texture will be created.
|
||||
/// See remarks below for additional info.</param>
|
||||
/// <param name="cloneMeshAsLinked">If <c>true</c> MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment.</param>
|
||||
/// <param name="useOriginalRegionSize">If <c>true</c> the size of the original attachment will be followed, instead of using the Sprite size.</param>
|
||||
/// <param name="pivotShiftsMeshUVCoords">If <c>true</c> 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.</param>
|
||||
/// <param name="useOriginalRegionScale">If <c>true</c> 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.</param>
|
||||
/// <remarks>When parameter <c>premultiplyAlpha</c> is set to <c>true</c>, 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 <see cref="AtlasUtilities.ClearCache()"/> on how to clear these cached textures.</remarks>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a clone of the attachment remapped with an atlasRegion image.</summary>
|
||||
/// <returns>The remapped clone.</returns>
|
||||
/// <param name="o">The original attachment.</param>
|
||||
/// <param name="atlasRegion">Atlas region.</param>
|
||||
/// <param name="cloneMeshAsLinked">If <c>true</c> MeshAttachments will be cloned as linked meshes and will inherit animation from the original attachment.</param>
|
||||
/// <param name="useOriginalRegionSize">If <c>true</c> the size of the original attachment will be followed, instead of using the Sprite size.</param>
|
||||
/// <param name="scale">Unity units per pixel scale used to scale the atlas region size when not using the original region size.</param>
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3431ed563b2c62f4c8c974a99365ba52
|
||||
timeCreated: 1563321428
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,211 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 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 AttachmentRegionExtensions {
|
||||
#region GetRegion
|
||||
/// <summary>
|
||||
/// Tries to get the region (image) of a renderable attachment. If the attachment is not renderable, it returns null.</summary>
|
||||
public static AtlasRegion GetRegion (this Attachment attachment) {
|
||||
var renderableAttachment = attachment as IHasRendererObject;
|
||||
if (renderableAttachment != null)
|
||||
return renderableAttachment.RendererObject as AtlasRegion;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Gets the region (image) of a RegionAttachment</summary>
|
||||
public static AtlasRegion GetRegion (this RegionAttachment regionAttachment) {
|
||||
return regionAttachment.RendererObject as AtlasRegion;
|
||||
}
|
||||
|
||||
/// <summary>Gets the region (image) of a MeshAttachment</summary>
|
||||
public static AtlasRegion GetRegion (this MeshAttachment meshAttachment) {
|
||||
return meshAttachment.RendererObject as AtlasRegion;
|
||||
}
|
||||
#endregion
|
||||
#region SetRegion
|
||||
/// <summary>
|
||||
/// Tries to set the region (image) of a renderable attachment. If the attachment is not renderable, nothing is applied.</summary>
|
||||
public static void SetRegion (this Attachment attachment, AtlasRegion region, bool updateOffset = true) {
|
||||
var regionAttachment = attachment as RegionAttachment;
|
||||
if (regionAttachment != null)
|
||||
regionAttachment.SetRegion(region, updateOffset);
|
||||
|
||||
var meshAttachment = attachment as MeshAttachment;
|
||||
if (meshAttachment != null)
|
||||
meshAttachment.SetRegion(region, updateOffset);
|
||||
}
|
||||
|
||||
/// <summary>Sets the region (image) of a RegionAttachment</summary>
|
||||
public static void SetRegion (this RegionAttachment attachment, AtlasRegion region, bool updateOffset = true) {
|
||||
if (region == null) throw new System.ArgumentNullException("region");
|
||||
|
||||
// (AtlasAttachmentLoader.cs)
|
||||
attachment.RendererObject = region;
|
||||
attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
|
||||
attachment.regionOffsetX = region.offsetX;
|
||||
attachment.regionOffsetY = region.offsetY;
|
||||
attachment.regionWidth = region.width;
|
||||
attachment.regionHeight = region.height;
|
||||
attachment.regionOriginalWidth = region.originalWidth;
|
||||
attachment.regionOriginalHeight = region.originalHeight;
|
||||
|
||||
if (updateOffset) attachment.UpdateOffset();
|
||||
}
|
||||
|
||||
/// <summary>Sets the region (image) of a MeshAttachment</summary>
|
||||
public static void SetRegion (this MeshAttachment attachment, AtlasRegion region, bool updateUVs = true) {
|
||||
if (region == null) throw new System.ArgumentNullException("region");
|
||||
|
||||
// (AtlasAttachmentLoader.cs)
|
||||
attachment.RendererObject = region;
|
||||
attachment.RegionU = region.u;
|
||||
attachment.RegionV = region.v;
|
||||
attachment.RegionU2 = region.u2;
|
||||
attachment.RegionV2 = region.v2;
|
||||
attachment.RegionRotate = region.rotate;
|
||||
attachment.RegionDegrees = region.degrees;
|
||||
attachment.regionOffsetX = region.offsetX;
|
||||
attachment.regionOffsetY = region.offsetY;
|
||||
attachment.regionWidth = region.width;
|
||||
attachment.regionHeight = region.height;
|
||||
attachment.regionOriginalWidth = region.originalWidth;
|
||||
attachment.regionOriginalHeight = region.originalHeight;
|
||||
|
||||
if (updateUVs) attachment.UpdateUVs();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Runtime RegionAttachments
|
||||
/// <summary>
|
||||
/// Creates a RegionAttachment based on a sprite. This method creates a real, usable AtlasRegion. That AtlasRegion uses a new AtlasPage with the Material provided./// </summary>
|
||||
public static RegionAttachment ToRegionAttachment (this Sprite sprite, Material material, float rotation = 0f) {
|
||||
return sprite.ToRegionAttachment(material.ToSpineAtlasPage(), rotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a RegionAttachment based on a sprite. This method creates a real, usable AtlasRegion. That AtlasRegion uses the AtlasPage provided./// </summary>
|
||||
public static RegionAttachment ToRegionAttachment (this Sprite sprite, AtlasPage page, float rotation = 0f) {
|
||||
if (sprite == null) throw new System.ArgumentNullException("sprite");
|
||||
if (page == null) throw new System.ArgumentNullException("page");
|
||||
var region = sprite.ToAtlasRegion(page);
|
||||
var unitsPerPixel = 1f / sprite.pixelsPerUnit;
|
||||
return region.ToRegionAttachment(sprite.name, unitsPerPixel, rotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Spine.AtlasRegion that uses a premultiplied alpha duplicate texture of the Sprite's texture data.
|
||||
/// Returns a RegionAttachment that uses it. Use this if you plan to use a premultiply alpha shader such as "Spine/Skeleton".</summary>
|
||||
/// <remarks>The duplicate texture is cached for later re-use. See documentation of
|
||||
/// <see cref="AttachmentCloneExtensions.GetRemappedClone"/> for additional details.</remarks>
|
||||
public static RegionAttachment ToRegionAttachmentPMAClone (this Sprite sprite, Shader shader, TextureFormat textureFormat = AtlasUtilities.SpineTextureFormat, bool mipmaps = AtlasUtilities.UseMipMaps, Material materialPropertySource = null, float rotation = 0f) {
|
||||
if (sprite == null) throw new System.ArgumentNullException("sprite");
|
||||
if (shader == null) throw new System.ArgumentNullException("shader");
|
||||
var region = sprite.ToAtlasRegionPMAClone(shader, textureFormat, mipmaps, materialPropertySource);
|
||||
var unitsPerPixel = 1f / sprite.pixelsPerUnit;
|
||||
return region.ToRegionAttachment(sprite.name, unitsPerPixel, rotation);
|
||||
}
|
||||
|
||||
public static RegionAttachment ToRegionAttachmentPMAClone (this Sprite sprite, Material materialPropertySource, TextureFormat textureFormat = AtlasUtilities.SpineTextureFormat, bool mipmaps = AtlasUtilities.UseMipMaps, float rotation = 0f) {
|
||||
return sprite.ToRegionAttachmentPMAClone(materialPropertySource.shader, textureFormat, mipmaps, materialPropertySource, rotation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new RegionAttachment from a given AtlasRegion.</summary>
|
||||
public static RegionAttachment ToRegionAttachment (this AtlasRegion region, string attachmentName, float scale = 0.01f, float rotation = 0f) {
|
||||
if (string.IsNullOrEmpty(attachmentName)) throw new System.ArgumentException("attachmentName can't be null or empty.", "attachmentName");
|
||||
if (region == null) throw new System.ArgumentNullException("region");
|
||||
|
||||
// (AtlasAttachmentLoader.cs)
|
||||
var attachment = new RegionAttachment(attachmentName);
|
||||
|
||||
attachment.RendererObject = region;
|
||||
attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
|
||||
attachment.regionOffsetX = region.offsetX;
|
||||
attachment.regionOffsetY = region.offsetY;
|
||||
attachment.regionWidth = region.width;
|
||||
attachment.regionHeight = region.height;
|
||||
attachment.regionOriginalWidth = region.originalWidth;
|
||||
attachment.regionOriginalHeight = region.originalHeight;
|
||||
|
||||
attachment.Path = region.name;
|
||||
attachment.scaleX = 1;
|
||||
attachment.scaleY = 1;
|
||||
attachment.rotation = rotation;
|
||||
|
||||
attachment.r = 1;
|
||||
attachment.g = 1;
|
||||
attachment.b = 1;
|
||||
attachment.a = 1;
|
||||
|
||||
// pass OriginalWidth and OriginalHeight because UpdateOffset uses it in its calculation.
|
||||
attachment.width = attachment.regionOriginalWidth * scale;
|
||||
attachment.height = attachment.regionOriginalHeight * scale;
|
||||
|
||||
attachment.SetColor(Color.white);
|
||||
attachment.UpdateOffset();
|
||||
return attachment;
|
||||
}
|
||||
|
||||
/// <summary> Sets the scale. Call regionAttachment.UpdateOffset to apply the change.</summary>
|
||||
public static void SetScale (this RegionAttachment regionAttachment, Vector2 scale) {
|
||||
regionAttachment.scaleX = scale.x;
|
||||
regionAttachment.scaleY = scale.y;
|
||||
}
|
||||
|
||||
/// <summary> Sets the scale. Call regionAttachment.UpdateOffset to apply the change.</summary>
|
||||
public static void SetScale (this RegionAttachment regionAttachment, float x, float y) {
|
||||
regionAttachment.scaleX = x;
|
||||
regionAttachment.scaleY = y;
|
||||
}
|
||||
|
||||
/// <summary> Sets the position offset. Call regionAttachment.UpdateOffset to apply the change.</summary>
|
||||
public static void SetPositionOffset (this RegionAttachment regionAttachment, Vector2 offset) {
|
||||
regionAttachment.x = offset.x;
|
||||
regionAttachment.y = offset.y;
|
||||
}
|
||||
|
||||
/// <summary> Sets the position offset. Call regionAttachment.UpdateOffset to apply the change.</summary>
|
||||
public static void SetPositionOffset (this RegionAttachment regionAttachment, float x, float y) {
|
||||
regionAttachment.x = x;
|
||||
regionAttachment.y = y;
|
||||
}
|
||||
|
||||
/// <summary> Sets the rotation. Call regionAttachment.UpdateOffset to apply the change.</summary>
|
||||
public static void SetRotation (this RegionAttachment regionAttachment, float rotation) {
|
||||
regionAttachment.rotation = rotation;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e7eac783deea004e9bc403eca68a7dc
|
||||
timeCreated: 1563321428
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user