live2D (sdk가 6.5 미지원으로 sprite로 대응)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
using Live2D.Cubism.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="MonoBehaviour"/>s.
|
||||
/// </summary>
|
||||
internal static class ComponentExtensionMethods
|
||||
{
|
||||
public static Component GetOrAddComponent(this Component self, Type type)
|
||||
{
|
||||
var component = self.GetComponent(type);
|
||||
|
||||
|
||||
if (component != null)
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
return self.gameObject.AddComponent(type);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a component should be moved on reimport.
|
||||
/// </summary>
|
||||
/// <param name="self">Component to check against.</param>
|
||||
/// <returns>True if component should be moved; false otherwise.</returns>
|
||||
public static bool MoveOnCubismReimport(this Component self, bool componentsOnly)
|
||||
{
|
||||
return self
|
||||
.GetType()
|
||||
.GetCustomAttributes(false)
|
||||
.FirstOrDefault(a => (a.GetType() == typeof(CubismDontMoveOnReimportAttribute)) || (a.GetType() == typeof(CubismMoveOnReimportCopyComponentsOnly) && !componentsOnly)) == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87405b60b59ea2746b508ef63aba402c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
300
Assets/Live2D/Cubism/Editor/Importers/CubismImporter.cs
Normal file
300
Assets/Live2D/Cubism/Editor/Importers/CubismImporter.cs
Normal file
@@ -0,0 +1,300 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
using Live2D.Cubism.Core;
|
||||
using Live2D.Cubism.Framework.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper functionality for <see cref="ICubismImporter"/>s.
|
||||
/// </summary>
|
||||
public static class CubismImporter
|
||||
{
|
||||
#region Delegates
|
||||
|
||||
/// <summary>
|
||||
/// Callback on <see cref="CubismModel"/> import.
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="model">Imported model.</param>
|
||||
public delegate void ModelImportListener(CubismModel3JsonImporter importer, CubismModel model);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Callback for textures used by Cubism model on <see cref="CubismModel"/> import.
|
||||
/// </summary>
|
||||
public delegate void TextureImportHandler(CubismModel3JsonImporter importer, CubismModel model, Texture2D texture);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Callback on Cubism motions import as<see cref="AnimationClip"/>.
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="animationClip">Generated animation.</param>
|
||||
public delegate void MotionImportHandler(CubismMotion3JsonImporter importer, AnimationClip animationClip);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Allows getting called back whenever a model is imported (and before it is saved).
|
||||
/// </summary>
|
||||
public static event ModelImportListener OnDidImportModel;
|
||||
|
||||
/// <summary>
|
||||
/// Allows customizing import of textures used by a Cubism model.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set <see langword="null"/> in case you don't want Cubism model texture importing to be customized from script.
|
||||
/// </remarks>
|
||||
public static TextureImportHandler OnDidImportTexture = BuiltinTextureImportHandler;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Material picker to use when importing models.
|
||||
/// </summary>
|
||||
public static CubismModel3Json.DrawableMaterialPicker OnPickDrawableMaterial = CubismBuiltinPickers.DrawableMaterialPicker;
|
||||
|
||||
/// <summary>
|
||||
/// Texture picker to use when importing models.
|
||||
/// </summary>
|
||||
public static CubismModel3Json.TexturePicker OnPickTexture = CubismBuiltinPickers.TexturePicker;
|
||||
|
||||
/// <summary>
|
||||
/// Offscreen material picker to use when importing models.
|
||||
/// </summary>
|
||||
public static CubismModel3Json.OffscreenMaterialPicker OnPickOffscreenMaterial = CubismBuiltinPickers.OffscreenMaterialPicker;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allows getting called back whenever a Cubism motions is imported (and before it is saved).
|
||||
/// </summary>
|
||||
public static event MotionImportHandler OnDidImportMotion;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Enables logging of import events.
|
||||
/// </summary>
|
||||
public static bool LogImportEvents = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get an importer for a Cubism asset.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Importer type.</typeparam>
|
||||
/// <param name="assetPath">Path to the asset.</param>
|
||||
/// <returns>The importer on success; <see langword="null"/> otherwise.</returns>
|
||||
public static T GetImporterAtPath<T>(string assetPath) where T : class, ICubismImporter
|
||||
{
|
||||
return GetImporterAtPath(assetPath) as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to deserialize an importer from <see cref="AssetImporter.userData"/>.
|
||||
/// </summary>
|
||||
/// <param name="assetPath">Path to the asset.</param>
|
||||
/// <returns>The importer on success; <see langword="null"/> otherwise.</returns>
|
||||
public static ICubismImporter GetImporterAtPath(string assetPath)
|
||||
{
|
||||
var importerEntry = _registry.Find(e => assetPath.EndsWith(e.FileExtension));
|
||||
|
||||
|
||||
// Return early in case no valid importer is registered.
|
||||
if (importerEntry.ImporterType == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var userData = AssetImporter
|
||||
.GetAtPath(assetPath)
|
||||
.userData;
|
||||
|
||||
|
||||
// Try to deserialize a importer from the user data.
|
||||
var importer = JsonUtility.FromJson(userData, importerEntry.ImporterType) as ICubismImporter;
|
||||
|
||||
|
||||
// Activate an instance in case Json deserialization magically fails...
|
||||
if (importer == null)
|
||||
{
|
||||
importer = Activator.CreateInstance(importerEntry.ImporterType) as ICubismImporter;
|
||||
}
|
||||
|
||||
|
||||
// Finalize importer initialization.
|
||||
if (importer != null)
|
||||
{
|
||||
importer.SetAssetPath(assetPath);
|
||||
}
|
||||
|
||||
|
||||
return importer;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Safely triggers <see cref="OnDidImportModel"/>.
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="model">Imported model.</param>
|
||||
internal static void SendModelImportEvent(CubismModel3JsonImporter importer, CubismModel model)
|
||||
{
|
||||
if (OnDidImportModel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OnDidImportModel(importer, model);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely triggers <see cref="OnDidImportModelTexture"/>
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="model">Imported model.</param>
|
||||
/// <param name="texture">Imported texture.</param>
|
||||
internal static void SendModelTextureImportEvent(CubismModel3JsonImporter importer, CubismModel model, Texture2D texture)
|
||||
{
|
||||
if (OnDidImportTexture == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OnDidImportTexture(importer, model, texture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely triggers <see cref="OnDidImportMotion"/>.
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="animationClip">Generated animation.</param>
|
||||
internal static void SendMotionImportEvent(CubismMotion3JsonImporter importer, AnimationClip animationClip)
|
||||
{
|
||||
if (OnDidImportMotion == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OnDidImportMotion(importer, animationClip);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Logs a reimport event.
|
||||
/// </summary>
|
||||
/// <param name="sourceName">Source asset reimported.</param>
|
||||
/// <param name="destinationName">Destination asset updated.</param>
|
||||
internal static void LogReimport(string sourceName, string destinationName)
|
||||
{
|
||||
if (!LogImportEvents)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Debug.LogFormat("[Cubism] Reimport: \"{0}\" was synced with \"{1}\".", destinationName, sourceName);
|
||||
}
|
||||
|
||||
#region Builtin Texture Import Handler
|
||||
|
||||
/// <summary>
|
||||
/// Makes sure textures used by Cubism models have the <see cref="TextureImporter.alphaIsTransparency"/> option enabled.
|
||||
/// </summary>
|
||||
/// <param name="importer">Importer.</param>
|
||||
/// <param name="model">Imported model.</param>
|
||||
/// <param name="texture">Imported texture.</param>
|
||||
private static void BuiltinTextureImportHandler(CubismModel3JsonImporter importer, CubismModel model, Texture2D texture)
|
||||
{
|
||||
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
|
||||
|
||||
if (!textureImporter)
|
||||
{
|
||||
Debug.LogError("[Texture Importer] Could not get TextureImporter for texture used by Cubism model.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Return early if texture already seems to be set up.
|
||||
if (!textureImporter.mipmapEnabled
|
||||
&& textureImporter.alphaIsTransparency
|
||||
&& textureImporter.textureType == TextureImporterType.Default
|
||||
&& textureImporter.textureCompression == TextureImporterCompression.Uncompressed
|
||||
&& textureImporter.wrapMode == TextureWrapMode.Repeat
|
||||
&& textureImporter.filterMode == FilterMode.Bilinear)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Set up texture importing.
|
||||
textureImporter.mipmapEnabled = false;
|
||||
textureImporter.alphaIsTransparency = true;
|
||||
textureImporter.textureType = TextureImporterType.Default;
|
||||
textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
|
||||
textureImporter.wrapMode = TextureWrapMode.Repeat;
|
||||
textureImporter.filterMode = FilterMode.Bilinear;
|
||||
|
||||
EditorUtility.SetDirty(texture);
|
||||
textureImporter.SaveAndReimport();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Registry
|
||||
|
||||
/// <summary>
|
||||
/// Registry entry.
|
||||
/// </summary>
|
||||
private struct ImporterEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Importer type.
|
||||
/// </summary>
|
||||
public Type ImporterType;
|
||||
|
||||
/// <summary>
|
||||
/// File extension valid for the importer.
|
||||
/// </summary>
|
||||
public string FileExtension;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// List of registered <see cref="ICubismImporter"/>s.
|
||||
/// </summary>
|
||||
private static List<ImporterEntry> _registry = new List<ImporterEntry>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Registers an importer type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of importer to register.</typeparam>
|
||||
/// <param name="fileExtension">The file extension the importer supports.</param>
|
||||
internal static void RegisterImporter<T>(string fileExtension) where T : ICubismImporter
|
||||
{
|
||||
_registry.Add(new ImporterEntry
|
||||
{
|
||||
ImporterType = typeof(T),
|
||||
FileExtension = fileExtension
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
Assets/Live2D/Cubism/Editor/Importers/CubismImporter.cs.meta
Normal file
11
Assets/Live2D/Cubism/Editor/Importers/CubismImporter.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a5211838ab488047b05c5806016ed5b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
76
Assets/Live2D/Cubism/Editor/Importers/CubismImporterBase.cs
Normal file
76
Assets/Live2D/Cubism/Editor/Importers/CubismImporterBase.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for Cubism asset importers.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public abstract class CubismImporterBase : ICubismImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the path to the imported asset.
|
||||
/// </summary>
|
||||
public string AssetPath { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
public abstract void Import();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves the importer state and reimports the asset.
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
var assetImporter = AssetImporter.GetAtPath(AssetPath);
|
||||
|
||||
|
||||
assetImporter.userData = JsonUtility.ToJson(this);
|
||||
|
||||
|
||||
AssetDatabase.WriteImportSettingsIfDirty(AssetPath);
|
||||
}
|
||||
|
||||
#region ICubismImporter
|
||||
|
||||
/// <summary>
|
||||
/// Sets the asset path.
|
||||
/// </summary>
|
||||
void ICubismImporter.SetAssetPath(string value)
|
||||
{
|
||||
AssetPath = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
void ICubismImporter.Import()
|
||||
{
|
||||
Import();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the importer state and reimports the asset.
|
||||
/// </summary>
|
||||
void ICubismImporter.Save()
|
||||
{
|
||||
Save();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d72a86459d505cb4ebc7c52a389e9c00
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,416 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
using Live2D.Cubism.Core;
|
||||
using Live2D.Cubism.Framework;
|
||||
using Live2D.Cubism.Framework.Expression;
|
||||
using Live2D.Cubism.Framework.Json;
|
||||
using Live2D.Cubism.Framework.MotionFade;
|
||||
using Live2D.Cubism.Framework.MouthMovement;
|
||||
using Live2D.Cubism.Framework.Pose;
|
||||
using Live2D.Cubism.Rendering;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles importing of Cubism models.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class CubismModel3JsonImporter : CubismImporterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="Model3Json"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized] private CubismModel3Json _model3Json;
|
||||
|
||||
/// <summary>
|
||||
///<see cref="CubismModel3Json"/> asset.
|
||||
/// </summary>
|
||||
public CubismModel3Json Model3Json
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_model3Json == null)
|
||||
{
|
||||
_model3Json = CubismModel3Json.LoadAtPath(AssetPath);
|
||||
}
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
if (_modelPrefab == null)
|
||||
{
|
||||
_modelPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetPath.Replace(".model3.json", ".prefab"));
|
||||
if(_modelPrefab != null)
|
||||
{
|
||||
_modelPrefabGuid = AssetGuid.GetGuid(_modelPrefab);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return _model3Json;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid of model prefab.
|
||||
/// </summary>
|
||||
[SerializeField] private string _modelPrefabGuid;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="ModelPrefab"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized] private GameObject _modelPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Prefab of model.
|
||||
/// </summary>
|
||||
private GameObject ModelPrefab
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_modelPrefab == null)
|
||||
{
|
||||
_modelPrefab = AssetGuid.LoadAsset<GameObject>(_modelPrefabGuid);
|
||||
}
|
||||
|
||||
|
||||
return _modelPrefab;
|
||||
}
|
||||
set
|
||||
{
|
||||
_modelPrefab = value;
|
||||
_modelPrefabGuid = AssetGuid.GetGuid(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid of moc.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private string _mocAssetGuid;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="MocAsset"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private CubismMoc _mocAsset;
|
||||
|
||||
/// <summary>
|
||||
/// Moc asset.
|
||||
/// </summary>
|
||||
private CubismMoc MocAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mocAsset == null)
|
||||
{
|
||||
_mocAsset = AssetGuid.LoadAsset<CubismMoc>(_mocAssetGuid);
|
||||
}
|
||||
|
||||
|
||||
return _mocAsset;
|
||||
}
|
||||
set
|
||||
{
|
||||
_mocAsset = value;
|
||||
_mocAssetGuid = AssetGuid.GetGuid(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Should import as original workflow.
|
||||
/// </summary>
|
||||
private bool ShouldImportAsOriginalWorkflow
|
||||
{
|
||||
get
|
||||
{
|
||||
return CubismUnityEditorMenu.ShouldImportAsOriginalWorkflow;
|
||||
}
|
||||
}
|
||||
|
||||
#region Unity Event Handling
|
||||
|
||||
/// <summary>
|
||||
/// Registers importer.
|
||||
/// </summary>
|
||||
[InitializeOnLoadMethod]
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private static void RegisterImporter()
|
||||
{
|
||||
CubismImporter.RegisterImporter<CubismModel3JsonImporter>(".model3.json");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CubismImporterBase
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
public override void Import()
|
||||
{
|
||||
var isImporterDirty = false;
|
||||
|
||||
|
||||
// Instantiate model source and model.
|
||||
var model = Model3Json.ToModel(CubismImporter.OnPickDrawableMaterial, CubismImporter.OnPickTexture, CubismImporter.OnPickOffscreenMaterial, ShouldImportAsOriginalWorkflow);
|
||||
|
||||
if (model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var assetPath = AssetPath.Replace(".model3.json", "");
|
||||
var modelName = Path.GetFileName(assetPath).Replace(".model3.json", "");
|
||||
|
||||
var moc = model.Moc;
|
||||
moc.name = modelName;
|
||||
|
||||
// Create moc asset.
|
||||
if (MocAsset == null)
|
||||
{
|
||||
AssetDatabase.CreateAsset(moc, $"{assetPath}.asset");
|
||||
|
||||
|
||||
MocAsset = moc;
|
||||
|
||||
|
||||
isImporterDirty = true;
|
||||
}
|
||||
|
||||
|
||||
// Create model prefab.
|
||||
if (ModelPrefab == null)
|
||||
{
|
||||
// Trigger event.
|
||||
CubismImporter.SendModelImportEvent(this, model);
|
||||
|
||||
|
||||
foreach (var texture in Model3Json.Textures)
|
||||
{
|
||||
CubismImporter.SendModelTextureImportEvent(this, model, texture);
|
||||
}
|
||||
|
||||
// Create prefab and trigger saving of changes.
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
ModelPrefab = PrefabUtility.SaveAsPrefabAsset(model.gameObject, $"{assetPath}.prefab");
|
||||
#else
|
||||
ModelPrefab = PrefabUtility.CreatePrefab($"{assetPath}.prefab", model.gameObject);
|
||||
#endif
|
||||
|
||||
isImporterDirty = true;
|
||||
}
|
||||
|
||||
|
||||
// Update model prefab.
|
||||
else
|
||||
{
|
||||
var cubismModel = ModelPrefab.FindCubismModel();
|
||||
if (cubismModel.Moc == null)
|
||||
{
|
||||
CubismModel.ResetMocReference(cubismModel,
|
||||
AssetDatabase.LoadAssetAtPath<CubismMoc>(
|
||||
$"{assetPath}.asset"));
|
||||
}
|
||||
|
||||
|
||||
// Copy all user data over from previous model.
|
||||
var source = Object.Instantiate(ModelPrefab).FindCubismModel();
|
||||
|
||||
|
||||
CopyUserData(source, model);
|
||||
|
||||
Object.DestroyImmediate(source.gameObject, true);
|
||||
|
||||
|
||||
// Trigger events.
|
||||
CubismImporter.SendModelImportEvent(this, model);
|
||||
|
||||
|
||||
foreach (var texture in Model3Json.Textures)
|
||||
{
|
||||
CubismImporter.SendModelTextureImportEvent(this, model, texture);
|
||||
}
|
||||
|
||||
var renderController = model.gameObject.GetComponent<CubismRenderController>();
|
||||
|
||||
if (renderController)
|
||||
{
|
||||
// HACK: Re-assign textures to avoid lost references due to Unity prefab optimization.
|
||||
foreach (var cubismRenderer in renderController.DrawableRenderers)
|
||||
{
|
||||
// Reset texture references.
|
||||
cubismRenderer.MainTexture =
|
||||
CubismBuiltinPickers.TexturePicker(Model3Json, cubismRenderer.Drawable);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset moc reference.
|
||||
CubismModel.ResetMocReference(model, MocAsset);
|
||||
|
||||
// Update moc asset before saving prefab to avoid IndexOutOfRangeException
|
||||
// when Inspector loads the prefab and calls Revive() with stale moc data.
|
||||
if (MocAsset != null)
|
||||
{
|
||||
EditorUtility.CopySerialized(moc, MocAsset);
|
||||
|
||||
// Revive by force to make instance using the new Moc.
|
||||
CubismMoc.ResetUnmanagedMoc(MocAsset);
|
||||
|
||||
EditorUtility.SetDirty(MocAsset);
|
||||
}
|
||||
|
||||
// Keep layer value.
|
||||
model.gameObject.layer = ModelPrefab.layer;
|
||||
|
||||
// Replace prefab.
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
ModelPrefab = PrefabUtility.SaveAsPrefabAsset(model.gameObject, $"{assetPath}.prefab");
|
||||
|
||||
// Clear stale non-serialized state cached during prefab replacement.
|
||||
var savedModel = ModelPrefab.FindCubismModel();
|
||||
if (savedModel != null)
|
||||
{
|
||||
CubismModel.ResetNonSerializedFields(savedModel);
|
||||
}
|
||||
#else
|
||||
ModelPrefab = PrefabUtility.ReplacePrefab(model.gameObject, ModelPrefab, ReplacePrefabOptions.ConnectToPrefab);
|
||||
#endif
|
||||
|
||||
// Log event.
|
||||
CubismImporter.LogReimport(AssetPath, AssetDatabase.GUIDToAssetPath(_modelPrefabGuid));
|
||||
}
|
||||
|
||||
|
||||
// Clean up.
|
||||
Object.DestroyImmediate(model.gameObject, true);
|
||||
|
||||
// Save state and assets.
|
||||
if (isImporterDirty)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void CopyUserData(CubismModel source, CubismModel destination, bool copyComponentsOnly = false)
|
||||
{
|
||||
// Give parameters, parts, and drawables special treatment.
|
||||
CopyUserData(source.Parameters, destination.Parameters, copyComponentsOnly);
|
||||
CopyUserData(source.Parts, destination.Parts, copyComponentsOnly);
|
||||
CopyUserData(source.Drawables, destination.Drawables, copyComponentsOnly);
|
||||
|
||||
|
||||
// Copy components.
|
||||
foreach (var sourceComponent in source.GetComponents(typeof(Component)))
|
||||
{
|
||||
// Skip non-movable components.
|
||||
if (!sourceComponent.MoveOnCubismReimport(copyComponentsOnly))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip copy original workflow component.
|
||||
if(sourceComponent.GetType() == typeof(CubismUpdateController)
|
||||
|| sourceComponent.GetType() == typeof(CubismFadeController)
|
||||
|| sourceComponent.GetType() == typeof(CubismExpressionController)
|
||||
|| sourceComponent.GetType() == typeof(CubismPoseController)
|
||||
|| sourceComponent.GetType() == typeof(CubismParameterStore)
|
||||
|| sourceComponent.GetType() == typeof(CubismDisplayInfoCombinedParameterInfo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy component.
|
||||
var destinationComponent = destination.GetOrAddComponent(sourceComponent.GetType());
|
||||
|
||||
|
||||
EditorUtility.CopySerialized(sourceComponent, destinationComponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void CopyUserData<T>(T[] source, T[] destination, bool copyComponentsOnly) where T : MonoBehaviour
|
||||
{
|
||||
foreach (var destinationT in destination)
|
||||
{
|
||||
var sourceT = source.FirstOrDefault(p => p.name == destinationT.name);
|
||||
|
||||
|
||||
// Skip removed parameters.
|
||||
if (sourceT == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Copy any children.
|
||||
foreach (var child in sourceT.transform
|
||||
.GetComponentsInChildren<Transform>()
|
||||
.Where(t => t != sourceT.transform)
|
||||
.Select(t => t.gameObject))
|
||||
{
|
||||
Object.Instantiate(child, destinationT.transform);
|
||||
}
|
||||
|
||||
|
||||
// Copy components.
|
||||
foreach (var sourceComponent in sourceT.GetComponents(typeof(Component)))
|
||||
{
|
||||
// Skip non-movable components.
|
||||
if (!sourceComponent.MoveOnCubismReimport(copyComponentsOnly))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip import-managed components that should not be inherited from the old prefab.
|
||||
if (sourceComponent.GetType() == typeof(CubismEyeBlinkParameter)
|
||||
|| sourceComponent.GetType() == typeof(CubismMouthParameter))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy component.
|
||||
var destinationComponent = destinationT.GetOrAddComponent(sourceComponent.GetType());
|
||||
if (destinationComponent is CubismDisplayInfoParameterName cdiParameterName && !string.IsNullOrEmpty(cdiParameterName.Name))
|
||||
{
|
||||
var name = cdiParameterName.Name;
|
||||
EditorUtility.CopySerialized(sourceComponent, destinationComponent);
|
||||
cdiParameterName.Name = name;
|
||||
EditorUtility.SetDirty(cdiParameterName);
|
||||
}
|
||||
else if (destinationComponent is CubismDisplayInfoPartName cdiPartName && !string.IsNullOrEmpty(cdiPartName.Name))
|
||||
{
|
||||
var name = cdiPartName.Name;
|
||||
EditorUtility.CopySerialized(sourceComponent, destinationComponent);
|
||||
cdiPartName.Name = name;
|
||||
EditorUtility.SetDirty(cdiPartName);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorUtility.CopySerialized(sourceComponent, destinationComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2b5f5eae05433546b6801c35df937b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
using Live2D.Cubism.Framework.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles importing of Cubism motions.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class CubismMotion3JsonImporter : CubismImporterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="Motion3Json"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private CubismMotion3Json _motion3Json;
|
||||
|
||||
/// <summary>
|
||||
///<see cref="CubismMotion3Json"/> asset.
|
||||
/// </summary>
|
||||
public CubismMotion3Json Motion3Json
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_motion3Json == null)
|
||||
{
|
||||
_motion3Json = CubismMotion3Json.LoadFrom(AssetDatabase.LoadAssetAtPath<TextAsset>((AssetPath)));
|
||||
}
|
||||
|
||||
|
||||
return _motion3Json;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// GUID of generated clip.
|
||||
/// </summary>
|
||||
[SerializeField] private string _animationClipGuid;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="AnimationClip"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized] private AnimationClip _animationClip;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the moc3 importer.
|
||||
/// </summary>
|
||||
private AnimationClip AnimationClip
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_animationClip != null)
|
||||
{
|
||||
return _animationClip;
|
||||
}
|
||||
|
||||
AnimationClip clip;
|
||||
var directoryName = Path.GetDirectoryName(AssetPath);
|
||||
var motionName = Path.GetFileName(AssetPath.Replace(".motion3.json", ".anim"));
|
||||
var motionPath = $"{directoryName}/{motionName}";
|
||||
motionPath = motionPath.Replace("\\", "/");
|
||||
|
||||
var assetList = CubismCreatedAssetList.GetInstance();
|
||||
var assetListIndex = assetList.AssetPaths.Contains(motionPath)
|
||||
? assetList.AssetPaths.IndexOf(motionPath)
|
||||
: -1;
|
||||
|
||||
// When the AnimationClip has already been registered in CubismCreatedAssetList.Assets.
|
||||
if (assetListIndex >= 0)
|
||||
{
|
||||
clip = (AnimationClip)assetList.Assets[assetListIndex];
|
||||
_animationClip = clip;
|
||||
_animationClipGuid = AssetGuid.GetGuid(_animationClip);
|
||||
|
||||
return _animationClip;
|
||||
}
|
||||
|
||||
clip = AssetGuid.LoadAsset<AnimationClip>(_animationClipGuid);
|
||||
_animationClip = clip;
|
||||
_animationClipGuid = AssetGuid.GetGuid(_animationClip);
|
||||
|
||||
// When the AnimationClip can be retrieved from a GUID.
|
||||
if (_animationClip != null)
|
||||
{
|
||||
return _animationClip;
|
||||
}
|
||||
|
||||
clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(AssetPath.Replace(".motion3.json", ".anim"));
|
||||
_animationClip = clip;
|
||||
_animationClipGuid = AssetGuid.GetGuid(clip);
|
||||
|
||||
return _animationClip;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animationClip = value;
|
||||
_animationClipGuid = AssetGuid.GetGuid(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should import as original workflow.
|
||||
/// </summary>
|
||||
private bool ShouldImportAsOriginalWorkflow
|
||||
{
|
||||
get
|
||||
{
|
||||
return CubismUnityEditorMenu.ShouldImportAsOriginalWorkflow;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should clear animation clip curves.
|
||||
/// </summary>
|
||||
private bool ShouldClearAnimationCurves
|
||||
{
|
||||
get
|
||||
{
|
||||
return CubismUnityEditorMenu.ShouldClearAnimationCurves;
|
||||
}
|
||||
}
|
||||
|
||||
#region Unity Event Handling
|
||||
|
||||
/// <summary>
|
||||
/// Registers importer.
|
||||
/// </summary>
|
||||
[InitializeOnLoadMethod]
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private static void RegisterImporter()
|
||||
{
|
||||
CubismImporter.RegisterImporter<CubismMotion3JsonImporter>(".motion3.json");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CubismImporterBase
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
public override void Import()
|
||||
{
|
||||
if (Motion3Json == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var isImporterDirty = false;
|
||||
|
||||
// Add reference of motion to list.
|
||||
var directoryName = Path.GetDirectoryName(AssetPath);
|
||||
var motionName = Path.GetFileName(AssetPath.Replace(".motion3.json", ""));
|
||||
var motionPath = $"{directoryName}/{motionName}.anim";
|
||||
|
||||
var assetList = CubismCreatedAssetList.GetInstance();
|
||||
var assetListIndex = assetList.AssetPaths.Contains(motionPath)
|
||||
? assetList.AssetPaths.IndexOf(motionPath)
|
||||
: -1;
|
||||
|
||||
AnimationClip clip;
|
||||
if (assetListIndex < 0)
|
||||
{
|
||||
clip = (ShouldImportAsOriginalWorkflow)
|
||||
? AssetDatabase.LoadAssetAtPath<AnimationClip>(motionPath)
|
||||
: null;
|
||||
|
||||
// Convert motion.
|
||||
var animationClip = (clip == null)
|
||||
? Motion3Json.ToAnimationClip(ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves)
|
||||
: Motion3Json.ToAnimationClip(clip, ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves);
|
||||
|
||||
if (animationClip == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
animationClip.name = motionName;
|
||||
|
||||
// Create animation clip.
|
||||
if (AnimationClip == null)
|
||||
{
|
||||
AssetDatabase.CreateAsset(animationClip, AssetPath.Replace(".motion3.json", ".anim"));
|
||||
AnimationClip = animationClip;
|
||||
}
|
||||
|
||||
isImporterDirty = true;
|
||||
clip = AnimationClip;
|
||||
|
||||
assetList.Assets.Add(AnimationClip);
|
||||
assetList.AssetPaths.Add(motionPath);
|
||||
assetList.IsImporterDirties.Add(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update animation clip.
|
||||
clip = (AnimationClip)assetList.Assets[assetListIndex];
|
||||
|
||||
// Convert motion.
|
||||
var animationClip = (clip == null)
|
||||
? Motion3Json.ToAnimationClip(ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves)
|
||||
: Motion3Json.ToAnimationClip(clip, ShouldImportAsOriginalWorkflow, ShouldClearAnimationCurves);
|
||||
|
||||
if (animationClip == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
animationClip.name = motionName;
|
||||
|
||||
// Create animation clip.
|
||||
if (AnimationClip == null)
|
||||
{
|
||||
AssetDatabase.CreateAsset(animationClip, AssetPath.Replace(".motion3.json", ".anim"));
|
||||
AnimationClip = animationClip;
|
||||
}
|
||||
|
||||
EditorUtility.CopySerialized(animationClip, AnimationClip);
|
||||
EditorUtility.SetDirty(AnimationClip);
|
||||
|
||||
// Log event.
|
||||
CubismImporter.LogReimport(AssetPath, AssetDatabase.GUIDToAssetPath(_animationClipGuid));
|
||||
}
|
||||
|
||||
if (clip == null)
|
||||
{
|
||||
Debug.LogError("CubismFadeMotionImporter : Can not create Motion.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger event.
|
||||
CubismImporter.SendMotionImportEvent(this, AnimationClip);
|
||||
|
||||
|
||||
// Apply changes.
|
||||
if (isImporterDirty)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (assetList.onPostImporting)
|
||||
{
|
||||
Task.Delay(1);
|
||||
}
|
||||
|
||||
assetListIndex = assetList.AssetPaths.Contains(motionPath)
|
||||
? assetList.AssetPaths.IndexOf(motionPath)
|
||||
: -1;
|
||||
|
||||
if (assetListIndex >= 0)
|
||||
{
|
||||
assetList.Remove(assetListIndex);
|
||||
}
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90c8795cd29fb0047bec2755fcd35661
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/Live2D/Cubism/Editor/Importers/ICubismImporter.cs
Normal file
33
Assets/Live2D/Cubism/Editor/Importers/ICubismImporter.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright(c) Live2D Inc. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by the Live2D Open Software license
|
||||
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
|
||||
*/
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
/// <summary>
|
||||
/// Common interface for Cubism asset importers.
|
||||
/// </summary>
|
||||
public interface ICubismImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the asset path.
|
||||
/// </summary>
|
||||
void SetAssetPath(string value);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
void Import();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves the importer.
|
||||
/// </summary>
|
||||
void Save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2374b8a6a81af94394cfac68832b35d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user