live2D (sdk가 6.5 미지원으로 sprite로 대응)
This commit is contained in:
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
* 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.MotionFade;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace Live2D.Cubism.Framework.Expression
|
||||
{
|
||||
/// <summary>
|
||||
/// Expression controller.
|
||||
/// </summary>
|
||||
public class CubismExpressionController : MonoBehaviour, ICubismUpdatable
|
||||
{
|
||||
#region variable
|
||||
|
||||
/// <summary>
|
||||
/// Expressions data list.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public CubismExpressionList ExpressionsList;
|
||||
|
||||
/// <summary>
|
||||
/// Use the expression calculation method.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public bool UseLegacyBlendCalculation = false;
|
||||
|
||||
/// <summary>
|
||||
/// CubismModel cache.
|
||||
/// </summary>
|
||||
private CubismModel _model = null;
|
||||
|
||||
/// <summary>
|
||||
/// Playing expressions.
|
||||
/// </summary>
|
||||
private List<CubismPlayingExpression> _playingExpressions = new List<CubismPlayingExpression>();
|
||||
|
||||
/// <summary>
|
||||
/// Playing expressions index.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public int CurrentExpressionIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Last playing expressions index.
|
||||
/// </summary>
|
||||
private int _lastExpressionIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Model has update controller component.
|
||||
/// </summary>
|
||||
[HideInInspector]
|
||||
public bool HasUpdateController { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Value of each parameter to be applied to the model.
|
||||
/// </summary>
|
||||
private List<CubismExpressionParameterValue> _expressionParameterValues = new List<CubismExpressionParameterValue>();
|
||||
|
||||
/// <summary>
|
||||
/// Default value for applying additive.
|
||||
/// </summary>
|
||||
private const float DefaultAdditiveValue = 0.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Initial value of multiply applied.
|
||||
/// </summary>
|
||||
private const float DefaultMultiplyValue = 1.0f;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Add new expression to playing expressions.
|
||||
/// </summary>
|
||||
private void StartExpression()
|
||||
{
|
||||
// Fail silently...
|
||||
if(ExpressionsList == null || ExpressionsList.CubismExpressionObjects == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup expression.
|
||||
_lastExpressionIndex = CurrentExpressionIndex;
|
||||
|
||||
// Set last expression end time
|
||||
if(_playingExpressions.Count > 0)
|
||||
{
|
||||
var playingExpression = _playingExpressions[_playingExpressions.Count - 1];
|
||||
var newExpressionEndTime = playingExpression.ExpressionUserTime + playingExpression.FadeOutTime;
|
||||
|
||||
if (playingExpression.ExpressionEndTime == 0.0f || newExpressionEndTime < playingExpression.ExpressionEndTime)
|
||||
{
|
||||
playingExpression.ExpressionEndTime = newExpressionEndTime;
|
||||
}
|
||||
_playingExpressions[_playingExpressions.Count - 1] = playingExpression;
|
||||
}
|
||||
|
||||
// Fail silently...
|
||||
if (CurrentExpressionIndex < 0 || CurrentExpressionIndex >= ExpressionsList.CubismExpressionObjects.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var palyingExpression = CubismPlayingExpression.Create(_model, ExpressionsList.CubismExpressionObjects[CurrentExpressionIndex]);
|
||||
|
||||
if(palyingExpression == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to PlayingExList.
|
||||
_playingExpressions.Add(palyingExpression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by cubism update controller. Order to invoke OnLateUpdate.
|
||||
/// </summary>
|
||||
public int ExecutionOrder
|
||||
{
|
||||
get { return CubismUpdateExecutionOrder.CubismExpressionController; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by cubism update controller. Needs to invoke OnLateUpdate on Editing.
|
||||
/// </summary>
|
||||
public bool NeedsUpdateOnEditing
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by cubism update manager.
|
||||
/// </summary>
|
||||
public void OnLateUpdate()
|
||||
{
|
||||
// Fail silently...
|
||||
if(!enabled || _model == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start expression when current expression changed.
|
||||
if(CurrentExpressionIndex != _lastExpressionIndex)
|
||||
{
|
||||
StartExpression();
|
||||
}
|
||||
|
||||
// Update of expressions.
|
||||
if (UseLegacyBlendCalculation)
|
||||
{
|
||||
UpdateExpressionLegacy();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update of expressions. (old method)
|
||||
/// </summary>
|
||||
private void UpdateExpressionLegacy()
|
||||
{
|
||||
// Update expression
|
||||
for (var expressionIndex = 0; expressionIndex < _playingExpressions.Count; ++expressionIndex)
|
||||
{
|
||||
var playingExpression = _playingExpressions[expressionIndex];
|
||||
|
||||
UpdateFadeWeight(playingExpression);
|
||||
|
||||
// Apply value.
|
||||
for (var i = 0; i < playingExpression.Destinations.Length; ++i)
|
||||
{
|
||||
// Fail silently...
|
||||
if (playingExpression.Destinations[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (playingExpression.Blend[i])
|
||||
{
|
||||
case CubismParameterBlendMode.Additive:
|
||||
playingExpression.Destinations[i].AddToValue(playingExpression.Value[i], playingExpression.FadeWeight);
|
||||
break;
|
||||
case CubismParameterBlendMode.Multiply:
|
||||
playingExpression.Destinations[i].MultiplyValueBy(playingExpression.Value[i], playingExpression.FadeWeight);
|
||||
break;
|
||||
case CubismParameterBlendMode.Override:
|
||||
playingExpression.Destinations[i].OverrideValue(playingExpression.Destinations[i].Value * (1 - playingExpression.FadeWeight) + (playingExpression.Value[i] * playingExpression.FadeInWeight));
|
||||
break;
|
||||
default:
|
||||
// When an unspecified value is set, it is already in addition mode.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply update value
|
||||
_playingExpressions[expressionIndex] = playingExpression;
|
||||
}
|
||||
|
||||
// Remove expression from playing expressions
|
||||
for (var expressionIndex = _playingExpressions.Count - 1; expressionIndex >= 0; --expressionIndex)
|
||||
{
|
||||
if (_playingExpressions[expressionIndex].FadeWeight > 0.0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_playingExpressions.RemoveAt(expressionIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update of expressions.
|
||||
/// </summary>
|
||||
private void UpdateExpression()
|
||||
{
|
||||
var expressionWeight = 0.0f;
|
||||
|
||||
// Update expression
|
||||
for (var expressionIndex = 0; expressionIndex < _playingExpressions.Count; ++expressionIndex)
|
||||
{
|
||||
var playingExpression = _playingExpressions[expressionIndex];
|
||||
|
||||
// List all parameters referenced by the Expression being played.
|
||||
for (var i = 0; i < playingExpression.Destinations.Length; ++i)
|
||||
{
|
||||
var index = -1;
|
||||
// Search for the presence of a parameter ID in the list.
|
||||
for (var j = 0; j < _expressionParameterValues.Count; j++)
|
||||
{
|
||||
if (_expressionParameterValues[j].Parameter != playingExpression.Destinations[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
index = j;
|
||||
break;
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the parameter does not exist in the list, add a new one.
|
||||
CubismExpressionParameterValue item = new CubismExpressionParameterValue();
|
||||
item.Parameter = playingExpression.Destinations[i];
|
||||
if (item.Parameter != null)
|
||||
{
|
||||
item.AdditiveValue = DefaultAdditiveValue;
|
||||
item.MultiplyValue = DefaultMultiplyValue;
|
||||
item.OverwriteValue = item.Parameter.Value;
|
||||
_expressionParameterValues.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// ------ Calculate value ------
|
||||
CalculateExpressionParameters(expressionIndex, playingExpression);
|
||||
|
||||
expressionWeight += playingExpression.FadeInTime == 0.0f
|
||||
? 1.0f
|
||||
: CubismFadeMath.GetEasingSine(
|
||||
(playingExpression.ExpressionUserTime - playingExpression.ExpressionStartTime) /
|
||||
playingExpression.FadeInTime);
|
||||
}
|
||||
|
||||
// ----- If the latest Expression fade is complete, delete the earlier one. ------
|
||||
if (_playingExpressions.Count > 1 &&
|
||||
_playingExpressions[_playingExpressions.Count-1].FadeWeight >= 1.0f)
|
||||
{
|
||||
// The last element of the array is not deleted.
|
||||
for (var i = _playingExpressions.Count - 2; i >= 0; --i)
|
||||
{
|
||||
_playingExpressions.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (expressionWeight > 1.0f)
|
||||
{
|
||||
expressionWeight = 1.0f;
|
||||
}
|
||||
|
||||
// Apply each value to the model.
|
||||
for (var i = 0; i < _expressionParameterValues.Count; i++)
|
||||
{
|
||||
var expressionParameterValue = _expressionParameterValues[i];
|
||||
expressionParameterValue.Parameter.OverrideValue(
|
||||
(expressionParameterValue.OverwriteValue + expressionParameterValue.AdditiveValue)
|
||||
* expressionParameterValue.MultiplyValue,
|
||||
expressionWeight);
|
||||
|
||||
expressionParameterValue.AdditiveValue = DefaultAdditiveValue;
|
||||
expressionParameterValue.MultiplyValue = DefaultMultiplyValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update motion weights.
|
||||
/// </summary>
|
||||
/// <param name="playingExpression">Expression motion during playback.</param>
|
||||
private void UpdateFadeWeight(CubismPlayingExpression playingExpression)
|
||||
{
|
||||
// Update expression user time.
|
||||
playingExpression.ExpressionUserTime += Time.deltaTime;
|
||||
|
||||
// Update weight
|
||||
playingExpression.FadeInWeight = (Mathf.Abs(playingExpression.FadeInTime) < float.Epsilon)
|
||||
? 1.0f
|
||||
: CubismFadeMath.GetEasingSine(playingExpression.ExpressionUserTime / playingExpression.FadeInTime);
|
||||
|
||||
playingExpression.FadeOutWeight = ((Mathf.Abs(playingExpression.ExpressionEndTime) < float.Epsilon) || (playingExpression.ExpressionEndTime < 0.0f))
|
||||
? 1.0f
|
||||
: CubismFadeMath.GetEasingSine(
|
||||
(playingExpression.ExpressionEndTime - playingExpression.ExpressionUserTime) / playingExpression.FadeOutTime);
|
||||
|
||||
playingExpression.FadeWeight = playingExpression.Weight * playingExpression.FadeInWeight * playingExpression.FadeOutWeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate parameters related to the model's facial expressions.
|
||||
/// </summary>
|
||||
/// <param name="expressionIndex">Index of currently processed facial expression motion.</param>
|
||||
/// <param name="playingExpression">Expression motion during playback.</param>
|
||||
private void CalculateExpressionParameters(int expressionIndex, CubismPlayingExpression playingExpression)
|
||||
{
|
||||
UpdateFadeWeight(playingExpression);
|
||||
|
||||
for (var i = 0; i < _expressionParameterValues.Count; i++)
|
||||
{
|
||||
var expressionParameterValue = _expressionParameterValues[i];
|
||||
|
||||
if (expressionParameterValue.Parameter == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var currentParameterValue = expressionParameterValue.OverwriteValue =
|
||||
expressionParameterValue.Parameter.Value;
|
||||
|
||||
var expressionParameters = playingExpression.Destinations;
|
||||
var parameterIndex = -1;
|
||||
for (var j = 0; j < expressionParameters.Length; j++)
|
||||
{
|
||||
if (expressionParameterValue.Parameter != expressionParameters[j])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
parameterIndex = j;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Parameters not referenced by the Expression being played have their initial values applied.
|
||||
if (parameterIndex < 0)
|
||||
{
|
||||
if (expressionIndex == 0)
|
||||
{
|
||||
expressionParameterValue.AdditiveValue = DefaultAdditiveValue;
|
||||
expressionParameterValue.MultiplyValue = DefaultMultiplyValue;
|
||||
expressionParameterValue.OverwriteValue = currentParameterValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionParameterValue.AdditiveValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.AdditiveValue,
|
||||
DefaultAdditiveValue,
|
||||
playingExpression.FadeWeight);
|
||||
expressionParameterValue.MultiplyValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.MultiplyValue,
|
||||
DefaultMultiplyValue,
|
||||
playingExpression.FadeWeight);
|
||||
expressionParameterValue.OverwriteValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.OverwriteValue,
|
||||
currentParameterValue,
|
||||
playingExpression.FadeWeight);
|
||||
}
|
||||
|
||||
_expressionParameterValues[i] = expressionParameterValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate value.
|
||||
var value = playingExpression.Value[parameterIndex];
|
||||
float newAdditiveValue, newMultiplyValue, newSetValue;
|
||||
switch (playingExpression.Blend[parameterIndex])
|
||||
{
|
||||
case CubismParameterBlendMode.Additive:
|
||||
newAdditiveValue = value;
|
||||
newMultiplyValue = DefaultMultiplyValue;
|
||||
newSetValue = currentParameterValue;
|
||||
break;
|
||||
case CubismParameterBlendMode.Multiply:
|
||||
newAdditiveValue = DefaultAdditiveValue;
|
||||
newMultiplyValue = value;
|
||||
newSetValue = currentParameterValue;
|
||||
break;
|
||||
case CubismParameterBlendMode.Override:
|
||||
newAdditiveValue = DefaultAdditiveValue;
|
||||
newMultiplyValue = DefaultMultiplyValue;
|
||||
newSetValue = value;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (expressionIndex == 0)
|
||||
{
|
||||
expressionParameterValue.AdditiveValue = newAdditiveValue;
|
||||
expressionParameterValue.MultiplyValue = newMultiplyValue;
|
||||
expressionParameterValue.OverwriteValue = newSetValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionParameterValue.AdditiveValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.AdditiveValue,
|
||||
newAdditiveValue,
|
||||
playingExpression.FadeWeight);
|
||||
expressionParameterValue.MultiplyValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.MultiplyValue,
|
||||
newMultiplyValue,
|
||||
playingExpression.FadeWeight);
|
||||
expressionParameterValue.OverwriteValue =
|
||||
CalculateValue(
|
||||
expressionParameterValue.OverwriteValue,
|
||||
newSetValue,
|
||||
playingExpression.FadeWeight);
|
||||
}
|
||||
_expressionParameterValues[i] = expressionParameterValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blend calculation.
|
||||
/// </summary>
|
||||
/// <param name="source">Source value.</param>
|
||||
/// <param name="destination">Destination value.</param>
|
||||
/// <param name="fadeWeight">Weight value.</param>
|
||||
/// <returns></returns>
|
||||
private float CalculateValue(float source, float destination, float fadeWeight)
|
||||
{
|
||||
return (source * (1.0f - fadeWeight)) + (destination * fadeWeight);
|
||||
}
|
||||
|
||||
#region Unity Event Handling
|
||||
|
||||
/// <summary>
|
||||
/// Called by Unity.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
_model = this.FindCubismModel();
|
||||
|
||||
// Get cubism update controller.
|
||||
HasUpdateController = (GetComponent<CubismUpdateController>() != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Unity.
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
if(!HasUpdateController)
|
||||
{
|
||||
OnLateUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b893d4d32dd60bc4c9a2e447d31c6e88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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 UnityEngine;
|
||||
|
||||
namespace Live2D.Cubism.Framework.Expression
|
||||
{
|
||||
public class CubismExpressionData : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Expression type.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public string Type;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade in time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float FadeInTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade out time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float FadeOutTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression Parameters
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public SerializableExpressionParameter[] Parameters;
|
||||
|
||||
/// <summary>
|
||||
/// ExpressionParameter
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public struct SerializableExpressionParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Expression Parameter Id
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public string Id;
|
||||
|
||||
/// <summary>
|
||||
/// Expression Parameter Value
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float Value;
|
||||
|
||||
/// <summary>
|
||||
/// Expression Parameter Blend Mode
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public CubismParameterBlendMode Blend;
|
||||
}
|
||||
|
||||
public static CubismExpressionData CreateInstance(CubismExp3Json json)
|
||||
{
|
||||
var expressionData = CreateInstance<CubismExpressionData>();
|
||||
return CreateInstance(expressionData, json);
|
||||
}
|
||||
|
||||
public static CubismExpressionData CreateInstance(CubismExpressionData expressionData, CubismExp3Json json)
|
||||
{
|
||||
expressionData.Type = json.Type;
|
||||
expressionData.FadeInTime = json.FadeInTime;
|
||||
expressionData.FadeOutTime = json.FadeOutTime;
|
||||
expressionData.Parameters = new SerializableExpressionParameter[json.Parameters.Length];
|
||||
|
||||
for(var i = 0; i < json.Parameters.Length; ++i)
|
||||
{
|
||||
expressionData.Parameters[i].Id = json.Parameters[i].Id;
|
||||
expressionData.Parameters[i].Value = json.Parameters[i].Value;
|
||||
|
||||
switch(json.Parameters[i].Blend)
|
||||
{
|
||||
case "Add":
|
||||
expressionData.Parameters[i].Blend = CubismParameterBlendMode.Additive;
|
||||
break;
|
||||
case "Multiply":
|
||||
expressionData.Parameters[i].Blend = CubismParameterBlendMode.Multiply;
|
||||
break;
|
||||
case "Overwrite":
|
||||
expressionData.Parameters[i].Blend = CubismParameterBlendMode.Override;
|
||||
break;
|
||||
default:
|
||||
expressionData.Parameters[i].Blend = CubismParameterBlendMode.Additive;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return expressionData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58229d41c24a7fb4aafd097ab43bcc2a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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 UnityEngine;
|
||||
|
||||
namespace Live2D.Cubism.Framework.Expression
|
||||
{
|
||||
public class CubismExpressionList : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Cubism expression objects.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public CubismExpressionData[] CubismExpressionObjects;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f401bb1c5c52514eba33c0c2ffdc8ff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
namespace Live2D.Cubism.Framework.Expression
|
||||
{
|
||||
/**
|
||||
* @brief Structure that allows parameters to have expression values to be applied.
|
||||
*/
|
||||
public struct CubismExpressionParameterValue
|
||||
{
|
||||
public CubismParameter Parameter; ///< Parameter id.
|
||||
public float AdditiveValue; ///< Additive value.
|
||||
public float MultiplyValue; ///< Multiply value.
|
||||
public float OverwriteValue; ///< Overwrite value.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72362d80f8b420a40b445bc1ebae1735
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* 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 Live2D.Cubism.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Live2D.Cubism.Framework.Expression
|
||||
{
|
||||
/// <summary>
|
||||
/// The cubism expression data.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class CubismPlayingExpression
|
||||
{
|
||||
#region variable
|
||||
|
||||
/// <summary>
|
||||
/// Expression type.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public string Type;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade in time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float FadeInTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade out time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float FadeOutTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression Weight.
|
||||
/// </summary>
|
||||
[SerializeField, Range(0.0f, 1.0f)]
|
||||
public float Weight;
|
||||
|
||||
/// <summary>
|
||||
/// Expression user time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float ExpressionUserTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression start time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float ExpressionStartTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression end time.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float ExpressionEndTime;
|
||||
|
||||
/// <summary>
|
||||
/// Expression parameters cache.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public CubismParameter[] Destinations;
|
||||
|
||||
/// <summary>
|
||||
/// Expression parameter value.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public float[] Value;
|
||||
|
||||
/// <summary>
|
||||
/// Expression parameter blend mode.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
public CubismParameterBlendMode[] Blend;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade weight.
|
||||
/// </summary>
|
||||
[NonSerialized, HideInInspector]
|
||||
public float FadeWeight;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade in weight.
|
||||
/// </summary>
|
||||
[NonSerialized, HideInInspector]
|
||||
public float FadeInWeight;
|
||||
|
||||
/// <summary>
|
||||
/// Expression fade out weight.
|
||||
/// </summary>
|
||||
[NonSerialized, HideInInspector]
|
||||
public float FadeOutWeight;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initialize expression data from <see cref="CubismExpressionData"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">model.</param>
|
||||
/// <param name="expressionData">Source.</param>
|
||||
public static CubismPlayingExpression Create(CubismModel model, CubismExpressionData expressionData)
|
||||
{
|
||||
// Fail silently...
|
||||
if(model == null || expressionData == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = new CubismPlayingExpression();
|
||||
|
||||
ret.Type = expressionData.Type;
|
||||
|
||||
ret.FadeInTime = (expressionData.FadeInTime < 0.0f)
|
||||
? 1.0f
|
||||
: expressionData.FadeInTime;
|
||||
|
||||
ret.FadeOutTime = (expressionData.FadeOutTime < 0.0f)
|
||||
? 1.0f
|
||||
: expressionData.FadeOutTime;
|
||||
|
||||
ret.Weight = 1.0f;
|
||||
ret.ExpressionUserTime = 0.0f;
|
||||
ret.ExpressionStartTime = 0.0f;
|
||||
ret.ExpressionEndTime = 0.0f;
|
||||
|
||||
var parameterCount = expressionData.Parameters.Length;
|
||||
ret.Destinations = new CubismParameter[parameterCount];
|
||||
ret.Value = new float[parameterCount];
|
||||
ret.Blend = new CubismParameterBlendMode[parameterCount];
|
||||
|
||||
for(var i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
ret.Destinations[i] = model.Parameters.FindById(expressionData.Parameters[i].Id);
|
||||
ret.Value[i] = expressionData.Parameters[i].Value;
|
||||
ret.Blend[i] = expressionData.Parameters[i].Blend;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 716fd6bb3f33dde4991e01d557f42482
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Live2D/Cubism/Framework/Expression/Editor.meta
Normal file
8
Assets/Live2D/Cubism/Framework/Expression/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cea1418493279242ace46ba3dae8f02
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* 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.Expression;
|
||||
using Live2D.Cubism.Framework.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Live2D.Cubism.Core;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Live2D.Cubism.Editor.Importers
|
||||
{
|
||||
public sealed class CubismExpression3JsonImporter : CubismImporterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="CubismPose3Json"/> backing field.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private CubismExp3Json _expressionJson;
|
||||
|
||||
private CubismExp3Json ExpressionJson
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_expressionJson != null)
|
||||
{
|
||||
return _expressionJson;
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(AssetPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var expressionJson = AssetDatabase.LoadAssetAtPath<TextAsset>((AssetPath));
|
||||
_expressionJson = CubismExp3Json.LoadFrom(expressionJson);
|
||||
|
||||
return _expressionJson;
|
||||
}
|
||||
}
|
||||
|
||||
#region Unity Event Handling
|
||||
|
||||
/// <summary>
|
||||
/// Registers importer.
|
||||
/// </summary>
|
||||
[InitializeOnLoadMethod]
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private static void RegisterImporter()
|
||||
{
|
||||
CubismImporter.RegisterImporter<CubismExpression3JsonImporter>(".exp3.json");
|
||||
CubismImporter.OnDidImportModel += OnModelImport;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cubism Import Event Handling
|
||||
|
||||
/// <summary>
|
||||
/// Imports the corresponding asset.
|
||||
/// </summary>
|
||||
public override void Import()
|
||||
{
|
||||
var oldExpressionData = AssetDatabase.LoadAssetAtPath<CubismExpressionData>(AssetPath.Replace(".exp3.json", ".exp3.asset"));
|
||||
|
||||
// Create expression data.
|
||||
CubismExpressionData expressionData;
|
||||
|
||||
if(oldExpressionData == null)
|
||||
{
|
||||
expressionData = CubismExpressionData.CreateInstance(ExpressionJson);
|
||||
AssetDatabase.CreateAsset(expressionData, AssetPath.Replace(".exp3.json", ".exp3.asset"));
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionData = CubismExpressionData.CreateInstance(oldExpressionData, ExpressionJson);
|
||||
EditorUtility.CopySerialized(expressionData, oldExpressionData);
|
||||
expressionData = oldExpressionData;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(expressionData);
|
||||
|
||||
// Add expression data to expression list.
|
||||
var directoryName = Path.GetDirectoryName(AssetPath);
|
||||
var modelDir = Path.GetDirectoryName(directoryName);
|
||||
var modelName = Path.GetFileName(modelDir);
|
||||
var expressionListPath = Path.GetDirectoryName(directoryName).Replace("\\", "/") + "/" + modelName + ".expressionList.asset";
|
||||
|
||||
var assetList = CubismCreatedAssetList.GetInstance();
|
||||
var assetListIndex = assetList.AssetPaths.Contains(expressionListPath)
|
||||
? assetList.AssetPaths.IndexOf(expressionListPath)
|
||||
: -1;
|
||||
|
||||
var expressionList = GetExpressionList(expressionListPath);
|
||||
|
||||
if (expressionList == null)
|
||||
{
|
||||
Debug.LogError("CubismExpression3JsonImporter : Can not create CubismExpressionList.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Rebuild the array if any element is null.
|
||||
if (expressionList.CubismExpressionObjects.Any(element => element == null))
|
||||
{
|
||||
var cubismExpressionObjectsToList = expressionList.CubismExpressionObjects.ToList();
|
||||
cubismExpressionObjectsToList.RemoveAll(element => element == null);
|
||||
|
||||
var expressionEqualityComparer = new ExpressionEqualityComparer();
|
||||
var expressionDistinctObjectsArray = cubismExpressionObjectsToList.Distinct(expressionEqualityComparer).ToArray();
|
||||
|
||||
expressionList.CubismExpressionObjects = new CubismExpressionData[0];
|
||||
Array.Resize(ref expressionList.CubismExpressionObjects, expressionDistinctObjectsArray.Length);
|
||||
|
||||
expressionList.CubismExpressionObjects = expressionDistinctObjectsArray;
|
||||
}
|
||||
|
||||
// Find index.
|
||||
var expressionName = Path.GetFileName(AssetPath).Replace(".json", "");
|
||||
var expressionIndex = -1;
|
||||
for (var i = 0; i < expressionList.CubismExpressionObjects.Length; ++i)
|
||||
{
|
||||
var expression = expressionList.CubismExpressionObjects[i];
|
||||
|
||||
if (expression.name != expressionName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
expressionIndex = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set expression data.
|
||||
if (expressionIndex != -1)
|
||||
{
|
||||
expressionList.CubismExpressionObjects[expressionIndex] = expressionData;
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionIndex = expressionList.CubismExpressionObjects.Length;
|
||||
Array.Resize(ref expressionList.CubismExpressionObjects, expressionIndex + 1);
|
||||
expressionList.CubismExpressionObjects[expressionIndex] = expressionData;
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(expressionList);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set expression list.
|
||||
/// </summary>
|
||||
/// <param name="importer">Event source.</param>
|
||||
/// <param name="model">Imported model.</param>
|
||||
private static void OnModelImport(CubismModel3JsonImporter importer, CubismModel model)
|
||||
{
|
||||
var expressionController = model.GetComponent<CubismExpressionController>();
|
||||
if (expressionController == null || importer.Model3Json.FileReferences.Expressions == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var modelDir = Path.GetDirectoryName(importer.AssetPath).Replace("\\","/");
|
||||
var modelName = Path.GetFileName(modelDir);
|
||||
var expressionListPath = modelDir + "/" + modelName + ".expressionList.asset";
|
||||
|
||||
var expressionList = GetExpressionList(expressionListPath);
|
||||
|
||||
if (expressionList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
expressionController.ExpressionsList = expressionList;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Load the .expressionList.
|
||||
/// If it does not exist, create a new one.
|
||||
/// </summary>
|
||||
/// <param name="expressionListPath">The path of the .expressionList.asset relative to the project.</param>
|
||||
/// <returns>.expressionList.asset</returns>
|
||||
private static CubismExpressionList GetExpressionList(string expressionListPath)
|
||||
{
|
||||
var assetList = CubismCreatedAssetList.GetInstance();
|
||||
var assetListIndex = assetList.AssetPaths.Contains(expressionListPath)
|
||||
? assetList.AssetPaths.IndexOf(expressionListPath)
|
||||
: -1;
|
||||
|
||||
CubismExpressionList expressionList = null;
|
||||
|
||||
if (assetListIndex < 0)
|
||||
{
|
||||
expressionList = AssetDatabase.LoadAssetAtPath<CubismExpressionList>(expressionListPath);
|
||||
|
||||
if (expressionList == null)
|
||||
{
|
||||
expressionList = ScriptableObject.CreateInstance<CubismExpressionList>();
|
||||
expressionList.CubismExpressionObjects = new CubismExpressionData[0];
|
||||
AssetDatabase.CreateAsset(expressionList, expressionListPath);
|
||||
}
|
||||
|
||||
assetList.Assets.Add(expressionList);
|
||||
assetList.AssetPaths.Add(expressionListPath);
|
||||
assetList.IsImporterDirties.Add(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
expressionList = (CubismExpressionList)assetList.Assets[assetListIndex];
|
||||
}
|
||||
|
||||
return expressionList;
|
||||
}
|
||||
|
||||
private class ExpressionEqualityComparer : IEqualityComparer<CubismExpressionData>
|
||||
{
|
||||
public bool Equals(CubismExpressionData x, CubismExpressionData y)
|
||||
{
|
||||
return x.name == y.name;
|
||||
}
|
||||
|
||||
public int GetHashCode(CubismExpressionData obj)
|
||||
{
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a096f2ae0a20faf4fa5a1b5539832b13
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:e5d337e0b3581c343aafde08e6e1727e"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c577e6f892ebd3c43a2ebf539ca10a09
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user