mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 07:14:55 +08:00
[unity] Added native support for slot blend modes Additive, Multiply and Screen with automatic assignment at newly imported skeleton assets. Added upgrade functionality. Closes #1822, closes #1559.
This commit is contained in:
parent
110581abea
commit
752e72eb8f
@ -250,6 +250,7 @@
|
||||
* `SkeletonRenderer` components now provide an additional update mode `Only Event Timelines` at the `Update When Invisible` property. This mode saves additional timeline updates compared to update mode `Everything Except Mesh`.
|
||||
* Now all URP (Universal Render Pipeline) and LWRP (Lightweight Render Pipeline) shaders support SRP (Scriptable Render Pipeline) batching. See [Unity SRPBatcher documentation pages](https://docs.unity3d.com/Manual/SRPBatcher.html) for additional information.
|
||||
* Sprite shaders now provide four `Diffuse Ramp` modes as an Inspector Material parameter: `Hard`, `Soft`, `Old Hard` and `Old Soft`. In spine-unity 3.8 it defaults to `Old Hard` to keep the behaviour of existing projects unchanged. Note that `Old Hard` and `Old Soft` ramp versions were using only the right half of the ramp texture, and additionally multiplying the light intensity by 2, both leading to brighter lighting than without a ramp texture active. The new ramp modes `Hard` and `Soft` use the full ramp texture and do not modify light intensity, being consistent with lighting without a ramp texture active.
|
||||
* Added **native support for slot blend modes** `Additive`, `Multiply` and `Screen` with automatic assignment at newly imported skeleton assets. `BlendModeMaterialAssets` are now obsolete and replaced by the native properties at `SkeletonDataAsset`. The `SkeletonDataAsset` Inspector provides a new `Blend Modes - Upgrade` button to upgrade an obsolete `BlendModeMaterialAsset` to the native blend modes properties. This upgrade will be performed automatically on imported and re-imported assets in Unity 2020.1 and newer to prevent reported `BlendModeMaterialAsset` issues in these Unity versions. spine-unity 4.0 and newer will automatically perform this upgrade regardless of the Unity version.
|
||||
|
||||
* **Changes of default values**
|
||||
* `SkeletonMecanim`'s `Layer Mix Mode` now defaults to `MixMode.MixNext` instead of `MixMode.MixAlways`.
|
||||
|
||||
@ -56,6 +56,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
SerializedProperty atlasAssets, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
|
||||
SerializedProperty skeletonDataModifiers;
|
||||
SerializedProperty blendModeMaterials;
|
||||
#if SPINE_TK2D
|
||||
SerializedProperty spriteCollection;
|
||||
#endif
|
||||
@ -114,6 +115,7 @@ namespace Spine.Unity.Editor {
|
||||
defaultMix = serializedObject.FindProperty("defaultMix");
|
||||
|
||||
skeletonDataModifiers = serializedObject.FindProperty("skeletonDataModifiers");
|
||||
blendModeMaterials = serializedObject.FindProperty("blendModeMaterials");
|
||||
|
||||
#if SPINE_SKELETON_MECANIM
|
||||
controller = serializedObject.FindProperty("controller");
|
||||
@ -125,7 +127,7 @@ namespace Spine.Unity.Editor {
|
||||
#else
|
||||
// Analysis disable once ConvertIfToOrExpression
|
||||
if (newAtlasAssets) atlasAssets.isExpanded = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This handles the case where the managed editor assembly is unloaded before recompilation when code changes.
|
||||
AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
|
||||
@ -286,6 +288,8 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUILayout.DelayedFloatField(scale); //EditorGUILayout.PropertyField(scale);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(skeletonDataModifiers, true);
|
||||
|
||||
DrawBlendModeMaterialProperties();
|
||||
}
|
||||
|
||||
// Texture source field.
|
||||
@ -311,6 +315,27 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
}
|
||||
|
||||
void DrawBlendModeMaterialProperties () {
|
||||
if (skeletonDataModifiers.arraySize > 0) {
|
||||
EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
|
||||
EditorGUILayout.PrefixLabel("Blend Modes");
|
||||
if (GUILayout.Button(new GUIContent("Upgrade", "Upgrade BlendModeMaterialAsset to built-in BlendModeMaterials."), EditorStyles.miniButton, GUILayout.Width(65f))) {
|
||||
foreach (SkeletonDataAsset skeletonData in targets) {
|
||||
BlendModeMaterialsUtility.UpgradeBlendModeMaterials(skeletonData);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(blendModeMaterials, true);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
foreach (SkeletonDataAsset skeletonData in targets) {
|
||||
BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSkeletonDataFields () {
|
||||
using (new EditorGUILayout.HorizontalScope()) {
|
||||
EditorGUILayout.LabelField("SkeletonData", EditorStyles.boldLabel);
|
||||
@ -331,6 +356,8 @@ namespace Spine.Unity.Editor {
|
||||
EditorGUILayout.DelayedFloatField(scale); //EditorGUILayout.PropertyField(scale);
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(skeletonDataModifiers, true);
|
||||
|
||||
DrawBlendModeMaterialProperties();
|
||||
}
|
||||
|
||||
void DrawAtlasAssetsFields () {
|
||||
|
||||
@ -427,6 +427,8 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
|
||||
|
||||
string currentHash = skeletonData != null ? skeletonData.Hash : null;
|
||||
|
||||
#if SPINE_SKELETONMECANIM
|
||||
@ -887,6 +889,7 @@ namespace Spine.Unity.Editor {
|
||||
skeletonDataAsset.skeletonJSON = spineJson;
|
||||
skeletonDataAsset.defaultMix = SpineEditorUtilities.Preferences.defaultMix;
|
||||
skeletonDataAsset.scale = SpineEditorUtilities.Preferences.defaultScale;
|
||||
skeletonDataAsset.blendModeMaterials.applyAdditiveMaterial = !SpineEditorUtilities.Preferences.UsesPMAWorkflow;
|
||||
}
|
||||
|
||||
AssetDatabase.CreateAsset(skeletonDataAsset, filePath);
|
||||
@ -894,7 +897,8 @@ namespace Spine.Unity.Editor {
|
||||
} else {
|
||||
skeletonDataAsset.atlasAssets = atlasAssets;
|
||||
skeletonDataAsset.Clear();
|
||||
skeletonDataAsset.GetSkeletonData(true);
|
||||
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
BlendModeMaterialsUtility.UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData);
|
||||
}
|
||||
|
||||
return skeletonDataAsset;
|
||||
|
||||
@ -0,0 +1,282 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2020, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
#define UPGRADE_ALL_BLEND_MODE_MATERIALS
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
public class BlendModeMaterialsUtility {
|
||||
|
||||
public const string MATERIAL_SUFFIX_MULTIPLY = "-Multiply";
|
||||
public const string MATERIAL_SUFFIX_SCREEN = "-Screen";
|
||||
public const string MATERIAL_SUFFIX_ADDITIVE = "-Additive";
|
||||
|
||||
#if UPGRADE_ALL_BLEND_MODE_MATERIALS
|
||||
public const bool ShallUpgradeBlendModeMaterials = true;
|
||||
#else
|
||||
public const bool ShallUpgradeBlendModeMaterials = false;
|
||||
#endif
|
||||
|
||||
protected class TemplateMaterials {
|
||||
public Material multiplyTemplate;
|
||||
public Material screenTemplate;
|
||||
public Material additiveTemplate;
|
||||
};
|
||||
|
||||
public static void UpgradeBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
|
||||
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (skeletonData == null)
|
||||
return;
|
||||
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, true);
|
||||
}
|
||||
|
||||
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset) {
|
||||
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (skeletonData == null)
|
||||
return;
|
||||
UpdateBlendModeMaterials(skeletonDataAsset, ref skeletonData, false);
|
||||
}
|
||||
|
||||
public static void UpdateBlendModeMaterials (SkeletonDataAsset skeletonDataAsset, ref SkeletonData skeletonData,
|
||||
bool upgradeFromModifierAssets = ShallUpgradeBlendModeMaterials) {
|
||||
|
||||
TemplateMaterials templateMaterials = new TemplateMaterials();
|
||||
bool anyMaterialsChanged = ClearUndesiredMaterialEntries(skeletonDataAsset);
|
||||
|
||||
var blendModesModifierAsset = FindBlendModeMaterialsModifierAsset(skeletonDataAsset);
|
||||
if (blendModesModifierAsset) {
|
||||
if (upgradeFromModifierAssets) {
|
||||
TransferSettingsFromModifierAsset(blendModesModifierAsset,
|
||||
skeletonDataAsset, templateMaterials);
|
||||
UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!UpdateBlendmodeMaterialsRequiredState(skeletonDataAsset, skeletonData))
|
||||
return;
|
||||
AssignPreferencesTemplateMaterials(templateMaterials);
|
||||
}
|
||||
bool success = CreateAndAssignMaterials(skeletonDataAsset, templateMaterials, ref anyMaterialsChanged);
|
||||
if (success) {
|
||||
if (blendModesModifierAsset != null) {
|
||||
RemoveObsoleteModifierAsset(blendModesModifierAsset, skeletonDataAsset);
|
||||
}
|
||||
}
|
||||
|
||||
skeletonDataAsset.Clear();
|
||||
skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (anyMaterialsChanged)
|
||||
ReloadSceneSkeletons(skeletonDataAsset);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
protected static bool ClearUndesiredMaterialEntries (SkeletonDataAsset skeletonDataAsset) {
|
||||
Predicate<BlendModeMaterials.ReplacementMaterial> ifMaterialMissing = r => r.material == null;
|
||||
|
||||
bool anyMaterialsChanged = false;
|
||||
if (!skeletonDataAsset.blendModeMaterials.applyAdditiveMaterial) {
|
||||
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.Count > 0;
|
||||
skeletonDataAsset.blendModeMaterials.additiveMaterials.Clear();
|
||||
}
|
||||
else
|
||||
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.additiveMaterials.RemoveAll(ifMaterialMissing) != 0;
|
||||
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.multiplyMaterials.RemoveAll(ifMaterialMissing) != 0;
|
||||
anyMaterialsChanged |= skeletonDataAsset.blendModeMaterials.screenMaterials.RemoveAll(ifMaterialMissing) != 0;
|
||||
return anyMaterialsChanged;
|
||||
}
|
||||
|
||||
protected static BlendModeMaterialsAsset FindBlendModeMaterialsModifierAsset (SkeletonDataAsset skeletonDataAsset) {
|
||||
foreach (var modifierAsset in skeletonDataAsset.skeletonDataModifiers) {
|
||||
if (modifierAsset is BlendModeMaterialsAsset)
|
||||
return (BlendModeMaterialsAsset)modifierAsset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static bool UpdateBlendmodeMaterialsRequiredState (SkeletonDataAsset skeletonDataAsset, SkeletonData skeletonData) {
|
||||
return skeletonDataAsset.blendModeMaterials.UpdateBlendmodeMaterialsRequiredState(skeletonData);
|
||||
}
|
||||
|
||||
protected static void TransferSettingsFromModifierAsset (BlendModeMaterialsAsset modifierAsset,
|
||||
SkeletonDataAsset skeletonDataAsset, TemplateMaterials templateMaterials) {
|
||||
|
||||
skeletonDataAsset.blendModeMaterials.TransferSettingsFrom(modifierAsset);
|
||||
|
||||
templateMaterials.multiplyTemplate = modifierAsset.multiplyMaterialTemplate;
|
||||
templateMaterials.screenTemplate = modifierAsset.screenMaterialTemplate;
|
||||
templateMaterials.additiveTemplate = modifierAsset.additiveMaterialTemplate;
|
||||
}
|
||||
|
||||
protected static void RemoveObsoleteModifierAsset (BlendModeMaterialsAsset modifierAsset,
|
||||
SkeletonDataAsset skeletonDataAsset) {
|
||||
|
||||
skeletonDataAsset.skeletonDataModifiers.Remove(modifierAsset);
|
||||
Debug.Log(string.Format("BlendModeMaterialsAsset upgraded to built-in BlendModeMaterials at SkeletonDataAsset '{0}'.",
|
||||
skeletonDataAsset.name), skeletonDataAsset);
|
||||
EditorUtility.SetDirty(skeletonDataAsset);
|
||||
}
|
||||
|
||||
protected static void AssignPreferencesTemplateMaterials (TemplateMaterials templateMaterials) {
|
||||
|
||||
templateMaterials.multiplyTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialMultiply;
|
||||
templateMaterials.screenTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialScreen;
|
||||
templateMaterials.additiveTemplate = SpineEditorUtilities.Preferences.BlendModeMaterialAdditive;
|
||||
}
|
||||
|
||||
protected static bool CreateAndAssignMaterials (SkeletonDataAsset skeletonDataAsset,
|
||||
TemplateMaterials templateMaterials, ref bool anyReplacementMaterialsChanged) {
|
||||
|
||||
bool anyCreationFailed = false;
|
||||
var blendModeMaterials = skeletonDataAsset.blendModeMaterials;
|
||||
bool applyAdditiveMaterial = blendModeMaterials.applyAdditiveMaterial;
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
|
||||
skeletonDataAsset.Clear();
|
||||
skeletonDataAsset.isUpgradingBlendModeMaterials = true;
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.BlendMode == BlendMode.Normal) continue;
|
||||
if (!applyAdditiveMaterial && slot.BlendMode == BlendMode.Additive) continue;
|
||||
|
||||
List<BlendModeMaterials.ReplacementMaterial> replacementMaterials = null;
|
||||
Material materialTemplate = null;
|
||||
string materialSuffix = null;
|
||||
switch (slot.BlendMode) {
|
||||
case BlendMode.Multiply:
|
||||
replacementMaterials = blendModeMaterials.multiplyMaterials;
|
||||
materialTemplate = templateMaterials.multiplyTemplate;
|
||||
materialSuffix = MATERIAL_SUFFIX_MULTIPLY;
|
||||
break;
|
||||
case BlendMode.Screen:
|
||||
replacementMaterials = blendModeMaterials.screenMaterials;
|
||||
materialTemplate = templateMaterials.screenTemplate;
|
||||
materialSuffix = MATERIAL_SUFFIX_SCREEN;
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
replacementMaterials = blendModeMaterials.additiveMaterials;
|
||||
materialTemplate = templateMaterials.additiveTemplate;
|
||||
materialSuffix = MATERIAL_SUFFIX_ADDITIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
skinEntries.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
var renderableAttachment = entry.Attachment as IHasRendererObject;
|
||||
if (renderableAttachment != null) {
|
||||
var originalRegion = (AtlasRegion)renderableAttachment.RendererObject;
|
||||
bool replacementExists = replacementMaterials.Exists(
|
||||
replacement => replacement.pageName == originalRegion.page.name);
|
||||
if (!replacementExists) {
|
||||
bool createdNewMaterial;
|
||||
var replacement = CreateOrLoadReplacementMaterial(originalRegion, materialTemplate, materialSuffix, out createdNewMaterial);
|
||||
if (replacement != null) {
|
||||
replacementMaterials.Add(replacement);
|
||||
anyReplacementMaterialsChanged = true;
|
||||
if (createdNewMaterial) {
|
||||
Debug.Log(string.Format("Created blend mode Material '{0}' for SkeletonDataAsset '{1}'.",
|
||||
replacement.material.name, skeletonDataAsset), replacement.material);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.LogError(string.Format("Failed creating blend mode Material for SkeletonDataAsset '{0}',"+
|
||||
" atlas page '{1}', template '{2}'.",
|
||||
skeletonDataAsset.name, originalRegion.page.name, materialTemplate.name),
|
||||
skeletonDataAsset);
|
||||
anyCreationFailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skeletonDataAsset.isUpgradingBlendModeMaterials = false;
|
||||
EditorUtility.SetDirty(skeletonDataAsset);
|
||||
return !anyCreationFailed;
|
||||
}
|
||||
|
||||
protected static string GetBlendModeMaterialPath(AtlasPage originalPage, string materialSuffix) {
|
||||
var originalMaterial = originalPage.rendererObject as Material;
|
||||
var originalPath = AssetDatabase.GetAssetPath(originalMaterial);
|
||||
return originalPath.Replace(".mat", materialSuffix + ".mat");
|
||||
}
|
||||
|
||||
protected static BlendModeMaterials.ReplacementMaterial CreateOrLoadReplacementMaterial (
|
||||
AtlasRegion originalRegion, Material materialTemplate, string materialSuffix, out bool createdNewMaterial) {
|
||||
|
||||
createdNewMaterial = false;
|
||||
var newReplacement = new BlendModeMaterials.ReplacementMaterial();
|
||||
var originalPage = originalRegion.page;
|
||||
var originalMaterial = originalPage.rendererObject as Material;
|
||||
var blendMaterialPath = GetBlendModeMaterialPath(originalPage, materialSuffix);
|
||||
|
||||
newReplacement.pageName = originalPage.name;
|
||||
if (File.Exists(blendMaterialPath)) {
|
||||
newReplacement.material = AssetDatabase.LoadAssetAtPath<Material>(blendMaterialPath);
|
||||
}
|
||||
else {
|
||||
var blendModeMaterial = new Material(materialTemplate) {
|
||||
name = originalMaterial.name + " " + materialTemplate.name,
|
||||
mainTexture = originalMaterial.mainTexture
|
||||
};
|
||||
newReplacement.material = blendModeMaterial;
|
||||
|
||||
AssetDatabase.CreateAsset(blendModeMaterial, blendMaterialPath);
|
||||
EditorUtility.SetDirty(blendModeMaterial);
|
||||
createdNewMaterial = true;
|
||||
}
|
||||
|
||||
if (newReplacement.material)
|
||||
return newReplacement;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void ReloadSceneSkeletons (SkeletonDataAsset skeletonDataAsset) {
|
||||
if (SpineEditorUtilities.Preferences.autoReloadSceneSkeletons)
|
||||
SpineEditorUtilities.DataReloadHandler.ReloadSceneSkeletonComponents(skeletonDataAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8094f8aedb33b7744b109c2c1294d37a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -124,6 +124,32 @@ namespace Spine.Unity.Editor {
|
||||
const string TEXTURE_SETTINGS_REFERENCE_KEY = "SPINE_TEXTURE_SETTINGS_REFERENCE";
|
||||
public static string textureSettingsReference = SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE;
|
||||
|
||||
public static bool UsesPMAWorkflow {
|
||||
get {
|
||||
return SpinePreferences.IsPMAWorkflow(textureSettingsReference);
|
||||
}
|
||||
}
|
||||
|
||||
const string BLEND_MODE_MATERIAL_MULTIPLY_KEY = "SPINE_BLENDMODE_MATERIAL_MULTIPLY";
|
||||
const string BLEND_MODE_MATERIAL_SCREEN_KEY = "SPINE_BLENDMODE_MATERIAL_SCREEN";
|
||||
const string BLEND_MODE_MATERIAL_ADDITIVE_KEY = "SPINE_BLENDMODE_MATERIAL_ADDITIVE";
|
||||
public static string blendModeMaterialMultiply = "";
|
||||
public static string blendModeMaterialScreen = "";
|
||||
public static string blendModeMaterialAdditive = "";
|
||||
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL;
|
||||
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_SCREEN_MATERIAL;
|
||||
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = SpinePreferences.DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL;
|
||||
|
||||
public static Material BlendModeMaterialMultiply {
|
||||
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialMultiply); }
|
||||
}
|
||||
public static Material BlendModeMaterialScreen {
|
||||
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialScreen); }
|
||||
}
|
||||
public static Material BlendModeMaterialAdditive {
|
||||
get { return AssetDatabase.LoadAssetAtPath<Material>(blendModeMaterialAdditive); }
|
||||
}
|
||||
|
||||
const string ATLASTXT_WARNING_KEY = "SPINE_ATLASTXT_WARNING";
|
||||
public static bool atlasTxtImportWarning = SpinePreferences.DEFAULT_ATLASTXT_WARNING;
|
||||
|
||||
@ -161,6 +187,9 @@ namespace Spine.Unity.Editor {
|
||||
showHierarchyIcons = EditorPrefs.GetBool(SHOW_HIERARCHY_ICONS_KEY, SpinePreferences.DEFAULT_SHOW_HIERARCHY_ICONS);
|
||||
setTextureImporterSettings = EditorPrefs.GetBool(SET_TEXTUREIMPORTER_SETTINGS_KEY, SpinePreferences.DEFAULT_SET_TEXTUREIMPORTER_SETTINGS);
|
||||
textureSettingsReference = EditorPrefs.GetString(TEXTURE_SETTINGS_REFERENCE_KEY, SpinePreferences.DEFAULT_TEXTURE_SETTINGS_REFERENCE);
|
||||
blendModeMaterialMultiply = EditorPrefs.GetString(BLEND_MODE_MATERIAL_MULTIPLY_KEY, "");
|
||||
blendModeMaterialScreen = EditorPrefs.GetString(BLEND_MODE_MATERIAL_SCREEN_KEY, "");
|
||||
blendModeMaterialAdditive = EditorPrefs.GetString(BLEND_MODE_MATERIAL_ADDITIVE_KEY, "");
|
||||
autoReloadSceneSkeletons = EditorPrefs.GetBool(AUTO_RELOAD_SCENESKELETONS_KEY, SpinePreferences.DEFAULT_AUTO_RELOAD_SCENESKELETONS);
|
||||
mecanimEventIncludeFolderName = EditorPrefs.GetBool(MECANIM_EVENT_INCLUDE_FOLDERNAME_KEY, SpinePreferences.DEFAULT_MECANIM_EVENT_INCLUDE_FOLDERNAME);
|
||||
atlasTxtImportWarning = EditorPrefs.GetBool(ATLASTXT_WARNING_KEY, SpinePreferences.DEFAULT_ATLASTXT_WARNING);
|
||||
@ -246,6 +275,28 @@ namespace Spine.Unity.Editor {
|
||||
EditorPrefs.SetString(TEXTURE_SETTINGS_REFERENCE_KEY, textureSettingsReference);
|
||||
}
|
||||
}
|
||||
|
||||
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialMultiply, BLEND_MODE_MATERIAL_MULTIPLY_KEY, new GUIContent("Multiply Material", "Multiply blend mode Material template."));
|
||||
if (string.IsNullOrEmpty(blendModeMaterialMultiply)) {
|
||||
var blendModeMaterialMultiplyGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
|
||||
if (blendModeMaterialMultiplyGUIDS.Length > 0) {
|
||||
blendModeMaterialMultiply = AssetDatabase.GUIDToAssetPath(blendModeMaterialMultiplyGUIDS[0]);
|
||||
}
|
||||
}
|
||||
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialScreen, BLEND_MODE_MATERIAL_SCREEN_KEY, new GUIContent("Screen Material", "Screen blend mode Material template."));
|
||||
if (string.IsNullOrEmpty(blendModeMaterialScreen)) {
|
||||
var blendModeMaterialScreenGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
|
||||
if (blendModeMaterialScreenGUIDS.Length > 0) {
|
||||
blendModeMaterialScreen = AssetDatabase.GUIDToAssetPath(blendModeMaterialScreenGUIDS[0]);
|
||||
}
|
||||
}
|
||||
SpineEditorUtilities.MaterialPrefsField(ref blendModeMaterialAdditive, BLEND_MODE_MATERIAL_ADDITIVE_KEY, new GUIContent("Additive Material", "Additive blend mode Material template."));
|
||||
if (string.IsNullOrEmpty(blendModeMaterialAdditive)) {
|
||||
var blendModeMaterialAdditiveGUIDS = AssetDatabase.FindAssets(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
|
||||
if (blendModeMaterialAdditiveGUIDS.Length > 0) {
|
||||
blendModeMaterialAdditive = AssetDatabase.GUIDToAssetPath(blendModeMaterialAdditiveGUIDS[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
@ -344,6 +395,16 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
static void MaterialPrefsField (ref string currentValue, string editorPrefsKey, GUIContent label) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUIUtility.wideMode = true;
|
||||
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(currentValue), typeof(Object), false) as Material);
|
||||
currentValue = material != null ? AssetDatabase.GetAssetPath(material) : "";
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
EditorPrefs.SetString(editorPrefsKey, currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static void FloatPropertyField (SerializedProperty property, GUIContent label, float min = float.NegativeInfinity, float max = float.PositiveInfinity) {
|
||||
EditorGUI.BeginChangeCheck();
|
||||
property.floatValue = EditorGUILayout.DelayedFloatField(label, property.floatValue);
|
||||
@ -357,6 +418,10 @@ namespace Spine.Unity.Editor {
|
||||
property.stringValue = shader != null ? shader.name : fallbackShaderName;
|
||||
}
|
||||
|
||||
public static void MaterialPropertyField (SerializedProperty property, GUIContent label) {
|
||||
var material = (EditorGUILayout.ObjectField(label, AssetDatabase.LoadAssetAtPath<Material>(property.stringValue), typeof(Material), false) as Material);
|
||||
property.stringValue = material ? AssetDatabase.GetAssetPath(material) : "";
|
||||
}
|
||||
|
||||
#if NEW_PREFERENCES_SETTINGS_PROVIDER
|
||||
public static void PresetAssetPropertyField (SerializedProperty property, GUIContent label) {
|
||||
|
||||
@ -78,6 +78,65 @@ namespace Spine.Unity.Editor {
|
||||
internal const string DEFAULT_TEXTURE_SETTINGS_REFERENCE = "";
|
||||
public string textureSettingsReference = DEFAULT_TEXTURE_SETTINGS_REFERENCE;
|
||||
|
||||
public bool UsesPMAWorkflow {
|
||||
get {
|
||||
return IsPMAWorkflow(textureSettingsReference);
|
||||
}
|
||||
}
|
||||
public static bool IsPMAWorkflow(string textureSettingsReference) {
|
||||
if (textureSettingsReference == null)
|
||||
return true;
|
||||
string settingsReference = textureSettingsReference.ToLower();
|
||||
if (settingsReference.Contains("straight") || !settingsReference.Contains("pma"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public const string DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL = "SkeletonPMAMultiply";
|
||||
public const string DEFAULT_BLEND_MODE_SCREEN_MATERIAL = "SkeletonPMAScreen";
|
||||
public const string DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL = "SkeletonPMAAdditive";
|
||||
|
||||
public Material blendModeMaterialMultiply = null;
|
||||
public Material blendModeMaterialScreen = null;
|
||||
public Material blendModeMaterialAdditive = null;
|
||||
|
||||
public string FindPathOfAsset (string assetName) {
|
||||
string typeSearchString = assetName;
|
||||
string[] guids = AssetDatabase.FindAssets(typeSearchString);
|
||||
if (guids.Length > 0) {
|
||||
return AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Material BlendModeMaterialMultiply {
|
||||
get {
|
||||
if (blendModeMaterialMultiply == null) {
|
||||
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_MULTIPLY_MATERIAL);
|
||||
blendModeMaterialMultiply = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||
}
|
||||
return blendModeMaterialMultiply;
|
||||
}
|
||||
}
|
||||
public Material BlendModeMaterialScreen {
|
||||
get {
|
||||
if (blendModeMaterialScreen == null) {
|
||||
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_SCREEN_MATERIAL);
|
||||
blendModeMaterialScreen = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||
}
|
||||
return blendModeMaterialScreen;
|
||||
}
|
||||
}
|
||||
public Material BlendModeMaterialAdditive {
|
||||
get {
|
||||
if (blendModeMaterialAdditive == null) {
|
||||
string path = FindPathOfAsset(DEFAULT_BLEND_MODE_ADDITIVE_MATERIAL);
|
||||
blendModeMaterialAdditive = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||
}
|
||||
return blendModeMaterialAdditive;
|
||||
}
|
||||
}
|
||||
|
||||
internal const bool DEFAULT_ATLASTXT_WARNING = true;
|
||||
public bool atlasTxtImportWarning = DEFAULT_ATLASTXT_WARNING;
|
||||
|
||||
@ -180,6 +239,10 @@ namespace Spine.Unity.Editor {
|
||||
textureSettingsRef.stringValue = AssetDatabase.GUIDToAssetPath(pmaTextureSettingsReferenceGUIDS[0]);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(settings.FindProperty("blendModeMaterialMultiply"), new GUIContent("Multiply Material", "Multiply blend mode Material template."));
|
||||
EditorGUILayout.PropertyField(settings.FindProperty("blendModeMaterialScreen"), new GUIContent("Screen Material", "Screen blend mode Material template."));
|
||||
EditorGUILayout.PropertyField(settings.FindProperty("blendModeMaterialAdditive"), new GUIContent("Additive Material", "Additive blend mode Material template."));
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
@ -0,0 +1,144 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2020, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using Spine;
|
||||
|
||||
namespace Spine.Unity {
|
||||
[System.Serializable]
|
||||
public class BlendModeMaterials {
|
||||
|
||||
[System.Serializable]
|
||||
public class ReplacementMaterial {
|
||||
public string pageName;
|
||||
public Material material;
|
||||
}
|
||||
|
||||
[SerializeField, HideInInspector] protected bool requiresBlendModeMaterials = false;
|
||||
public bool applyAdditiveMaterial = false;
|
||||
|
||||
public List<ReplacementMaterial> additiveMaterials = new List<ReplacementMaterial>();
|
||||
public List<ReplacementMaterial> multiplyMaterials = new List<ReplacementMaterial>();
|
||||
public List<ReplacementMaterial> screenMaterials = new List<ReplacementMaterial>();
|
||||
|
||||
public bool RequiresBlendModeMaterials { get { return requiresBlendModeMaterials; } set { requiresBlendModeMaterials = value; } }
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void TransferSettingsFrom (BlendModeMaterialsAsset modifierAsset) {
|
||||
applyAdditiveMaterial = modifierAsset.applyAdditiveMaterial;
|
||||
}
|
||||
|
||||
public bool UpdateBlendmodeMaterialsRequiredState (SkeletonData skeletonData) {
|
||||
requiresBlendModeMaterials = false;
|
||||
|
||||
if (skeletonData == null) throw new ArgumentNullException("skeletonData");
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.blendMode == BlendMode.Normal) continue;
|
||||
if (!applyAdditiveMaterial && slot.blendMode == BlendMode.Additive) continue;
|
||||
|
||||
skinEntries.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
if (entry.Attachment is IHasRendererObject) {
|
||||
requiresBlendModeMaterials = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
public void ApplyMaterials (SkeletonData skeletonData) {
|
||||
if (skeletonData == null) throw new ArgumentNullException("skeletonData");
|
||||
if (!requiresBlendModeMaterials)
|
||||
return;
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
var slotsItems = skeletonData.Slots.Items;
|
||||
for (int slotIndex = 0, slotCount = skeletonData.Slots.Count; slotIndex < slotCount; slotIndex++) {
|
||||
var slot = slotsItems[slotIndex];
|
||||
if (slot.blendMode == BlendMode.Normal) continue;
|
||||
if (!applyAdditiveMaterial && slot.blendMode == BlendMode.Additive) continue;
|
||||
|
||||
List<ReplacementMaterial> replacementMaterials = null;
|
||||
switch (slot.blendMode) {
|
||||
case BlendMode.Multiply:
|
||||
replacementMaterials = multiplyMaterials;
|
||||
break;
|
||||
case BlendMode.Screen:
|
||||
replacementMaterials = screenMaterials;
|
||||
break;
|
||||
case BlendMode.Additive:
|
||||
replacementMaterials = additiveMaterials;
|
||||
break;
|
||||
}
|
||||
if (replacementMaterials == null)
|
||||
continue;
|
||||
|
||||
skinEntries.Clear();
|
||||
foreach (var skin in skeletonData.Skins)
|
||||
skin.GetAttachments(slotIndex, skinEntries);
|
||||
|
||||
foreach (var entry in skinEntries) {
|
||||
var renderableAttachment = entry.Attachment as IHasRendererObject;
|
||||
if (renderableAttachment != null) {
|
||||
renderableAttachment.RendererObject = CloneAtlasRegionWithMaterial(
|
||||
(AtlasRegion)renderableAttachment.RendererObject, replacementMaterials);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected AtlasRegion CloneAtlasRegionWithMaterial (AtlasRegion originalRegion, List<ReplacementMaterial> replacementMaterials) {
|
||||
var newRegion = originalRegion.Clone();
|
||||
Material material = null;
|
||||
foreach (var replacement in replacementMaterials) {
|
||||
if (replacement.pageName == originalRegion.page.name) {
|
||||
material = replacement.material;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AtlasPage originalPage = originalRegion.page;
|
||||
var newPage = originalPage.Clone();
|
||||
newPage.rendererObject = material;
|
||||
newRegion.page = newPage;
|
||||
return newRegion;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d03ca55657e89b949a4c07bc9207beac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -49,6 +49,9 @@ namespace Spine.Unity {
|
||||
#endif
|
||||
public TextAsset skeletonJSON;
|
||||
|
||||
public bool isUpgradingBlendModeMaterials = false;
|
||||
public BlendModeMaterials blendModeMaterials = new BlendModeMaterials();
|
||||
|
||||
[Tooltip("Use SkeletonDataModifierAssets to apply changes to the SkeletonData after being loaded, such as apply blend mode Materials to Attachments under slots with special blend modes.")]
|
||||
public List<SkeletonDataModifierAsset> skeletonDataModifiers = new List<SkeletonDataModifierAsset>();
|
||||
|
||||
@ -187,10 +190,14 @@ namespace Spine.Unity {
|
||||
return null;
|
||||
|
||||
if (skeletonDataModifiers != null) {
|
||||
foreach (var m in skeletonDataModifiers) {
|
||||
if (m != null) m.Apply(loadedSkeletonData);
|
||||
foreach (var modifier in skeletonDataModifiers) {
|
||||
if (modifier != null && !(isUpgradingBlendModeMaterials && modifier is BlendModeMaterialsAsset)) {
|
||||
modifier.Apply(loadedSkeletonData);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isUpgradingBlendModeMaterials)
|
||||
blendModeMaterials.ApplyMaterials(loadedSkeletonData);
|
||||
|
||||
this.InitializeWithData(loadedSkeletonData);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user