Browse Source

[unity] Allow SkeletonGraphic runtime atlas.

pharan 8 years ago
parent
commit
9cd0167a03

+ 178 - 1
spine-unity/Assets/Examples/Other Examples/Mix and Match.unity

@@ -375,6 +375,80 @@ Transform:
   m_Father: {fileID: 0}
   m_RootOrder: 2
   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
 GameObject:
   m_ObjectHideFlags: 0
@@ -550,7 +624,7 @@ RectTransform:
   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: 608, y: -253}
+  m_AnchoredPosition: {x: -74, y: 416}
   m_SizeDelta: {x: 661, y: 181}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!114 &1262477662
@@ -670,6 +744,7 @@ RectTransform:
   - {fileID: 1620489274}
   - {fileID: 952321880}
   - {fileID: 1262477661}
+  - {fileID: 1958410249}
   m_Father: {fileID: 0}
   m_RootOrder: 1
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -1018,6 +1093,108 @@ Material:
     - _node_3476: 0
     m_Colors:
     - _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
 Texture2D:
   m_ObjectHideFlags: 0

+ 134 - 0
spine-unity/Assets/Examples/Scripts/MixAndMatchGraphic.cs

@@ -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();
+		}
+	}
+}

+ 12 - 0
spine-unity/Assets/Examples/Scripts/MixAndMatchGraphic.cs.meta

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

+ 2 - 0
spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/SkeletonGraphic.cs

@@ -122,9 +122,11 @@ namespace Spine.Unity {
 
 		#region Internals
 		// This is used by the UI system to determine what to put in the MaterialPropertyBlock.
+		public Texture OverrideTexture { get; set; }
 		public override Texture mainTexture {
 			get { 
 				// Fail loudly when incorrectly set up.
+				if (OverrideTexture != null) return OverrideTexture;
 				return skeletonDataAsset == null ? null : skeletonDataAsset.atlasAssets[0].materials[0].mainTexture;
 			}
 		}