WXMC/.svn/pristine/c3/c3deb9354639b473a000e30c91855d5def18ac01.svn-base
2024-12-04 16:18:46 +08:00

283 lines
12 KiB
Plaintext

/******************************************************************************
* 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);
}
}
}