SkeletonUtility initial commit

This commit is contained in:
Fenrisul 2014-09-11 20:10:33 -07:00
parent 3f4c69d77a
commit bd40a5fa33
72 changed files with 2751 additions and 48 deletions

View File

@ -36,8 +36,9 @@ using Spine;
/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
[ExecuteInEditMode]
[AddComponentMenu("Spine/BoneComponent")]
public class BoneComponent : MonoBehaviour {
[AddComponentMenu("Spine/BoneFollower")]
public class BoneFollower : MonoBehaviour {
[System.NonSerialized]
public bool valid;
@ -55,31 +56,50 @@ public class BoneComponent : MonoBehaviour {
}
}
// TODO: Make the rotation behavior more customizable
// public bool followTransformRotation = false;
// TODO: Make transform follow bone scale? too specific? This is really useful for shared shadow assets.
//public bool followBoneScale = false;
/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
public String boneName;
public bool resetOnAwake = true;
protected Transform cachedTransform;
protected Transform skeletonTransform;
public void HandleResetRenderer(SkeletonRenderer skeletonRenderer){
Reset();
}
public void Reset () {
bone = null;
cachedTransform = transform;
valid = skeletonRenderer != null && skeletonRenderer.valid;
if (!valid) return;
skeletonTransform = skeletonRenderer.transform;
skeletonRenderer.OnReset -= HandleResetRenderer;
skeletonRenderer.OnReset += HandleResetRenderer;
if(Application.isEditor)
DoUpdate();
}
void OnDestroy(){
//cleanup
if(skeletonRenderer != null)
skeletonRenderer.OnReset -= HandleResetRenderer;
}
public void Awake () {
Reset();
if(resetOnAwake)
Reset();
}
public void LateUpdate () {
void LateUpdate(){
DoUpdate();
}
public void DoUpdate () {
if (!valid) {
Reset();
return;
@ -92,6 +112,9 @@ public class BoneComponent : MonoBehaviour {
Debug.LogError("Bone not found: " + boneName, this);
return;
}
else{
}
}
Spine.Skeleton skeleton = skeletonRenderer.skeleton;
@ -113,9 +136,10 @@ public class BoneComponent : MonoBehaviour {
if(followBoneRotation) {
Vector3 rotation = skeletonTransform.rotation.eulerAngles;
cachedTransform.rotation = Quaternion.Euler(rotation.x, rotation.y,
skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation) );
cachedTransform.rotation = Quaternion.Euler(rotation.x, rotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation) );
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 487b42efe96d8cc408a757541ea3f169
guid: a1fd8daaed7b64148a34acb96ba14ce1
MonoImporter:
serializedVersion: 2
defaultReferences: []

View File

@ -0,0 +1,106 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using System;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(BoneFollower))]
public class BoneFollowerInspector : Editor {
private SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation;
BoneFollower component;
void OnEnable () {
skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
boneName = serializedObject.FindProperty("boneName");
followBoneRotation = serializedObject.FindProperty("followBoneRotation");
followZPosition = serializedObject.FindProperty("followZPosition");
component = (BoneFollower)target;
ForceReload();
}
void FindRenderer(){
if(skeletonRenderer.objectReferenceValue == null){
SkeletonRenderer parentRenderer = component.GetComponentInParent<SkeletonRenderer>();
if(parentRenderer != null){
skeletonRenderer.objectReferenceValue = (UnityEngine.Object)parentRenderer;
}
}
}
void ForceReload(){
if(component.skeletonRenderer != null){
if(component.skeletonRenderer.valid == false)
component.skeletonRenderer.Reset();
}
}
override public void OnInspectorGUI () {
serializedObject.Update();
FindRenderer();
EditorGUILayout.PropertyField(skeletonRenderer);
if (component.valid) {
String[] bones = new String[1];
try{
bones = new String[component.skeletonRenderer.skeleton.Data.Bones.Count + 1];
}
catch{
}
bones[0] = "<None>";
for (int i = 0; i < bones.Length - 1; i++)
bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones[i].Name;
Array.Sort<String>(bones);
int boneIndex = Math.Max(0, Array.IndexOf(bones, boneName.stringValue));
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Bone");
EditorGUIUtility.LookLikeControls();
boneIndex = EditorGUILayout.Popup(boneIndex, bones);
EditorGUILayout.EndHorizontal();
boneName.stringValue = boneIndex == 0 ? null : bones[boneIndex];
EditorGUILayout.PropertyField(followBoneRotation);
EditorGUILayout.PropertyField(followZPosition);
}
else{
GUILayout.Label("INVALID");
}
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
component.Reset();
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c71ca35fd6241cb49a0b0756a664fcf7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 52b12ec801461494185a4d3dc66f3d1d
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 3d1be4ea889f3a14b864352fe49a1bde
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 8322793223a533a4ca8be6f430256dfc
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 97a43f11e00735147a9dc3dff6d68191
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 955aed20030d0504b8a9c6934a5cb47a
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: de1a4f5ad4bdf1a4ea072c4d59ba87d8
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: d226a80acc775714aa78b85e16a00e9b
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 2c2c6d283dcf3654baf40001c982891c
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 2b3a6f35bbaa8414eb51a344743ee641
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: a309a2e14638a204091b915126910f45
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: d1de1604dfe4cb64c9d31246a8e43c78
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: da6f6d414e43aac46a57cc5a87208db4
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: f2216037084d99d4481810cb521ed96f
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 5bb0631368b462047869d8788673cb48
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: bfd9f3d2607e9e44c97384d7575a17dc
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 04c82a4acf7b5244e947f2709ec3a6cf
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 8bd14c7643597a74ba2edc10a5e4c4ed
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 0338faf3e7d93e2478fcbc022d13e081
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 4e7c964fa5e07024c8bf1debecc3b7c8
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: f31c0c0d608e8ba4f9a1afb032092287
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -1
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: -1
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,47 @@
fileFormatVersion: 2
guid: 754d724c1bd750048852e8cf3d4a05ee
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

View File

@ -31,16 +31,23 @@
using System;
using UnityEditor;
using UnityEngine;
using Spine;
[CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : SkeletonRendererInspector {
protected SerializedProperty animationName, loop, timeScale;
protected bool isPrefab;
protected override void OnEnable () {
base.OnEnable();
animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop");
timeScale = serializedObject.FindProperty("timeScale");
if(PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
isPrefab = true;
}
protected override void gui () {
@ -49,6 +56,25 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
SkeletonAnimation component = (SkeletonAnimation)target;
if (!component.valid) return;
//catch case where SetAnimation was used to set track 0 without using AnimationName
if(Application.isPlaying){
TrackEntry currentState = component.state.GetCurrent(0);
if(currentState != null){
if(component.AnimationName != animationName.stringValue){
animationName.stringValue = currentState.Animation.Name;
}
if(loop.boolValue != currentState.Loop){
loop.boolValue = currentState.Loop;
}
if(timeScale.floatValue != currentState.TimeScale){
timeScale.floatValue = currentState.TimeScale;
}
}
}
// Animation name.
{
String[] animations = new String[component.skeleton.Data.Animations.Count + 1];
@ -69,10 +95,21 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex];
component.AnimationName = selectedAnimationName;
animationName.stringValue = selectedAnimationName;
}
EditorGUILayout.PropertyField(loop);
EditorGUILayout.PropertyField(timeScale);
component.timeScale = Math.Max(component.timeScale, 0);
EditorGUILayout.Space();
if(!isPrefab){
if(component.GetComponent<SkeletonUtility>() == null){
if(GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))){
component.gameObject.AddComponent<SkeletonUtility>();
}
}
}
}
}

View File

@ -28,6 +28,11 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Automatic import and advanced preview added by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using System;
using System.Collections.Generic;
using UnityEditor;
@ -53,18 +58,26 @@ public class SkeletonDataAssetInspector : Editor {
private string m_skeletonDataAssetGUID;
void OnEnable () {
atlasAsset = serializedObject.FindProperty("atlasAsset");
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
scale = serializedObject.FindProperty("scale");
fromAnimation = serializedObject.FindProperty("fromAnimation");
toAnimation = serializedObject.FindProperty("toAnimation");
duration = serializedObject.FindProperty("duration");
defaultMix = serializedObject.FindProperty("defaultMix");
m_skeletonDataAsset = (SkeletonDataAsset)target;
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(m_skeletonDataAsset) );
EditorApplication.update += Update;
try{
atlasAsset = serializedObject.FindProperty("atlasAsset");
skeletonJSON = serializedObject.FindProperty("skeletonJSON");
scale = serializedObject.FindProperty("scale");
fromAnimation = serializedObject.FindProperty("fromAnimation");
toAnimation = serializedObject.FindProperty("toAnimation");
duration = serializedObject.FindProperty("duration");
defaultMix = serializedObject.FindProperty("defaultMix");
m_skeletonDataAsset = (SkeletonDataAsset)target;
m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID( AssetDatabase.GetAssetPath(m_skeletonDataAsset) );
EditorApplication.update += Update;
}
catch{
}
}
void OnDestroy(){

View File

@ -1,4 +1,38 @@
#pragma warning disable 0219
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Spine Editor Utilities created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
using UnityEditor;
@ -15,6 +49,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
public static Texture2D skeleton;
public static Texture2D nullBone;
public static Texture2D bone;
public static Texture2D poseBones;
public static Texture2D boneNib;
public static Texture2D slot;
public static Texture2D skinPlaceholder;
@ -27,6 +62,11 @@ public class SpineEditorUtilities : AssetPostprocessor {
public static Texture2D animationRoot;
public static Texture2D spine;
public static Texture2D _event;
public static Texture2D constraintNib;
public static Texture2D warning;
public static Texture2D skeletonUtility;
public static Texture2D hingeChain;
public static Texture2D subMeshRenderer;
public static Mesh boneMesh{
get{
@ -61,6 +101,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png");
nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-null.png");
bone = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-bone.png");
poseBones = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-poseBones.png");
boneNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-boneNib.png");
slot = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-slot.png");
skinPlaceholder = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png");
@ -73,6 +114,12 @@ public class SpineEditorUtilities : AssetPostprocessor {
animationRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-animationRoot.png");
spine = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-spine.png");
_event = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-event.png");
constraintNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-constraintNib.png");
warning = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-warning.png");
skeletonUtility = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-skeletonUtility.png");
hingeChain = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-hingeChain.png");
subMeshRenderer = (Texture2D)AssetDatabase.LoadMainAssetAtPath( SpineEditorUtilities.editorGUIPath + "/icon-subMeshRenderer.png");
}
}
@ -81,8 +128,9 @@ public class SpineEditorUtilities : AssetPostprocessor {
public static string editorPath = "";
public static string editorGUIPath = "";
static List<int> skeletonRendererInstanceIDs;
static Dictionary<int, GameObject> skeletonRendererTable;
static Dictionary<int, SkeletonUtilityBone> skeletonUtilityBoneTable;
public static float defaultScale = 0.01f;
public static float defaultMix = 0.2f;
@ -96,7 +144,8 @@ public class SpineEditorUtilities : AssetPostprocessor {
Icons.Initialize();
skeletonRendererInstanceIDs = new List<int>();
skeletonRendererTable = new Dictionary<int, GameObject>();
skeletonUtilityBoneTable = new Dictionary<int, SkeletonUtilityBone>();
EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
@ -105,22 +154,49 @@ public class SpineEditorUtilities : AssetPostprocessor {
}
static void HierarchyWindowChanged(){
skeletonRendererInstanceIDs.Clear();
skeletonRendererTable.Clear();
skeletonUtilityBoneTable.Clear();
SkeletonRenderer[] arr = Object.FindObjectsOfType<SkeletonRenderer>();
foreach(SkeletonRenderer r in arr)
skeletonRendererInstanceIDs.Add(r.gameObject.GetInstanceID());
skeletonRendererTable.Add( r.gameObject.GetInstanceID(), r.gameObject );
SkeletonUtilityBone[] boneArr = Object.FindObjectsOfType<SkeletonUtilityBone>();
foreach(SkeletonUtilityBone b in boneArr)
skeletonUtilityBoneTable.Add(b.gameObject.GetInstanceID(), b);
}
static void HierarchyWindowItemOnGUI(int instanceId, Rect selectionRect){
if(skeletonRendererInstanceIDs.Contains(instanceId)){
if(skeletonRendererTable.ContainsKey(instanceId)){
Rect r = new Rect (selectionRect);
r.x = r.width - 15;
r.width = 15;
GUI.Label(r, Icons.spine);
}
else if(skeletonUtilityBoneTable.ContainsKey(instanceId)){
Rect r = new Rect (selectionRect);
//r.x = r.width - 15;
r.x -= 26;
if(skeletonUtilityBoneTable[instanceId] != null){
if( skeletonUtilityBoneTable[instanceId].transform.childCount == 0 )
r.x += 15;
r.width = 15;
if( skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow ){
GUI.Label(r, Icons.bone);
}
else{
GUI.Label(r, Icons.poseBones);
}
}
}
}
[MenuItem("Assets/Spine/Ingest")]
@ -335,20 +411,24 @@ public class SpineEditorUtilities : AssetPostprocessor {
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(spineJson));
string filePath = assetPath + "/" + primaryName + "_SkeletonData.asset";
if(spineJson != null && atlasAsset != null){
SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
skelDataAsset.atlasAsset = atlasAsset;
skelDataAsset.skeletonJSON = spineJson;
skelDataAsset.fromAnimation = new string[0];
skelDataAsset.toAnimation = new string[0];
skelDataAsset.duration = new float[0];
skelDataAsset.defaultMix = defaultMix;
skelDataAsset.scale = defaultScale;
AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset");
AssetDatabase.SaveAssets();
SkeletonDataAsset skelDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
if(skelDataAsset == null){
skelDataAsset = SkeletonDataAsset.CreateInstance<SkeletonDataAsset>();
skelDataAsset.atlasAsset = atlasAsset;
skelDataAsset.skeletonJSON = spineJson;
skelDataAsset.fromAnimation = new string[0];
skelDataAsset.toAnimation = new string[0];
skelDataAsset.duration = new float[0];
skelDataAsset.defaultMix = defaultMix;
skelDataAsset.scale = defaultScale;
AssetDatabase.CreateAsset(skelDataAsset, filePath);
AssetDatabase.SaveAssets();
}
return skelDataAsset;
}

View File

@ -0,0 +1,69 @@
Shader "Spine/Bones" {
Properties {
_Color ("Color", Color) = (0.5,0.5,0.5,0.5)
_MainTex ("Particle Texture", 2D) = "white" {}
}
Category {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
AlphaTest Greater .01
ColorMask RGB
Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_particles
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 _Color;
struct appdata_t {
float4 vertex : POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
#ifdef SOFTPARTICLES_ON
float4 projPos : TEXCOORD1;
#endif
};
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
#ifdef SOFTPARTICLES_ON
o.projPos = ComputeScreenPos (o.vertex);
COMPUTE_EYEDEPTH(o.projPos.z);
#endif
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
sampler2D_float _CameraDepthTexture;
fixed4 frag (v2f i) : SV_Target
{
return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
}
ENDCG
}
}
}
}

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 66988de88a15abd4e8846c6805485f57
ShaderImporter:
defaultTextures: []
userData:

Binary file not shown.

View File

@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 43227e5adadc6f24bb4bf74b92a56fb4
NativeFormatImporter:
userData:

View File

@ -0,0 +1,21 @@
Shader "Spine/HiddenPass" {
SubShader
{
Tags {"Queue" = "Geometry-1" }
Lighting Off
Pass
{
ZWrite Off
ColorMask 0
}
}
}

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 913475501bf19374c84390868a9d6d3d
ShaderImporter:
defaultTextures: []
userData:

View File

@ -42,7 +42,9 @@ public class SkeletonAnimation : SkeletonRenderer {
public Spine.AnimationState state;
public delegate void UpdateBonesDelegate(SkeletonAnimation skeleton);
public UpdateBonesDelegate UpdateBones;
public UpdateBonesDelegate UpdateLocal;
public UpdateBonesDelegate UpdateWorld;
public UpdateBonesDelegate UpdateComplete;
[SerializeField]
private String _animationName;
@ -83,7 +85,19 @@ public class SkeletonAnimation : SkeletonRenderer {
skeleton.Update(deltaTime);
state.Update(deltaTime);
state.Apply(skeleton);
if (UpdateBones != null) UpdateBones(this);
if (UpdateLocal != null)
UpdateLocal(this);
skeleton.UpdateWorldTransform();
if (UpdateWorld != null){
UpdateWorld(this);
skeleton.UpdateWorldTransform();
}
if (UpdateComplete != null){
UpdateComplete(this);
}
}
}

View File

@ -1,4 +1,39 @@
using UnityEngine;
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Spine Extensions created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
using System.Collections;
using Spine;

View File

@ -37,6 +37,10 @@ using Spine;
/// <summary>Renders a skeleton.</summary>
[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class SkeletonRenderer : MonoBehaviour {
public delegate void SkeletonRendererDelegate(SkeletonRenderer skeletonRenderer);
public SkeletonRendererDelegate OnReset;
[System.NonSerialized]
public bool valid;
[System.NonSerialized]
@ -96,6 +100,7 @@ public class SkeletonRenderer : MonoBehaviour {
skeleton = new Skeleton(skeletonData);
if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default")
skeleton.SetSkin(initialSkinName);
if(OnReset != null) OnReset(this);
}
public void Awake () {
@ -112,7 +117,6 @@ public class SkeletonRenderer : MonoBehaviour {
public virtual void LateUpdate () {
if (!valid) return;
// Count vertices and submesh triangles.
int vertexCount = 0;
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
@ -122,7 +126,8 @@ public class SkeletonRenderer : MonoBehaviour {
int drawOrderCount = drawOrder.Count;
bool renderMeshes = this.renderMeshes;
for (int i = 0; i < drawOrderCount; i++) {
Attachment attachment = drawOrder[i].attachment;
Slot slot = drawOrder[i];
Attachment attachment = slot.attachment;
object rendererObject;
int attachmentVertexCount, attachmentTriangleCount;
@ -149,7 +154,7 @@ public class SkeletonRenderer : MonoBehaviour {
// Populate submesh when material changes.
Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
if (lastMaterial != material && lastMaterial != null) {
if ((lastMaterial != material && lastMaterial != null) || slot.Data.name[0] == '*') {
AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
submeshTriangleCount = 0;
submeshFirstVertex = vertexCount;

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: f6e0caaafe294de48af468a6a9321473
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: a751a9d1e3e26d64d997b66a781df8e9
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,287 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Skeleton Utility created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using Spine;
[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
public class SkeletonUtilityBoneInspector : Editor {
SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
//multi selected flags
bool containsFollows, containsOverrides, multiObject;
//single selected helpers
SkeletonUtilityBone utilityBone;
SkeletonUtility skeletonUtility;
bool canCreateHingeChain = false;
void OnEnable(){
mode = this.serializedObject.FindProperty("mode");
boneName = this.serializedObject.FindProperty("boneName");
zPosition = this.serializedObject.FindProperty("zPosition");
position = this.serializedObject.FindProperty("position");
rotation = this.serializedObject.FindProperty("rotation");
scale = this.serializedObject.FindProperty("scale");
overrideAlpha = this.serializedObject.FindProperty("overrideAlpha");
parentReference = this.serializedObject.FindProperty("parentReference");
EvaluateFlags();
if(utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null){
skeletonUtility.skeletonRenderer.Reset();
}
canCreateHingeChain = CanCreateHingeChain();
}
/// <summary>
/// Evaluates the flags.
/// </summary>
void EvaluateFlags(){
utilityBone = (SkeletonUtilityBone)target;
skeletonUtility = utilityBone.skeletonUtility;
if(Selection.objects.Length == 1){
containsFollows = utilityBone.mode == SkeletonUtilityBone.Mode.Follow;
containsOverrides = utilityBone.mode == SkeletonUtilityBone.Mode.Override;
}
else{
int boneCount = 0;
foreach(Object o in Selection.objects){
if(o is GameObject){
GameObject go = (GameObject)o;
SkeletonUtilityBone sub = go.GetComponent<SkeletonUtilityBone>();
if(sub != null){
boneCount++;
if(sub.mode == SkeletonUtilityBone.Mode.Follow)
containsFollows = true;
if(sub.mode == SkeletonUtilityBone.Mode.Override)
containsOverrides = true;
}
}
}
if(boneCount > 1)
multiObject = true;
}
}
public override void OnInspectorGUI ()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(mode);
if(EditorGUI.EndChangeCheck()){
containsOverrides = mode.enumValueIndex == 1;
containsFollows = mode.enumValueIndex == 0;
}
EditorGUI.BeginDisabledGroup( multiObject );
{
string str = boneName.stringValue;
if(str == "") str = "<None>";
if(multiObject) str = "<Multiple>";
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Bone");
if(GUILayout.Button( str, EditorStyles.popup )){
BoneSelectorContextMenu( str, ((SkeletonUtilityBone)target).skeletonUtility.skeletonRenderer.skeleton.Bones, "<None>", TargetBoneSelected );
}
GUILayout.EndHorizontal();
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.PropertyField(zPosition);
EditorGUILayout.PropertyField(position);
EditorGUILayout.PropertyField(rotation);
EditorGUILayout.PropertyField(scale);
EditorGUI.BeginDisabledGroup( containsFollows );
{
EditorGUILayout.PropertyField(overrideAlpha);
EditorGUILayout.PropertyField(parentReference);
}
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
GUILayout.BeginHorizontal();
{
EditorGUI.BeginDisabledGroup( multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0);
{
if(GUILayout.Button(new GUIContent("Add Child", SpineEditorUtilities.Icons.bone), GUILayout.Width(150), GUILayout.Height(24)))
BoneSelectorContextMenu( "", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup( multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides);
{
if(GUILayout.Button(new GUIContent("Add Override", SpineEditorUtilities.Icons.poseBones), GUILayout.Width(150), GUILayout.Height(24)))
SpawnOverride();
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup( multiObject || !utilityBone.valid || !canCreateHingeChain );
{
if(GUILayout.Button(new GUIContent("Create Hinge Chain", SpineEditorUtilities.Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24)))
CreateHingeChain();
}
EditorGUI.EndDisabledGroup();
}
GUILayout.EndHorizontal();
serializedObject.ApplyModifiedProperties();
}
void BoneSelectorContextMenu(string current, List<Bone> bones, string topValue, GenericMenu.MenuFunction2 callback){
GenericMenu menu = new GenericMenu();
if(topValue != "")
menu.AddItem( new GUIContent(topValue), current == topValue, callback, null );
for(int i = 0; i < bones.Count; i++){
menu.AddItem( new GUIContent(bones[i].Data.Name), bones[i].Data.Name == current, callback, bones[i] );
}
menu.ShowAsContext();
}
void TargetBoneSelected(object obj){
if(obj == null){
boneName.stringValue = "";
serializedObject.ApplyModifiedProperties();
}
else{
Bone bone = (Bone)obj;
boneName.stringValue = bone.Data.Name;
serializedObject.ApplyModifiedProperties();
utilityBone.Reset();
}
}
void SpawnChildBoneSelected(object obj){
if(obj == null){
//add recursively
foreach(var bone in utilityBone.bone.Children){
GameObject go = skeletonUtility.SpawnBoneRecursively( bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale );
SkeletonUtilityBone[] newUtilityBones = go.GetComponentsInChildren<SkeletonUtilityBone>();
foreach(SkeletonUtilityBone utilBone in newUtilityBones)
SkeletonUtilityInspector.AttachIcon(utilBone);
}
}
else{
Bone bone = (Bone)obj;
GameObject go = skeletonUtility.SpawnBone( bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale );
SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
}
}
void SpawnOverride(){
GameObject go = skeletonUtility.SpawnBone( utilityBone.bone, utilityBone.transform.parent, SkeletonUtilityBone.Mode.Override, utilityBone.position, utilityBone.rotation, utilityBone.scale);
go.name = go.name + " [Override]";
SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
Selection.activeGameObject = go;
EditorGUIUtility.PingObject(go);
}
bool CanCreateHingeChain(){
if(utilityBone == null) return false;
if(utilityBone.rigidbody != null) return false;
if(utilityBone.bone != null && utilityBone.bone.Children.Count == 0) return false;
Rigidbody[] rigidbodies = utilityBone.GetComponentsInChildren<Rigidbody>();
if(rigidbodies.Length > 0) return false;
return true;
}
void CreateHingeChain(){
var utilBoneArr = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
foreach(var utilBone in utilBoneArr){
AttachRigidbody(utilBone);
}
utilityBone.rigidbody.isKinematic = true;
foreach(var utilBone in utilBoneArr){
if(utilBone == utilityBone)
continue;
utilBone.mode = SkeletonUtilityBone.Mode.Override;
HingeJoint joint = utilBone.gameObject.AddComponent<HingeJoint>();
joint.axis = Vector3.forward;
joint.connectedBody = utilBone.transform.parent.rigidbody;
joint.useLimits = true;
JointLimits limits = new JointLimits();
limits.min = -20;
limits.max = 20;
joint.limits = limits;
utilBone.rigidbody.mass = utilBone.transform.parent.rigidbody.mass * 0.75f;
}
}
void AttachRigidbody(SkeletonUtilityBone utilBone){
if(utilBone.GetComponent<Collider>() == null){
if(utilBone.bone.Data.Length == 0){
SphereCollider sphere = utilBone.gameObject.AddComponent<SphereCollider>();
sphere.radius = 0.1f;
}
else{
float length = utilBone.bone.Data.Length;
BoxCollider box = utilBone.gameObject.AddComponent<BoxCollider>();
box.size = new Vector3( length, length / 3, 0.2f);
box.center = new Vector3(length / 2, 0, 0);
}
}
utilBone.gameObject.AddComponent<Rigidbody>();
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b3ae20b4bcc31f645afd6f5b64f82473
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,316 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Skeleton Utility created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
using UnityEditor;
#if UNITY_4_3
//nothing
#else
using UnityEditor.AnimatedValues;
#endif
using System.Collections;
using System.Collections.Generic;
using Spine;
using System.Reflection;
[CustomEditor(typeof(SkeletonUtility))]
public class SkeletonUtilityInspector : Editor {
public static void AttachIcon(SkeletonUtilityBone utilityBone){
Skeleton skeleton = utilityBone.skeletonUtility.skeletonRenderer.skeleton;
Texture2D icon;
if(utilityBone.bone.Data.Length == 0)
icon = SpineEditorUtilities.Icons.nullBone;
else
icon = SpineEditorUtilities.Icons.boneNib;
foreach(IkConstraint c in skeleton.IkConstraints){
if(c.Target == utilityBone.bone){
icon = SpineEditorUtilities.Icons.constraintNib;
break;
}
}
typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2]{ utilityBone.gameObject, icon});
}
static void AttachIconsToChildren(Transform root){
if(root != null){
var utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
foreach(var utilBone in utilityBones){
AttachIcon(utilBone);
}
}
}
static SkeletonUtilityInspector(){
#if UNITY_4_3
showSlots = false;
#else
showSlots = new AnimBool(false);
#endif
}
SkeletonUtility skeletonUtility;
Skeleton skeleton;
SkeletonRenderer skeletonRenderer;
Transform transform;
bool isPrefab;
Dictionary<Slot, List<Attachment>> attachmentTable = new Dictionary<Slot, List<Attachment>>();
//GUI stuff
#if UNITY_4_3
static bool showSlots;
#else
static AnimBool showSlots;
#endif
void OnEnable(){
skeletonUtility = (SkeletonUtility)target;
skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
skeleton = skeletonRenderer.skeleton;
transform = skeletonRenderer.transform;
if(skeleton == null){
skeletonRenderer.Reset();
skeletonRenderer.LateUpdate();
skeleton = skeletonRenderer.skeleton;
}
UpdateAttachments();
if(PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
isPrefab = true;
}
void OnDestroy(){
}
void OnSceneGUI(){
if(skeleton == null){
OnEnable();
return;
}
float flipRotation = skeleton.FlipX ? -1 : 1;
foreach(Bone b in skeleton.Bones){
Vector3 vec = transform.TransformPoint(new Vector3(b.WorldX, b.WorldY, 0));
Quaternion rot = Quaternion.Euler(0,0,b.WorldRotation * flipRotation);
Vector3 forward = transform.TransformDirection( rot * Vector3.right);
forward *= flipRotation;
SpineEditorUtilities.Icons.boneMaterial.SetPass(0);
Graphics.DrawMeshNow( SpineEditorUtilities.Icons.boneMesh, Matrix4x4.TRS ( vec, Quaternion.LookRotation(transform.forward, forward), Vector3.one * b.Data.Length * b.WorldScaleX));
}
}
void UpdateAttachments(){
attachmentTable = new Dictionary<Slot, List<Attachment>>();
Skin skin = skeleton.Skin;
if(skin == null){
skin = skeletonRenderer.skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
}
for(int i = skeleton.Slots.Count-1; i >= 0; i--){
List<Attachment> attachments = new List<Attachment>();
skin.FindAttachmentsForSlot(i, attachments);
attachmentTable.Add(skeleton.Slots[i], attachments);
}
}
void SpawnHierarchyButton(string label, string tooltip, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca, params GUILayoutOption[] options){
GUIContent content = new GUIContent(label, tooltip);
if(GUILayout.Button(content, options)){
if(skeletonUtility.skeletonRenderer == null)
skeletonUtility.skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
if(skeletonUtility.boneRoot != null){
return;
}
skeletonUtility.SpawnHierarchy(mode, pos, rot, sca);
SkeletonUtilityBone[] boneComps = skeletonUtility.GetComponentsInChildren<SkeletonUtilityBone>();
foreach(SkeletonUtilityBone b in boneComps)
AttachIcon(b);
}
}
public override void OnInspectorGUI ()
{
if(isPrefab){
GUILayout.Label(new GUIContent("Cannot edit Prefabs", SpineEditorUtilities.Icons.warning));
return;
}
skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField( "Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);
GUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(skeletonUtility.boneRoot != null);
{
if(GUILayout.Button(new GUIContent("Spawn Hierarchy", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(150), GUILayout.Height(24)))
SpawnHierarchyContextMenu();
}
EditorGUI.EndDisabledGroup();
if(GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24)))
skeletonUtility.SpawnSubRenderers(true);
GUILayout.EndHorizontal();
EditorGUI.BeginChangeCheck();
skeleton.FlipX = EditorGUILayout.ToggleLeft("Flip X", skeleton.FlipX);
skeleton.FlipY = EditorGUILayout.ToggleLeft("Flip Y", skeleton.FlipY);
if(EditorGUI.EndChangeCheck()){
skeletonRenderer.LateUpdate();
SceneView.RepaintAll();
}
#if UNITY_4_3
showSlots = EditorGUILayout.Foldout(showSlots, "Slots");
#else
showSlots.target = EditorGUILayout.Foldout(showSlots.target, "Slots");
if(EditorGUILayout.BeginFadeGroup(showSlots.faded)){
#endif
foreach(KeyValuePair<Slot, List<Attachment>> pair in attachmentTable){
Slot slot = pair.Key;
EditorGUILayout.BeginHorizontal();
EditorGUI.indentLevel = 1;
EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, SpineEditorUtilities.Icons.slot), GUILayout.ExpandWidth(false));
EditorGUI.BeginChangeCheck();
Color c = EditorGUILayout.ColorField(new Color(slot.R, slot.G, slot.B, slot.A), GUILayout.Width(60));
if(EditorGUI.EndChangeCheck()){
slot.SetColor( c );
skeletonRenderer.LateUpdate();
}
EditorGUILayout.EndHorizontal();
foreach(Attachment attachment in pair.Value){
if(slot.Attachment == attachment){
GUI.contentColor = Color.white;
}
else{
GUI.contentColor = Color.grey;
}
EditorGUI.indentLevel = 2;
bool isAttached = attachment == slot.Attachment;
Texture2D icon = null;
if(attachment is MeshAttachment || attachment is SkinnedMeshAttachment)
icon = SpineEditorUtilities.Icons.mesh;
else
icon = SpineEditorUtilities.Icons.image;
bool swap = EditorGUILayout.ToggleLeft( new GUIContent( attachment.Name, icon ), attachment == slot.Attachment );
if(!isAttached && swap){
slot.Attachment = attachment;
skeletonRenderer.LateUpdate();
}
else if(isAttached && !swap){
slot.Attachment = null;
skeletonRenderer.LateUpdate();
}
GUI.contentColor = Color.white;
}
}
#if UNITY_4_3
#else
}
EditorGUILayout.EndFadeGroup();
if(showSlots.isAnimating)
Repaint();
#endif
}
void SpawnHierarchyContextMenu(){
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Follow"), false, SpawnFollowHierarchy);
menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
menu.AddSeparator("");
menu.AddItem(new GUIContent("Override"), false, SpawnOverrideHierarchy);
menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
menu.ShowAsContext();
}
void SpawnFollowHierarchy(){
Selection.activeGameObject = skeletonUtility.SpawnHierarchy( SkeletonUtilityBone.Mode.Follow, true, true, true );
AttachIconsToChildren( skeletonUtility.boneRoot );
}
void SpawnFollowHierarchyRootOnly(){
Selection.activeGameObject = skeletonUtility.SpawnRoot( SkeletonUtilityBone.Mode.Follow, true, true, true );
AttachIconsToChildren( skeletonUtility.boneRoot );
}
void SpawnOverrideHierarchy(){
Selection.activeGameObject = skeletonUtility.SpawnHierarchy( SkeletonUtilityBone.Mode.Override, true, true, true );
AttachIconsToChildren( skeletonUtility.boneRoot );
}
void SpawnOverrideHierarchyRootOnly(){
Selection.activeGameObject = skeletonUtility.SpawnRoot( SkeletonUtilityBone.Mode.Override, true, true, true );
AttachIconsToChildren( skeletonUtility.boneRoot );
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a5b90df955eb8c2429ac67c8b2de6c5c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,335 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Skeleton Utility created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Spine;
[RequireComponent(typeof(SkeletonAnimation))]
[ExecuteInEditMode]
public class SkeletonUtility : MonoBehaviour {
public delegate void SkeletonUtilityDelegate();
public event SkeletonUtilityDelegate OnReset;
public Transform boneRoot;
void Update(){
if(boneRoot != null && skeletonRenderer.skeleton != null){
Vector3 flipScale = Vector3.one;
if(skeletonRenderer.skeleton.FlipX)
flipScale.x = -1;
if(skeletonRenderer.skeleton.FlipY)
flipScale.y = -1;
boneRoot.localScale = flipScale;
}
}
[HideInInspector]
public SkeletonRenderer skeletonRenderer;
[HideInInspector]
public SkeletonAnimation skeletonAnimation;
[System.NonSerialized]
public List<SkeletonUtilityBone> utilityBones = new List<SkeletonUtilityBone>();
[System.NonSerialized]
public List<SkeletonUtilityConstraint> utilityConstraints = new List<SkeletonUtilityConstraint>();
// Dictionary<Bone, SkeletonUtilityBone> utilityBoneTable;
protected bool hasTransformBones;
protected bool hasUtilityConstraints;
protected bool needToReprocessBones;
void OnEnable(){
if(skeletonRenderer == null){
skeletonRenderer = GetComponent<SkeletonRenderer>();
}
if(skeletonAnimation == null){
skeletonAnimation = GetComponent<SkeletonAnimation>();
}
skeletonRenderer.OnReset -= HandleRendererReset;
skeletonRenderer.OnReset += HandleRendererReset;
if(skeletonAnimation != null){
skeletonAnimation.UpdateLocal -= UpdateLocal;
skeletonAnimation.UpdateLocal += UpdateLocal;
}
CollectBones();
}
void Start(){
//recollect because order of operations failure when switching between game mode and edit mode...
// CollectBones();
}
void OnDisable(){
skeletonRenderer.OnReset -= HandleRendererReset;
if(skeletonAnimation != null){
skeletonAnimation.UpdateLocal -= UpdateLocal;
skeletonAnimation.UpdateWorld -= UpdateWorld;
skeletonAnimation.UpdateComplete -= UpdateComplete;
}
}
void HandleRendererReset(SkeletonRenderer r){
if(OnReset != null)
OnReset();
CollectBones();
}
public void RegisterBone(SkeletonUtilityBone bone){
if(utilityBones.Contains(bone))
return;
else{
utilityBones.Add(bone);
needToReprocessBones = true;
}
}
public void UnregisterBone(SkeletonUtilityBone bone){
utilityBones.Remove(bone);
}
public void RegisterConstraint(SkeletonUtilityConstraint constraint){
if(utilityConstraints.Contains(constraint))
return;
else{
utilityConstraints.Add(constraint);
needToReprocessBones = true;
}
}
public void UnregisterConstraint(SkeletonUtilityConstraint constraint){
utilityConstraints.Remove(constraint);
}
public void CollectBones(){
if(skeletonRenderer.skeleton == null)
return;
if(boneRoot != null){
List<string> constraintTargetNames = new List<string>();
foreach(IkConstraint c in skeletonRenderer.skeleton.IkConstraints){
constraintTargetNames.Add(c.Target.Data.Name);
}
foreach(var b in utilityBones){
if(b.bone == null){
return;
}
if(b.mode == SkeletonUtilityBone.Mode.Override){
hasTransformBones = true;
}
if(constraintTargetNames.Contains( b.bone.Data.Name )){
hasUtilityConstraints = true;
}
}
if(utilityConstraints.Count > 0)
hasUtilityConstraints = true;
if(skeletonAnimation != null){
skeletonAnimation.UpdateWorld -= UpdateWorld;
skeletonAnimation.UpdateComplete -= UpdateComplete;
if(hasTransformBones || hasUtilityConstraints){
skeletonAnimation.UpdateWorld += UpdateWorld;
}
if(hasUtilityConstraints){
skeletonAnimation.UpdateComplete += UpdateComplete;
}
}
needToReprocessBones = false;
}
else{
utilityBones.Clear();
utilityConstraints.Clear();
}
}
void UpdateLocal(SkeletonAnimation anim){
if(needToReprocessBones)
CollectBones();
if(utilityBones == null)
return;
foreach(SkeletonUtilityBone b in utilityBones){
b.transformLerpComplete = false;
}
UpdateAllBones();
}
void UpdateWorld(SkeletonAnimation anim){
UpdateAllBones();
foreach(SkeletonUtilityConstraint c in utilityConstraints)
c.DoUpdate();
}
void UpdateComplete(SkeletonAnimation anim){
UpdateAllBones();
}
void UpdateAllBones(){
if(boneRoot == null){
CollectBones();
}
if(utilityBones == null)
return;
foreach(SkeletonUtilityBone b in utilityBones){
b.DoUpdate();
}
}
public Transform GetBoneRoot(){
if(boneRoot != null)
return boneRoot;
boneRoot = new GameObject("SkeletonUtility-Root").transform;
boneRoot.parent = transform;
boneRoot.localPosition = Vector3.zero;
boneRoot.localRotation = Quaternion.identity;
boneRoot.localScale = Vector3.one;
return boneRoot;
}
public GameObject SpawnRoot(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca){
GetBoneRoot();
Skeleton skeleton = this.skeletonRenderer.skeleton;
GameObject go = SpawnBone( skeleton.RootBone, boneRoot, mode, pos, rot, sca );
CollectBones();
return go;
}
public GameObject SpawnHierarchy(SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca){
GetBoneRoot();
Skeleton skeleton = this.skeletonRenderer.skeleton;
GameObject go = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
CollectBones();
return go;
}
public GameObject SpawnBoneRecursively(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca){
GameObject go = SpawnBone(bone, parent, mode, pos, rot, sca);
foreach(Bone child in bone.Children){
SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca);
}
return go;
}
public GameObject SpawnBone(Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca){
GameObject go = new GameObject(bone.Data.Name);
go.transform.parent = parent;
SkeletonUtilityBone b = go.AddComponent<SkeletonUtilityBone>();
b.skeletonUtility = this;
b.position = pos;
b.rotation = rot;
b.scale = sca;
b.mode = mode;
b.zPosition = true;
b.Reset();
b.bone = bone;
b.boneName = bone.Data.Name;
b.valid = true;
if(mode == SkeletonUtilityBone.Mode.Override){
if(rot)
go.transform.localRotation = Quaternion.Euler(0, 0, b.bone.RotationIK);
if(pos)
go.transform.localPosition = new Vector3(b.bone.X, b.bone.Y, 0);
go.transform.localScale = new Vector3(b.bone.scaleX, b.bone.scaleY, 0);
}
return go;
}
public void SpawnSubRenderers(bool disablePrimaryRenderer){
int submeshCount = GetComponent<MeshFilter>().sharedMesh.subMeshCount;
for(int i = 0; i < submeshCount; i++){
GameObject go = new GameObject("Submesh " + i, typeof(MeshFilter), typeof(MeshRenderer));
go.transform.parent = transform;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
go.transform.localScale = Vector3.one;
SkeletonUtilitySubmeshRenderer s = go.AddComponent<SkeletonUtilitySubmeshRenderer>();
s.sortingOrder = i * 10;
s.submeshIndex = i;
s.Initialize( renderer );
s.Update();
}
if(disablePrimaryRenderer)
renderer.enabled = false;
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7f726fb798ad621458c431cb9966d91d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,218 @@
/******************************************************************************
* Spine Runtimes Software License
* Version 2.1
*
* Copyright (c) 2013, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to install, execute and perform the Spine Runtimes
* Software (the "Software") solely for internal use. Without the written
* permission of Esoteric Software (typically granted by licensing Spine), you
* may not (a) modify, translate, adapt or otherwise create derivative works,
* improvements of the Software or develop new applications using the Software
* or (b) remove, delete, alter or obscure any trademarks or any copyright,
* trademark, patent or other intellectual property or proprietary rights
* notices on or in the Software, including any copy thereof. Redistributions
* in binary or source form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) 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 THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
/*****************************************************************************
* Skeleton Utility created by Mitch Thompson
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using Spine;
/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
[ExecuteInEditMode]
[AddComponentMenu("Spine/SkeletonUtilityBone")]
public class SkeletonUtilityBone : MonoBehaviour {
public enum Mode { Follow, Override }
[System.NonSerialized]
public bool valid;
[System.NonSerialized]
public SkeletonUtility skeletonUtility;
[System.NonSerialized]
public Bone bone;
public Mode mode;
public bool zPosition = true;
public bool position;
public bool rotation;
public bool scale;
[Range(0f,1f)]
public float overrideAlpha = 1;
/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
public String boneName;
public Transform parentReference;
[HideInInspector]
public bool transformLerpComplete;
protected Transform cachedTransform;
protected Transform skeletonTransform;
public bool NonUniformScaleWarning{
get{
return nonUniformScaleWarning;
}
}
private bool nonUniformScaleWarning;
public void Reset () {
bone = null;
cachedTransform = transform;
valid = skeletonUtility != null && skeletonUtility.skeletonRenderer != null && skeletonUtility.skeletonRenderer.valid;
if (!valid) return;
skeletonTransform = skeletonUtility.transform;
skeletonUtility.OnReset -= HandleOnReset;
skeletonUtility.OnReset += HandleOnReset;
DoUpdate();
}
void OnEnable(){
skeletonUtility = GetComponentInParent<SkeletonUtility>();
if(skeletonUtility == null)
return;
skeletonUtility.RegisterBone(this);
skeletonUtility.OnReset += HandleOnReset;
}
void HandleOnReset ()
{
Reset ();
}
void OnDisable(){
if(skeletonUtility != null){
skeletonUtility.OnReset -= HandleOnReset;
skeletonUtility.UnregisterBone(this);
}
}
public void DoUpdate () {
if (!valid) {
Reset();
return;
}
Spine.Skeleton skeleton = skeletonUtility.skeletonRenderer.skeleton;
if (bone == null) {
if (boneName == null || boneName.Length == 0) return;
bone = skeleton.FindBone(boneName);
if (bone == null) {
Debug.LogError("Bone not found: " + boneName, this);
return;
}
}
float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
if(mode == Mode.Follow){
if(position){
cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0);
}
if(rotation){
if(bone.Data.InheritRotation){
cachedTransform.localRotation = Quaternion.Euler(0,0,bone.rotationIK);
}
else{
Vector3 euler = skeletonTransform.rotation.eulerAngles;
cachedTransform.rotation = Quaternion.Euler(euler.x, euler.y, skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation) );
}
}
if(scale){
cachedTransform.localScale = new Vector3(bone.scaleX, bone.scaleY, 1);
nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
}
}
else if(mode == Mode.Override){
if(transformLerpComplete)
return;
if(parentReference == null){
if(position){
bone.x = Mathf.Lerp(bone.x, cachedTransform.localPosition.x, overrideAlpha);
bone.y = Mathf.Lerp(bone.y, cachedTransform.localPosition.y, overrideAlpha);
}
if(rotation){
bone.rotation = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha);
}
if(scale){
bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
}
}
else{
if(position){
Vector3 pos = parentReference.InverseTransformPoint(cachedTransform.position);
bone.x = Mathf.Lerp(bone.x, pos.x, overrideAlpha);
bone.y = Mathf.Lerp(bone.y, pos.y, overrideAlpha);
}
if(rotation){
bone.rotation = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation( Vector3.forward, parentReference.InverseTransformDirection( cachedTransform.up ) ).eulerAngles.z, overrideAlpha);
}
//TODO: Something about this
if(scale){
bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
}
}
transformLerpComplete = true;
}
}
void OnDrawGizmos(){
if(NonUniformScaleWarning){
Gizmos.DrawIcon(transform.position + new Vector3(0,0.128f,0), "icon-warning");
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b238dfcde8209044b97d23f62bcaadf6
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,22 @@
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
public abstract class SkeletonUtilityConstraint : MonoBehaviour {
protected SkeletonUtilityBone utilBone;
protected SkeletonUtility skeletonUtility;
protected virtual void OnEnable(){
utilBone = GetComponent<SkeletonUtilityBone>();
skeletonUtility = GetComponentInParent<SkeletonUtility>();
skeletonUtility.RegisterConstraint(this);
}
protected virtual void OnDisable(){
skeletonUtility.UnregisterConstraint(this);
}
public abstract void DoUpdate();
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 522dbfcc6c916df4396f14f35048d185
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,61 @@
using UnityEngine;
using System.Collections;
public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
public Transform[] eyes;
public float radius = 0.5f;
public Transform target;
public Vector3 targetPosition;
public float speed = 10;
Vector3[] origins;
Vector3 centerPoint;
protected override void OnEnable ()
{
if(!Application.isPlaying)
return;
base.OnEnable ();
Bounds centerBounds = new Bounds( eyes[0].localPosition, Vector3.zero );
origins = new Vector3[eyes.Length];
for(int i = 0; i < eyes.Length; i++){
origins[i] = eyes[i].localPosition;
centerBounds.Encapsulate( origins[i] );
}
centerPoint = centerBounds.center;
}
protected override void OnDisable ()
{
if(!Application.isPlaying)
return;
base.OnDisable ();
}
public override void DoUpdate ()
{
if(target != null)
targetPosition = target.position;
Vector3 goal = targetPosition;
Vector3 center = transform.TransformPoint(centerPoint);
Vector3 dir = goal - center;
if(dir.magnitude > 1)
dir.Normalize();
for(int i = 0; i < eyes.Length; i++){
center = transform.TransformPoint(origins[i]);
eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius), speed * Time.deltaTime);
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0d994c65b6daec64f80ae2ae04e9d999
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,58 @@
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
public LayerMask groundMask;
public bool use2D = true;
public float castDistance = 5f;
Vector3 rayOrigin;
Vector3 rayDir = new Vector3(0,-1,0);
float hitY;
protected override void OnEnable ()
{
base.OnEnable ();
}
protected override void OnDisable ()
{
base.OnDisable ();
}
public override void DoUpdate()
{
rayOrigin = transform.position + new Vector3(0,castDistance,0);
hitY = float.MinValue;
if(use2D){
RaycastHit2D hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance, groundMask);
if(hit.collider != null){
hitY = hit.point.y;
}
}
else{
RaycastHit hit;
if(Physics.Raycast( rayOrigin, rayDir, out hit, castDistance, groundMask)){
hitY = hit.point.y;
}
}
Vector3 v = transform.position;
v.y = Mathf.Clamp(v.y, hitY, float.MaxValue);
transform.position = v;
utilBone.bone.X = transform.localPosition.x;
utilBone.bone.Y = transform.localPosition.y;
}
void OnDrawGizmos(){
Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
Gizmos.DrawLine(rayOrigin, hitEnd);
Gizmos.color = Color.red;
Gizmos.DrawLine(hitEnd, clearEnd);
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3662334b99de5fe4396ab24e30c4fd12
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,81 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SkeletonUtilityKinematicShadow : MonoBehaviour {
public bool hideShadow = true;
Dictionary<Transform, Transform> shadowTable;
GameObject shadowRoot;
void Start(){
shadowRoot = (GameObject)Instantiate(gameObject);
if(hideShadow)
shadowRoot.hideFlags = HideFlags.HideInHierarchy;
shadowRoot.transform.parent = transform.root;
shadowTable = new Dictionary<Transform, Transform>();
Destroy(shadowRoot.GetComponent<SkeletonUtilityKinematicShadow>());
shadowRoot.transform.position = transform.position;
shadowRoot.transform.rotation = transform.rotation;
Vector3 scaleRef = transform.TransformPoint(Vector3.right);
float scale = Vector3.Distance(transform.position, scaleRef);
shadowRoot.transform.localScale = Vector3.one;
var shadowJoints = shadowRoot.GetComponentsInChildren<Joint>();
foreach(Joint j in shadowJoints){
j.connectedAnchor *= scale;
}
var joints = GetComponentsInChildren<Joint>();
foreach(var j in joints)
Destroy(j);
var rbs = GetComponentsInChildren<Rigidbody>();
foreach(var rb in rbs)
Destroy(rb);
var colliders = GetComponentsInChildren<Collider>();
foreach(var c in colliders)
Destroy(c);
//match by bone name
var shadowBones = shadowRoot.GetComponentsInChildren<SkeletonUtilityBone>();
var bones = GetComponentsInChildren<SkeletonUtilityBone>();
//build bone lookup
foreach(var b in bones){
if(b.gameObject == gameObject)
continue;
foreach(var sb in shadowBones){
if(sb.rigidbody == null)
continue;
if(sb.boneName == b.boneName){
shadowTable.Add( sb.transform, b.transform );
break;
}
}
}
foreach(var b in shadowBones)
Destroy(b);
}
void FixedUpdate(){
shadowRoot.rigidbody.MovePosition( transform.position );
shadowRoot.rigidbody.MoveRotation( transform.rotation );
foreach(var pair in shadowTable){
pair.Value.localPosition = pair.Key.localPosition;
pair.Value.localRotation = pair.Key.localRotation;
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cfeac06b8a6aa1645813700e3e4c0863
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,102 @@
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class SkeletonUtilitySubmeshRenderer : MonoBehaviour {
public Renderer parentRenderer;
[System.NonSerialized]
public Mesh mesh;
public int submeshIndex = 0;
public int sortingOrder = 0;
public int sortingLayerID = 0;
public Material hiddenPassMaterial;
Renderer cachedRenderer;
MeshFilter filter;
Material[] sharedMaterials;
MeshFilter parentFilter;
void Awake(){
cachedRenderer = renderer;
sharedMaterials = cachedRenderer.sharedMaterials;
filter = GetComponent<MeshFilter>();
if(parentRenderer != null)
Initialize( parentRenderer );
}
void OnEnable(){
parentRenderer = transform.parent.GetComponent<Renderer>();
parentRenderer.GetComponent<SkeletonRenderer>().OnReset += HandleSkeletonReset;
}
void OnDisable(){
parentRenderer.GetComponent<SkeletonRenderer>().OnReset -= HandleSkeletonReset;
}
void HandleSkeletonReset(SkeletonRenderer r){
if(parentRenderer != null)
Initialize(parentRenderer);
}
public void Initialize(Renderer parentRenderer){
this.parentRenderer = parentRenderer;
parentFilter = parentRenderer.GetComponent<MeshFilter>();
mesh = parentFilter.sharedMesh;
filter.sharedMesh = mesh;
Debug.Log("Mesh: " + mesh);
}
public void Update(){
if(mesh == null || mesh != parentFilter.sharedMesh){
mesh = parentFilter.sharedMesh;
filter.sharedMesh = mesh;
}
if(cachedRenderer == null)
cachedRenderer = renderer;
if(mesh == null || submeshIndex > mesh.subMeshCount - 1){
cachedRenderer.enabled = false;
return;
}
else{
renderer.enabled = true;
}
bool changed = false;
if(sharedMaterials.Length != parentRenderer.sharedMaterials.Length){
sharedMaterials = parentRenderer.sharedMaterials;
changed = true;
}
for(int i = 0; i < renderer.sharedMaterials.Length; i++){
if(i == submeshIndex)
continue;
if(sharedMaterials[i] != hiddenPassMaterial){
sharedMaterials[i] = hiddenPassMaterial;
changed = true;
}
}
if(sharedMaterials[submeshIndex] != parentRenderer.sharedMaterials[submeshIndex]){
sharedMaterials[submeshIndex] = parentRenderer.sharedMaterials[submeshIndex];
changed = true;
}
if(changed){
cachedRenderer.sharedMaterials = sharedMaterials;
}
cachedRenderer.sortingLayerID = sortingLayerID;
cachedRenderer.sortingOrder = sortingOrder;
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7820c1c2b0e52c6408de899d6939996e
MonoImporter:
serializedVersion: 2
defaultReferences:
- parentRenderer: {instanceID: 0}
- mesh: {instanceID: 0}
- hiddenPassMaterial: {fileID: 2100000, guid: 43227e5adadc6f24bb4bf74b92a56fb4,
type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData: