Merge remote-tracking branch 'origin/3.6-beta' into 3.6-beta

This commit is contained in:
NathanSweet 2017-06-12 02:49:03 +02:00
commit ef6f181267
8 changed files with 349 additions and 4 deletions

View File

@ -743,7 +743,7 @@ namespace Spine {
public VertexAttachment Attachment { get { return attachment; } set { attachment = value; } } public VertexAttachment Attachment { get { return attachment; } set { attachment = value; } }
override public int PropertyId { override public int PropertyId {
get { return ((int)TimelineType.Deform << 24) + slotIndex; } get { return ((int)TimelineType.Deform << 24) + attachment.id + slotIndex; }
} }
public DeformTimeline (int frameCount) public DeformTimeline (int frameCount)

View File

@ -33,10 +33,15 @@ using System;
namespace Spine { namespace Spine {
/// <summary>>An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices.</summary> /// <summary>>An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices.</summary>
public class VertexAttachment : Attachment { public class VertexAttachment : Attachment {
static int nextID = 0;
internal readonly int id = (nextID++ & 65535) << 11;
internal int[] bones; internal int[] bones;
internal float[] vertices; internal float[] vertices;
internal int worldVerticesLength; internal int worldVerticesLength;
/// <summary>Gets a unique ID for this attachment.</summary>
public int Id { get { return id; } }
public int[] Bones { get { return bones; } set { bones = value; } } public int[] Bones { get { return bones; } set { bones = value; } }
public float[] Vertices { get { return vertices; } set { vertices = value; } } public float[] Vertices { get { return vertices; } set { vertices = value; } }
public int WorldVerticesLength { get { return worldVerticesLength; } set { worldVerticesLength = value; } } public int WorldVerticesLength { get { return worldVerticesLength; } set { worldVerticesLength = value; } }

View File

@ -375,6 +375,80 @@ Transform:
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 2 m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &694242025
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 694242026}
- component: {fileID: 694242028}
- component: {fileID: 694242027}
m_Layer: 5
m_Name: Text (6)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &694242026
RectTransform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 694242025}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.2500063, y: 1.2500063, z: 1.2500063}
m_Children: []
m_Father: {fileID: 1958410249}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.7178893, y: 0.5}
m_AnchoredPosition: {x: 285, y: -70}
m_SizeDelta: {x: 40, y: 30}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &694242027
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 694242025}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 24
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 0
m_MaxSize: 55
m_Alignment: 4
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 1
m_VerticalOverflow: 1
m_LineSpacing: 1
m_Text: SkeletonGraphic Equipped
--- !u!222 &694242028
CanvasRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 694242025}
--- !u!1 &952321879 --- !u!1 &952321879
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -550,7 +624,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 608, y: -253} m_AnchoredPosition: {x: -74, y: 416}
m_SizeDelta: {x: 661, y: 181} m_SizeDelta: {x: 661, y: 181}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1262477662 --- !u!114 &1262477662
@ -670,6 +744,7 @@ RectTransform:
- {fileID: 1620489274} - {fileID: 1620489274}
- {fileID: 952321880} - {fileID: 952321880}
- {fileID: 1262477661} - {fileID: 1262477661}
- {fileID: 1958410249}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 1 m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -1018,6 +1093,108 @@ Material:
- _node_3476: 0 - _node_3476: 0
m_Colors: m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1}
--- !u!1 &1958410248
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 1958410249}
- component: {fileID: 1958410252}
- component: {fileID: 1958410251}
- component: {fileID: 1958410250}
m_Layer: 0
m_Name: SkeletonGraphic (spineboy-unity)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1958410249
RectTransform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1958410248}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.8, y: 0.8, z: 0.8}
m_Children:
- {fileID: 694242026}
m_Father: {fileID: 1442798444}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 538, y: -522}
m_SizeDelta: {x: 551, y: 678}
m_Pivot: {x: 0.5294104, y: 0.0076879906}
--- !u!114 &1958410250
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1958410248}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8e24c5293ec0b444eba7a2680caa925f, type: 3}
m_Name:
m_EditorClassIdentifier:
baseSkinName: base
sourceMaterial: {fileID: 2100000, guid: 1455e88fdb81ccc45bdeaedd657bad4d, type: 2}
visorSprite: {fileID: 21300000, guid: 4f554405f8f06164db0773d689da243c, type: 3}
visorSlot: goggles
visorKey: goggles
gunSprite: {fileID: 21300000, guid: 02c4cbcce432ae74bb2d965060e64d29, type: 3}
gunSlot: gun
gunKey: gun
repack: 1
runtimeAtlas: {fileID: 0}
runtimeMaterial: {fileID: 0}
--- !u!114 &1958410251
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1958410248}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d85b887af7e6c3f45a2e2d2920d641bc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 2100000, guid: b66cf7a186d13054989b33a5c90044e4, type: 2}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
skeletonDataAsset: {fileID: 11400000, guid: a467507a4ffb1d542a558739b2fede77, type: 2}
initialSkinName: base
initialFlipX: 0
initialFlipY: 0
startingAnimation: run
startingLoop: 1
timeScale: 1
freeze: 0
unscaledTime: 0
meshGenerator:
settings:
useClipping: 1
zSpacing: 0
pmaVertexColors: 1
tintBlack: 0
calculateTangents: 0
addNormals: 0
immutableTriangles: 0
--- !u!222 &1958410252
CanvasRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1958410248}
--- !u!28 &1983722037 --- !u!28 &1983722037
Texture2D: Texture2D:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -0,0 +1,134 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable, and
* non-transferable license to use, install, execute, and perform the Spine
* Runtimes software and derivative works solely for personal or internal
* use. Without the written permission of Esoteric Software (see Section 2 of
* the Spine Software License Agreement), you may not (a) modify, translate,
* adapt, or develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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 SOFTWARE 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 THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
using UnityEngine;
using Spine.Unity.Modules.AttachmentTools;
namespace Spine.Unity.Examples {
// This is an example script that shows you how to change images on your skeleton using UnityEngine.Sprites.
public class MixAndMatchGraphic : MonoBehaviour {
#region Inspector
[SpineSkin]
public string baseSkinName = "base";
public Material sourceMaterial; // This will be used as the basis for shader and material property settings.
[Header("Visor")]
public Sprite visorSprite;
[SpineSlot] public string visorSlot;
[SpineAttachment(slotField:"visorSlot", skinField:"baseSkinName")] public string visorKey = "goggles";
[Header("Gun")]
public Sprite gunSprite;
[SpineSlot] public string gunSlot;
[SpineAttachment(slotField:"gunSlot", skinField:"baseSkinName")] public string gunKey = "gun";
[Header("Runtime Repack Required!!")]
public bool repack = true;
[Header("Do not assign")]
public Texture2D runtimeAtlas;
public Material runtimeMaterial;
#endregion
Skin customSkin;
void OnValidate () {
if (sourceMaterial == null) {
var skeletonGraphic = GetComponent<SkeletonGraphic>();
if (skeletonGraphic != null)
sourceMaterial = skeletonGraphic.SkeletonDataAsset.atlasAssets[0].materials[0];
}
}
void Start () {
Apply();
}
void Apply () {
var skeletonGraphic = GetComponent<SkeletonGraphic>();
var skeleton = skeletonGraphic.Skeleton;
// STEP 0: PREPARE SKINS
// Let's prepare a new skin to be our custom skin with equips/customizations. We get a clone so our original skins are unaffected.
customSkin = customSkin ?? new Skin("custom skin"); // This requires that all customizations are done with skin placeholders defined in Spine.
//customSkin = customSkin ?? skeleton.UnshareSkin(true, false, skeletonAnimation.AnimationState); // use this if you are not customizing on the default skin and don't plan to remove
// Next let's
var baseSkin = skeleton.Data.FindSkin(baseSkinName);
// STEP 1: "EQUIP" ITEMS USING SPRITES
// STEP 1.1 Find the original attachment.
// Step 1.2 Get a clone of the original attachment.
// Step 1.3 Apply the Sprite image to it.
// Step 1.4 Add the remapped clone to the new custom skin.
// Let's do this for the visor.
int visorSlotIndex = skeleton.FindSlotIndex(visorSlot); // You can access GetAttachment and SetAttachment via string, but caching the slotIndex is faster.
Attachment baseAttachment = baseSkin.GetAttachment(visorSlotIndex, visorKey); // STEP 1.1
Attachment newAttachment = baseAttachment.GetRemappedClone(visorSprite, sourceMaterial); // STEP 1.2 - 1.3
customSkin.SetAttachment(visorSlotIndex, visorKey, newAttachment); // STEP 1.4
// And now for the gun.
int gunSlotIndex = skeleton.FindSlotIndex(gunSlot);
Attachment baseGun = baseSkin.GetAttachment(gunSlotIndex, gunKey); // STEP 1.1
Attachment newGun = baseGun.GetRemappedClone(gunSprite, sourceMaterial); // STEP 1.2 - 1.3
if (newGun != null) customSkin.SetAttachment(gunSlotIndex, gunKey, newGun); // STEP 1.4
// customSkin.RemoveAttachment(gunSlotIndex, gunKey); // To remove an item.
// customSkin.Clear()
// Use skin.Clear() To remove all customizations.
// Customizations will fall back to the value in the default skin if it was defined there.
// To prevent fallback from happening, make sure the key is not defined in the default skin.
// STEP 3: APPLY AND CLEAN UP.
// Recommended: REPACK THE CUSTOM SKIN TO MINIMIZE DRAW CALLS
// Repacking requires that you set all source textures/sprites/atlases to be Read/Write enabled in the inspector.
// Combine all the attachment sources into one skin. Usually this means the default skin and the custom skin.
// call Skin.GetRepackedSkin to get a cloned skin with cloned attachments that all use one texture.
// Under the hood, this relies on
if (repack) {
var repackedSkin = new Skin("repacked skin");
repackedSkin.Append(skeleton.Data.DefaultSkin);
repackedSkin.Append(customSkin);
repackedSkin = repackedSkin.GetRepackedSkin("repacked skin", sourceMaterial, out runtimeMaterial, out runtimeAtlas);
skeleton.SetSkin(repackedSkin);
} else {
skeleton.SetSkin(customSkin);
}
skeleton.SetSlotsToSetupPose();
skeletonGraphic.Update(0);
skeletonGraphic.OverrideTexture = runtimeAtlas;
Resources.UnloadUnusedAssets();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8e24c5293ec0b444eba7a2680caa925f
timeCreated: 1480089275
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -73,6 +73,8 @@ namespace Spine.Unity {
public int SlotCount { get { return endSlot - startSlot; } } public int SlotCount { get { return endSlot - startSlot; } }
} }
public delegate void MeshGeneratorDelegate (MeshGenerator meshGenerator);
[System.Serializable] [System.Serializable]
public class MeshGenerator { public class MeshGenerator {
public Settings settings = Settings.Default; public Settings settings = Settings.Default;
@ -115,6 +117,10 @@ namespace Spine.Unity {
[NonSerialized] readonly ExposedList<Color32> colorBuffer = new ExposedList<Color32>(4); [NonSerialized] readonly ExposedList<Color32> colorBuffer = new ExposedList<Color32>(4);
[NonSerialized] readonly ExposedList<ExposedList<int>> submeshes = new ExposedList<ExposedList<int>> { new ExposedList<int>(6) }; // start with 1 submesh. [NonSerialized] readonly ExposedList<ExposedList<int>> submeshes = new ExposedList<ExposedList<int>> { new ExposedList<int>(6) }; // start with 1 submesh.
public Vector3[] VertexBuffer { get { return this.vertexBuffer.Items; } }
public Vector2[] UVBuffer { get { return this.uvBuffer.Items; } }
public Color32[] ColorBuffer { get { return this.colorBuffer.Items; } }
[NonSerialized] Vector2 meshBoundsMin, meshBoundsMax; [NonSerialized] Vector2 meshBoundsMin, meshBoundsMax;
[NonSerialized] float meshBoundsThickness; [NonSerialized] float meshBoundsThickness;
[NonSerialized] int submeshIndex = 0; [NonSerialized] int submeshIndex = 0;

View File

@ -122,9 +122,11 @@ namespace Spine.Unity {
#region Internals #region Internals
// This is used by the UI system to determine what to put in the MaterialPropertyBlock. // This is used by the UI system to determine what to put in the MaterialPropertyBlock.
public Texture OverrideTexture { get; set; }
public override Texture mainTexture { public override Texture mainTexture {
get { get {
// Fail loudly when incorrectly set up. // Fail loudly when incorrectly set up.
if (OverrideTexture != null) return OverrideTexture;
return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].materials[0].mainTexture; return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
} }
} }
@ -197,6 +199,9 @@ namespace Spine.Unity {
public event UpdateBonesDelegate UpdateWorld; public event UpdateBonesDelegate UpdateWorld;
public event UpdateBonesDelegate UpdateComplete; public event UpdateBonesDelegate UpdateComplete;
/// <summary> Occurs after the vertex data populated every frame, before the vertices are pushed into the mesh.</summary>
public event Spine.Unity.MeshGeneratorDelegate OnPostProcessVertices;
public void Clear () { public void Clear () {
skeleton = null; skeleton = null;
canvasRenderer.Clear(); canvasRenderer.Clear();
@ -267,6 +272,7 @@ namespace Spine.Unity {
} }
if (canvas != null) meshGenerator.ScaleVertexData(canvas.referencePixelsPerUnit); if (canvas != null) meshGenerator.ScaleVertexData(canvas.referencePixelsPerUnit);
if (OnPostProcessVertices != null) OnPostProcessVertices.Invoke(this.meshGenerator);
var mesh = smartMesh.mesh; var mesh = smartMesh.mesh;
meshGenerator.FillVertexData(mesh); meshGenerator.FillVertexData(mesh);

View File

@ -41,7 +41,10 @@ namespace Spine.Unity {
public class SkeletonRenderer : MonoBehaviour, ISkeletonComponent { public class SkeletonRenderer : MonoBehaviour, ISkeletonComponent {
public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer); public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer);
public SkeletonRendererDelegate OnRebuild; public event SkeletonRendererDelegate OnRebuild;
/// <summary> Occurs after the vertex data is populated every frame, before the vertices are pushed into the mesh.</summary>
public event Spine.Unity.MeshGeneratorDelegate OnPostProcessVertices;
public SkeletonDataAsset skeletonDataAsset; public SkeletonDataAsset skeletonDataAsset;
public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } } // ISkeletonComponent public SkeletonDataAsset SkeletonDataAsset { get { return skeletonDataAsset; } } // ISkeletonComponent
@ -280,6 +283,8 @@ namespace Spine.Unity {
meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles); meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
} }
if (OnPostProcessVertices != null) OnPostProcessVertices.Invoke(this.meshGenerator);
// STEP 3. Move the mesh data into a UnityEngine.Mesh =========================================================================== // STEP 3. Move the mesh data into a UnityEngine.Mesh ===========================================================================
var currentMesh = currentSmartMesh.mesh; var currentMesh = currentSmartMesh.mesh;
meshGenerator.FillVertexData(currentMesh); meshGenerator.FillVertexData(currentMesh);