evershade/Packages/super-tiled2unity.v2.2.0/Editor/Importers/SuperImporter.cs

231 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using UnityEditor;
using UnityEditor.AssetImporters;
using UnityEngine;
using UnityEngine.Assertions;
namespace SuperTiled2Unity.Editor
{
public abstract class SuperImporter : ScriptedImporter
{
// Keep track of our importer version so that we may handle converions from old imports
[SerializeField]
private int m_ImporterVersion = 0;
public int ImporterVersion
{
get => m_ImporterVersion;
protected set => m_ImporterVersion = value;
}
// Keep track of loaded database objects by type
private readonly Dictionary<KeyValuePair<string, Type>, UnityEngine.Object> m_CachedDatabase = new Dictionary<KeyValuePair<string, Type>, UnityEngine.Object>();
// For tracking assets and dependencies imported by SuperTiled2Unity
private SuperAsset m_SuperAsset;
// For keeping track of errors while our asset and dependencies are being imported
protected ImportErrors ImportErrors { get; private set; }
protected AssetImportContext AssetImportContext { get; private set; }
public override sealed void OnImportAsset(AssetImportContext ctx)
{
m_CachedDatabase.Clear();
m_SuperAsset = null;
ImportErrors = null;
AssetImportContext = ctx;
#if UNITY_2020_3_OR_NEWER
try
{
InternalOnImportAsset();
InternalOnImportAssetCompleted();
}
catch (XmlException xml)
{
// Xml exceptions are common if the Tiled data file somehow becomes corrupted
ReportGenericError($"Asset file may contain corrupted XML data. Trying opening in Tiled Map Editor to resolve.\n{xml.Message}");
}
catch (Exception ex)
{
// These errors should be reported for bug fixing
ReportGenericError($"Unknown error encountered. Please report as a bug.\nUnknown error importing '{assetPath}'\n{ex.Message}\nStack Trace:\n{ex.StackTrace}");
}
#else
{
string error = SuperTiled2Unity_Config.GetVersionError();
Debug.LogError(error);
}
#endif
}
public T RequestDependencyAssetAtPath<T>(string path) where T : UnityEngine.Object
{
Assert.IsNotNull(m_SuperAsset, "Must be a SuperAsset type if we are requesting dependencies.");
// Is the asset in our cache?
path = path.SanitizePath();
var key = new KeyValuePair<string, Type>(path.ToLower(), typeof(T));
if (m_CachedDatabase.TryGetValue(key, out UnityEngine.Object cachedObject))
{
return cachedObject as T;
}
// Asset is not in our cache so load it from the asset database
string absPath;
if (Path.IsPathRooted(path))
{
// Rooted paths baked into Tiled files are not recommended but if they resolve to a Unity asset then so be it.
absPath = Path.GetFullPath(path);
}
else
{
// Passed-in path should be relative to this asset
var thisAssetFolder = Path.GetDirectoryName(assetPath);
var combiedPath = Path.Combine(thisAssetFolder, path);
absPath = Path.GetFullPath(combiedPath);
}
string requestedAssetPath = absPath;
if (!AssetPath.TryAbsoluteToAsset(ref requestedAssetPath))
{
ReportMissingDependency(absPath);
return null;
}
// Keep track that the asset is a dependency
// We do this even if the asset doesn't exist (as long as we have a valid asset path)
m_SuperAsset.AddDependency(AssetImportContext, requestedAssetPath);
// In most cases our dependency is already known by the AssetDatabase
T asset = AssetDatabase.LoadAssetAtPath<T>(requestedAssetPath);
if (asset != null)
{
// Add the asset to our cache for next time it is requested
m_CachedDatabase[key] = asset;
// We also need to know if the dependency asset itself has errors
var errors = AssetDatabase.LoadAssetAtPath<ImportErrors>(requestedAssetPath);
if (errors != null)
{
ReportErrorsInDependency(requestedAssetPath);
}
return asset;
}
else
{
ReportMissingDependency(path);
}
return null;
}
public bool CheckSortingLayerName(string sortName)
{
if (!sortName.Equals("Default", StringComparison.OrdinalIgnoreCase) && SortingLayer.NameToID(sortName) == 0)
{
ReportMissingSortingLayer(sortName);
return false;
}
return true;
}
public bool CheckLayerName(string layerName)
{
if (!UnityEditorInternal.InternalEditorUtility.layers.Contains(layerName))
{
ReportMissingLayer(layerName);
return false;
}
return true;
}
public bool CheckTagName(string tagName)
{
if (!UnityEditorInternal.InternalEditorUtility.tags.Contains(tagName))
{
ReportMissingTag(tagName);
return false;
}
return true;
}
public void ReportMissingDependency(string dependencyAssetPath)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportMissingDependency(dependencyAssetPath);
}
public void ReportErrorsInDependency(string dependencyAssetPath)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportErrorsInDependency(dependencyAssetPath);
}
public void ReportMissingSprite(string textureAssetPath, int spriteId, int x, int y, int w, int h)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportMissingSprite(textureAssetPath, spriteId, x, y, w, h);
}
public void ReportWrongPixelsPerUnit(string dependencyAssetPath, float dependencyPPU, float ourPPU)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportWrongPixelsPerUnit(dependencyAssetPath, dependencyPPU, ourPPU);
}
public void ReportMissingTag(string tag)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportMissingTag(tag);
}
public void ReportMissingLayer(string layer)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportMissingLayer(layer);
}
public void ReportMissingSortingLayer(string sortingLayer)
{
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportMissingSortingLayer(sortingLayer);
}
public void ReportGenericError(string error)
{
Debug.LogError(error);
AddImportErrorsScriptableObjectIfNeeded();
ImportErrors.ReportGenericError(error);
}
private void AddImportErrorsScriptableObjectIfNeeded()
{
if (ImportErrors == null)
{
ImportErrors = ScriptableObject.CreateInstance<ImportErrors>();
ImportErrors.name = "import-errors";
AssetImportContext.AddObjectToAsset("_import-errors", ImportErrors);
}
}
protected void AddSuperAsset<T>() where T : SuperAsset
{
m_SuperAsset = ScriptableObject.CreateInstance<T>();
m_SuperAsset.name = Path.GetFileNameWithoutExtension(assetPath);
AssetImportContext.AddObjectToAsset("_superAsset", m_SuperAsset);
}
protected abstract void InternalOnImportAsset();
protected abstract void InternalOnImportAssetCompleted();
}
}