Update to Cubism 4 SDK for Web R1
This commit is contained in:
278
src/motion/acubismmotion.ts
Normal file
278
src/motion/acubismmotion.ts
Normal file
@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismmath } from '../math/cubismmath';
|
||||
import { Live2DCubismFramework as cubismmodel } from '../model/cubismmodel';
|
||||
import { Live2DCubismFramework as cubismmotionqueueentry } from './cubismmotionqueueentry';
|
||||
import { Live2DCubismFramework as csmstring } from '../type/csmstring';
|
||||
import { Live2DCubismFramework as csmvector } from '../type/csmvector';
|
||||
import { CSM_ASSERT } from '../utils/cubismdebug';
|
||||
import csmVector = csmvector.csmVector;
|
||||
import csmString = csmstring.csmString;
|
||||
import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import CubismMath = cubismmath.CubismMath;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/** モーション再生終了コールバック関数定義 */
|
||||
export type FinishedMotionCallback = (self: ACubismMotion) => void;
|
||||
|
||||
/**
|
||||
* モーションの抽象基底クラス
|
||||
*
|
||||
* モーションの抽象基底クラス。MotionQueueManagerによってモーションの再生を管理する。
|
||||
*/
|
||||
export abstract class ACubismMotion {
|
||||
/**
|
||||
* インスタンスの破棄
|
||||
*/
|
||||
public static delete(motion: ACubismMotion): void {
|
||||
motion.release();
|
||||
motion = void 0;
|
||||
motion = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
this._fadeInSeconds = -1.0;
|
||||
this._fadeOutSeconds = -1.0;
|
||||
this._weight = 1.0;
|
||||
this._offsetSeconds = 0.0; // 再生の開始時刻
|
||||
this._firedEventValues = new csmVector<csmString>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
this._weight = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータ
|
||||
* @param model 対象のモデル
|
||||
* @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
*/
|
||||
public updateParameters(
|
||||
model: CubismModel,
|
||||
motionQueueEntry: CubismMotionQueueEntry,
|
||||
userTimeSeconds: number
|
||||
): void {
|
||||
if (!motionQueueEntry.isAvailable() || motionQueueEntry.isFinished()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!motionQueueEntry.isStarted()) {
|
||||
motionQueueEntry.setIsStarted(true);
|
||||
motionQueueEntry.setStartTime(userTimeSeconds - this._offsetSeconds); // モーションの開始時刻を記録
|
||||
motionQueueEntry.setFadeInStartTime(userTimeSeconds); // フェードインの開始時刻
|
||||
|
||||
const duration: number = this.getDuration();
|
||||
|
||||
if (motionQueueEntry.getEndTime() < 0) {
|
||||
// 開始していないうちに終了設定している場合がある。
|
||||
motionQueueEntry.setEndTime(
|
||||
duration <= 0 ? -1 : motionQueueEntry.getStartTime() + duration
|
||||
);
|
||||
// duration == -1 の場合はループする
|
||||
}
|
||||
}
|
||||
|
||||
let fadeWeight: number = this._weight; // 現在の値と掛け合わせる割合
|
||||
|
||||
//---- フェードイン・アウトの処理 ----
|
||||
// 単純なサイン関数でイージングする
|
||||
const fadeIn: number =
|
||||
this._fadeInSeconds == 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(userTimeSeconds - motionQueueEntry.getFadeInStartTime()) /
|
||||
this._fadeInSeconds
|
||||
);
|
||||
|
||||
const fadeOut: number =
|
||||
this._fadeOutSeconds == 0.0 || motionQueueEntry.getEndTime() < 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(motionQueueEntry.getEndTime() - userTimeSeconds) /
|
||||
this._fadeOutSeconds
|
||||
);
|
||||
|
||||
fadeWeight = fadeWeight * fadeIn * fadeOut;
|
||||
|
||||
motionQueueEntry.setState(userTimeSeconds, fadeWeight);
|
||||
|
||||
CSM_ASSERT(0.0 <= fadeWeight && fadeWeight <= 1.0);
|
||||
|
||||
//---- 全てのパラメータIDをループする ----
|
||||
this.doUpdateParameters(
|
||||
model,
|
||||
userTimeSeconds,
|
||||
fadeWeight,
|
||||
motionQueueEntry
|
||||
);
|
||||
|
||||
// 後処理
|
||||
// 終了時刻を過ぎたら終了フラグを立てる(CubismMotionQueueManager)
|
||||
if (
|
||||
motionQueueEntry.getEndTime() > 0 &&
|
||||
motionQueueEntry.getEndTime() < userTimeSeconds
|
||||
) {
|
||||
motionQueueEntry.setIsFinished(true); // 終了
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインの時間を設定する
|
||||
* @param fadeInSeconds フェードインにかかる時間[秒]
|
||||
*/
|
||||
public setFadeInTime(fadeInSeconds: number): void {
|
||||
this._fadeInSeconds = fadeInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードアウトの時間を設定する
|
||||
* @param fadeOutSeconds フェードアウトにかかる時間[秒]
|
||||
*/
|
||||
public setFadeOutTime(fadeOutSeconds: number): void {
|
||||
this._fadeOutSeconds = fadeOutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードアウトにかかる時間の取得
|
||||
* @return フェードアウトにかかる時間[秒]
|
||||
*/
|
||||
public getFadeOutTime(): number {
|
||||
return this._fadeOutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインにかかる時間の取得
|
||||
* @return フェードインにかかる時間[秒]
|
||||
*/
|
||||
public getFadeInTime(): number {
|
||||
return this._fadeInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション適用の重みの設定
|
||||
* @param weight 重み(0.0 - 1.0)
|
||||
*/
|
||||
public setWeight(weight: number): void {
|
||||
this._weight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション適用の重みの取得
|
||||
* @return 重み(0.0 - 1.0)
|
||||
*/
|
||||
public getWeight(): number {
|
||||
return this._weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの長さの取得
|
||||
* @return モーションの長さ[秒]
|
||||
*
|
||||
* @note ループの時は「-1」。
|
||||
* ループでない場合は、オーバーライドする。
|
||||
* 正の値の時は取得される時間で終了する。
|
||||
* 「-1」の時は外部から停止命令がない限り終わらない処理となる。
|
||||
*/
|
||||
public getDuration(): number {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのループ1回分の長さの取得
|
||||
* @return モーションのループ一回分の長さ[秒]
|
||||
*
|
||||
* @note ループしない場合は、getDuration()と同じ値を返す
|
||||
* ループ一回分の長さが定義できない場合(プログラム的に動き続けるサブクラスなど)の場合は「-1」を返す
|
||||
*/
|
||||
public getLoopDuration(): number {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション再生の開始時刻の設定
|
||||
* @param offsetSeconds モーション再生の開始時刻[秒]
|
||||
*/
|
||||
public setOffsetTime(offsetSeconds: number): void {
|
||||
this._offsetSeconds = offsetSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータ更新
|
||||
*
|
||||
* イベント発火のチェック。
|
||||
* 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。
|
||||
*
|
||||
* @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒]
|
||||
* @param motionTimeSeconds 今回の再生時間[秒]
|
||||
*/
|
||||
public getFiredEvent(
|
||||
beforeCheckTimeSeconds: number,
|
||||
motionTimeSeconds: number
|
||||
): csmVector<csmString> {
|
||||
return this._firedEventValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションを更新して、モデルにパラメータ値を反映する
|
||||
* @param model 対象のモデル
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
* @param weight モーションの重み
|
||||
* @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||
* @return true モデルへパラメータ値の反映あり
|
||||
* @return false モデルへのパラメータ値の反映なし(モーションの変化なし)
|
||||
*/
|
||||
public abstract doUpdateParameters(
|
||||
model: CubismModel,
|
||||
userTimeSeconds: number,
|
||||
weight: number,
|
||||
motionQueueEntry: CubismMotionQueueEntry
|
||||
): void;
|
||||
|
||||
/**
|
||||
* モーション再生終了コールバックの登録
|
||||
*
|
||||
* モーション再生終了コールバックを登録する。
|
||||
* isFinishedフラグを設定するタイミングで呼び出される。
|
||||
* 以下の状態の際には呼び出されない:
|
||||
* 1. 再生中のモーションが「ループ」として設定されているとき
|
||||
* 2. コールバックが登録されていない時
|
||||
*
|
||||
* @param onFinishedMotionHandler モーション再生終了コールバック関数
|
||||
*/
|
||||
public setFinishedMotionHandler = (
|
||||
onFinishedMotionHandler: FinishedMotionCallback
|
||||
) => (this._onFinishedMotion = onFinishedMotionHandler);
|
||||
|
||||
/**
|
||||
* モーション再生終了コールバックの取得
|
||||
*
|
||||
* モーション再生終了コールバックを取得する。
|
||||
*
|
||||
* @return 登録されているモーション再生終了コールバック関数
|
||||
*/
|
||||
public getFinishedMotionHandler = () => this._onFinishedMotion;
|
||||
|
||||
public _fadeInSeconds: number; // フェードインにかかる時間[秒]
|
||||
public _fadeOutSeconds: number; // フェードアウトにかかる時間[秒]
|
||||
public _weight: number; // モーションの重み
|
||||
public _offsetSeconds: number; // モーション再生の開始時間[秒]
|
||||
|
||||
public _firedEventValues: csmVector<csmString>;
|
||||
|
||||
// モーション再生終了コールバック関数
|
||||
public _onFinishedMotion?: FinishedMotionCallback;
|
||||
}
|
||||
}
|
199
src/motion/cubismexpressionmotion.ts
Normal file
199
src/motion/cubismexpressionmotion.ts
Normal file
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as acubismmotion } from './acubismmotion';
|
||||
import { Live2DCubismFramework as cubismjson } from '../utils/cubismjson';
|
||||
import { Live2DCubismFramework as cubismid } from '../id/cubismid';
|
||||
import { Live2DCubismFramework as cubismframework } from '../live2dcubismframework';
|
||||
import { Live2DCubismFramework as cubismmodel } from '../model/cubismmodel';
|
||||
import { Live2DCubismFramework as cubismmotionqueueentry } from './cubismmotionqueueentry';
|
||||
import { Live2DCubismFramework as csmvector } from '../type/csmvector';
|
||||
import JsonFloat = cubismjson.JsonFloat;
|
||||
import csmVector = csmvector.csmVector;
|
||||
import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import CubismFramework = cubismframework.CubismFramework;
|
||||
import CubismIdHandle = cubismid.CubismIdHandle;
|
||||
import CubismJson = cubismjson.CubismJson;
|
||||
import Value = cubismjson.Value;
|
||||
import ACubismMotion = acubismmotion.ACubismMotion;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
// exp3.jsonのキーとデフォルト
|
||||
const ExpressionKeyFadeIn = 'FadeInTime';
|
||||
const ExpressionKeyFadeOut = 'FadeOutTime';
|
||||
const ExpressionKeyParameters = 'Parameters';
|
||||
const ExpressionKeyId = 'Id';
|
||||
const ExpressionKeyValue = 'Value';
|
||||
const ExpressionKeyBlend = 'Blend';
|
||||
const BlendValueAdd = 'Add';
|
||||
const BlendValueMultiply = 'Multiply';
|
||||
const BlendValueOverwrite = 'Overwrite';
|
||||
const DefaultFadeTime = 1.0;
|
||||
|
||||
/**
|
||||
* 表情のモーション
|
||||
*
|
||||
* 表情のモーションクラス。
|
||||
*/
|
||||
export class CubismExpressionMotion extends ACubismMotion {
|
||||
/**
|
||||
* インスタンスを作成する。
|
||||
* @param buffer expファイルが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(
|
||||
buffer: ArrayBuffer,
|
||||
size: number
|
||||
): CubismExpressionMotion {
|
||||
const expression: CubismExpressionMotion = new CubismExpressionMotion();
|
||||
|
||||
const json: CubismJson = CubismJson.create(buffer, size);
|
||||
const root: Value = json.getRoot();
|
||||
|
||||
expression.setFadeInTime(
|
||||
root.getValueByString(ExpressionKeyFadeIn).toFloat(DefaultFadeTime)
|
||||
); // フェードイン
|
||||
expression.setFadeOutTime(
|
||||
root.getValueByString(ExpressionKeyFadeOut).toFloat(DefaultFadeTime)
|
||||
); // フェードアウト
|
||||
|
||||
// 各パラメータについて
|
||||
const parameterCount = root
|
||||
.getValueByString(ExpressionKeyParameters)
|
||||
.getSize();
|
||||
expression._parameters.prepareCapacity(parameterCount);
|
||||
|
||||
for (let i = 0; i < parameterCount; ++i) {
|
||||
const param: Value = root
|
||||
.getValueByString(ExpressionKeyParameters)
|
||||
.getValueByIndex(i);
|
||||
const parameterId: CubismIdHandle = CubismFramework.getIdManager().getId(
|
||||
param.getValueByString(ExpressionKeyId).getRawString()
|
||||
); // パラメータID
|
||||
|
||||
const value: number = param
|
||||
.getValueByString(ExpressionKeyValue)
|
||||
.toFloat(); // 値
|
||||
|
||||
// 計算方法の設定
|
||||
let blendType: ExpressionBlendType;
|
||||
|
||||
if (
|
||||
param.getValueByString(ExpressionKeyBlend).isNull() ||
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueAdd
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Add;
|
||||
} else if (
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueMultiply
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Multiply;
|
||||
} else if (
|
||||
param.getValueByString(ExpressionKeyBlend).getString() ==
|
||||
BlendValueOverwrite
|
||||
) {
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Overwrite;
|
||||
} else {
|
||||
// その他 仕様にない値を設定した時は加算モードにすることで復旧
|
||||
blendType = ExpressionBlendType.ExpressionBlendType_Add;
|
||||
}
|
||||
|
||||
// 設定オブジェクトを作成してリストに追加する
|
||||
const item: ExpressionParameter = new ExpressionParameter();
|
||||
|
||||
item.parameterId = parameterId;
|
||||
item.blendType = blendType;
|
||||
item.value = value;
|
||||
|
||||
expression._parameters.pushBack(item);
|
||||
}
|
||||
|
||||
CubismJson.delete(json); // JSONデータは不要になったら削除する
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータの更新の実行
|
||||
* @param model 対象のモデル
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
* @param weight モーションの重み
|
||||
* @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||
*/
|
||||
public doUpdateParameters(
|
||||
model: CubismModel,
|
||||
userTimeSeconds: number,
|
||||
weight: number,
|
||||
motionQueueEntry: CubismMotionQueueEntry
|
||||
): void {
|
||||
for (let i = 0; i < this._parameters.getSize(); ++i) {
|
||||
const parameter: ExpressionParameter = this._parameters.at(i);
|
||||
|
||||
switch (parameter.blendType) {
|
||||
case ExpressionBlendType.ExpressionBlendType_Add: {
|
||||
model.addParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ExpressionBlendType.ExpressionBlendType_Multiply: {
|
||||
model.multiplyParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
case ExpressionBlendType.ExpressionBlendType_Overwrite: {
|
||||
model.setParameterValueById(
|
||||
parameter.parameterId,
|
||||
parameter.value,
|
||||
weight
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// 仕様にない値を設定した時はすでに加算モードになっている
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this._parameters = new csmVector<ExpressionParameter>();
|
||||
}
|
||||
|
||||
_parameters: csmVector<ExpressionParameter>; // 表情のパラメータ情報リスト
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情パラメータ値の計算方式
|
||||
*/
|
||||
export enum ExpressionBlendType {
|
||||
ExpressionBlendType_Add = 0, // 加算
|
||||
ExpressionBlendType_Multiply = 1, // 乗算
|
||||
ExpressionBlendType_Overwrite = 2 // 上書き
|
||||
}
|
||||
|
||||
/**
|
||||
* 表情のパラメータ情報
|
||||
*/
|
||||
export class ExpressionParameter {
|
||||
parameterId: CubismIdHandle; // パラメータID
|
||||
blendType: ExpressionBlendType; // パラメータの演算種類
|
||||
value: number; // 値
|
||||
}
|
||||
}
|
945
src/motion/cubismmotion.ts
Normal file
945
src/motion/cubismmotion.ts
Normal file
@ -0,0 +1,945 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismmotionjson } from './cubismmotionjson';
|
||||
import { Live2DCubismFramework as cubismmotioninternal } from './cubismmotioninternal';
|
||||
import { Live2DCubismFramework as acubismmotion } from './acubismmotion';
|
||||
import { Live2DCubismFramework as cubismmodel } from '../model/cubismmodel';
|
||||
import { Live2DCubismFramework as cubismframework } from '../live2dcubismframework';
|
||||
import { Live2DCubismFramework as cubismmotionqueueentry } from './cubismmotionqueueentry';
|
||||
import { Live2DCubismFramework as cubismmath } from '../math/cubismmath';
|
||||
import { Live2DCubismFramework as csmvector } from '../type/csmvector';
|
||||
import { Live2DCubismFramework as cubismid } from '../id/cubismid';
|
||||
import { Live2DCubismFramework as csmstring } from '../type/csmstring';
|
||||
import { CubismLogDebug, CSM_ASSERT } from '../utils/cubismdebug';
|
||||
import csmString = csmstring.csmString;
|
||||
import CubismMotionData = cubismmotioninternal.CubismMotionData;
|
||||
import CubismMotionSegment = cubismmotioninternal.CubismMotionSegment;
|
||||
import CubismMotionPoint = cubismmotioninternal.CubismMotionPoint;
|
||||
import CubismMotionEvent = cubismmotioninternal.CubismMotionEvent;
|
||||
import CubismMotionSegmentType = cubismmotioninternal.CubismMotionSegmentType;
|
||||
import CubismIdHandle = cubismid.CubismIdHandle;
|
||||
import CubismMotionCurve = cubismmotioninternal.CubismMotionCurve;
|
||||
import CubismMotionCurveTarget = cubismmotioninternal.CubismMotionCurveTarget;
|
||||
import csmVector = csmvector.csmVector;
|
||||
import CubismMath = cubismmath.CubismMath;
|
||||
import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry;
|
||||
import CubismFramework = cubismframework.CubismFramework;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import ACubismMotion = acubismmotion.ACubismMotion;
|
||||
import FinishedMotionCallback = acubismmotion.FinishedMotionCallback;
|
||||
import CubismMotionJson = cubismmotionjson.CubismMotionJson;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
const EffectNameEyeBlink = 'EyeBlink';
|
||||
const EffectNameLipSync = 'LipSync';
|
||||
const TargetNameModel = 'Model';
|
||||
const TargetNameParameter = 'Parameter';
|
||||
const TargetNamePartOpacity = 'PartOpacity';
|
||||
|
||||
function lerpPoints(
|
||||
a: CubismMotionPoint,
|
||||
b: CubismMotionPoint,
|
||||
t: number
|
||||
): CubismMotionPoint {
|
||||
const result: CubismMotionPoint = new CubismMotionPoint();
|
||||
|
||||
result.time = a.time + (b.time - a.time) * t;
|
||||
result.value = a.value + (b.value - a.value) * t;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function linearEvaluate(points: CubismMotionPoint[], time: number): number {
|
||||
let t: number = (time - points[0].time) / (points[1].time - points[0].time);
|
||||
|
||||
if (t < 0.0) {
|
||||
t = 0.0;
|
||||
}
|
||||
|
||||
return points[0].value + (points[1].value - points[0].value) * t;
|
||||
}
|
||||
|
||||
function bezierEvaluate(points: CubismMotionPoint[], time: number): number {
|
||||
let t: number = (time - points[0].time) / (points[3].time - points[0].time);
|
||||
|
||||
if (t < 0.0) {
|
||||
t = 0.0;
|
||||
}
|
||||
|
||||
const p01: CubismMotionPoint = lerpPoints(points[0], points[1], t);
|
||||
const p12: CubismMotionPoint = lerpPoints(points[1], points[2], t);
|
||||
const p23: CubismMotionPoint = lerpPoints(points[2], points[3], t);
|
||||
|
||||
const p012: CubismMotionPoint = lerpPoints(p01, p12, t);
|
||||
const p123: CubismMotionPoint = lerpPoints(p12, p23, t);
|
||||
|
||||
return lerpPoints(p012, p123, t).value;
|
||||
}
|
||||
|
||||
function steppedEvaluate(points: CubismMotionPoint[], time: number): number {
|
||||
return points[0].value;
|
||||
}
|
||||
|
||||
function inverseSteppedEvaluate(
|
||||
points: CubismMotionPoint[],
|
||||
time: number
|
||||
): number {
|
||||
return points[1].value;
|
||||
}
|
||||
|
||||
function evaluateCurve(
|
||||
motionData: CubismMotionData,
|
||||
index: number,
|
||||
time: number
|
||||
): number {
|
||||
// Find segment to evaluate.
|
||||
const curve: CubismMotionCurve = motionData.curves.at(index);
|
||||
|
||||
let target = -1;
|
||||
const totalSegmentCount: number =
|
||||
curve.baseSegmentIndex + curve.segmentCount;
|
||||
let pointPosition = 0;
|
||||
for (let i: number = curve.baseSegmentIndex; i < totalSegmentCount; ++i) {
|
||||
// Get first point of next segment.
|
||||
pointPosition =
|
||||
motionData.segments.at(i).basePointIndex +
|
||||
(motionData.segments.at(i).segmentType ==
|
||||
CubismMotionSegmentType.CubismMotionSegmentType_Bezier
|
||||
? 3
|
||||
: 1);
|
||||
|
||||
// Break if time lies within current segment.
|
||||
if (motionData.points.at(pointPosition).time > time) {
|
||||
target = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target == -1) {
|
||||
return motionData.points.at(pointPosition).value;
|
||||
}
|
||||
|
||||
const segment: CubismMotionSegment = motionData.segments.at(target);
|
||||
|
||||
return segment.evaluate(
|
||||
motionData.points.get(segment.basePointIndex),
|
||||
time
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションクラス
|
||||
*
|
||||
* モーションのクラス。
|
||||
*/
|
||||
export class CubismMotion extends ACubismMotion {
|
||||
/**
|
||||
* インスタンスを作成する
|
||||
*
|
||||
* @param buffer motion3.jsonが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
* @param onFinishedMotionHandler モーション再生終了時に呼び出されるコールバック関数
|
||||
* @return 作成されたインスタンス
|
||||
*/
|
||||
public static create(
|
||||
buffer: ArrayBuffer,
|
||||
size: number,
|
||||
onFinishedMotionHandler?: FinishedMotionCallback
|
||||
): CubismMotion {
|
||||
const ret = new CubismMotion();
|
||||
|
||||
ret.parse(buffer, size);
|
||||
ret._sourceFrameRate = ret._motionData.fps;
|
||||
ret._loopDurationSeconds = ret._motionData.duration;
|
||||
ret._onFinishedMotion = onFinishedMotionHandler;
|
||||
|
||||
// NOTE: Editorではループありのモーション書き出しは非対応
|
||||
// ret->_loop = (ret->_motionData->Loop > 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータの更新の実行
|
||||
* @param model 対象のモデル
|
||||
* @param userTimeSeconds 現在の時刻[秒]
|
||||
* @param fadeWeight モーションの重み
|
||||
* @param motionQueueEntry CubismMotionQueueManagerで管理されているモーション
|
||||
*/
|
||||
public doUpdateParameters(
|
||||
model: CubismModel,
|
||||
userTimeSeconds: number,
|
||||
fadeWeight: number,
|
||||
motionQueueEntry: CubismMotionQueueEntry
|
||||
): void {
|
||||
if (this._modelCurveIdEyeBlink == null) {
|
||||
this._modelCurveIdEyeBlink = CubismFramework.getIdManager().getId(
|
||||
EffectNameEyeBlink
|
||||
);
|
||||
}
|
||||
|
||||
if (this._modelCurveIdLipSync == null) {
|
||||
this._modelCurveIdLipSync = CubismFramework.getIdManager().getId(
|
||||
EffectNameLipSync
|
||||
);
|
||||
}
|
||||
|
||||
let timeOffsetSeconds: number =
|
||||
userTimeSeconds - motionQueueEntry.getStartTime();
|
||||
|
||||
if (timeOffsetSeconds < 0.0) {
|
||||
timeOffsetSeconds = 0.0; // エラー回避
|
||||
}
|
||||
|
||||
let lipSyncValue: number = Number.MAX_VALUE;
|
||||
let eyeBlinkValue: number = Number.MAX_VALUE;
|
||||
|
||||
//まばたき、リップシンクのうちモーションの適用を検出するためのビット(maxFlagCount個まで
|
||||
const MaxTargetSize = 64;
|
||||
let lipSyncFlags = 0;
|
||||
let eyeBlinkFlags = 0;
|
||||
|
||||
//瞬き、リップシンクのターゲット数が上限を超えている場合
|
||||
if (this._eyeBlinkParameterIds.getSize() > MaxTargetSize) {
|
||||
CubismLogDebug(
|
||||
'too many eye blink targets : {0}',
|
||||
this._eyeBlinkParameterIds.getSize()
|
||||
);
|
||||
}
|
||||
if (this._lipSyncParameterIds.getSize() > MaxTargetSize) {
|
||||
CubismLogDebug(
|
||||
'too many lip sync targets : {0}',
|
||||
this._lipSyncParameterIds.getSize()
|
||||
);
|
||||
}
|
||||
|
||||
const tmpFadeIn: number =
|
||||
this._fadeInSeconds <= 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(userTimeSeconds - motionQueueEntry.getFadeInStartTime()) /
|
||||
this._fadeInSeconds
|
||||
);
|
||||
|
||||
const tmpFadeOut: number =
|
||||
this._fadeOutSeconds <= 0.0 || motionQueueEntry.getEndTime() < 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(motionQueueEntry.getEndTime() - userTimeSeconds) /
|
||||
this._fadeOutSeconds
|
||||
);
|
||||
let value: number;
|
||||
let c: number, parameterIndex: number;
|
||||
|
||||
// 'Repeat' time as necessary.
|
||||
let time: number = timeOffsetSeconds;
|
||||
|
||||
if (this._isLoop) {
|
||||
while (time > this._motionData.duration) {
|
||||
time -= this._motionData.duration;
|
||||
}
|
||||
}
|
||||
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
// Evaluate model curves.
|
||||
for (
|
||||
c = 0;
|
||||
c < this._motionData.curveCount &&
|
||||
curves.at(c).type ==
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_Model;
|
||||
++c
|
||||
) {
|
||||
// Evaluate curve and call handler.
|
||||
value = evaluateCurve(this._motionData, c, time);
|
||||
|
||||
if (curves.at(c).id == this._modelCurveIdEyeBlink) {
|
||||
eyeBlinkValue = value;
|
||||
} else if (curves.at(c).id == this._modelCurveIdLipSync) {
|
||||
lipSyncValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
let parameterMotionCurveCount = 0;
|
||||
|
||||
for (
|
||||
;
|
||||
c < this._motionData.curveCount &&
|
||||
curves.at(c).type ==
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter;
|
||||
++c
|
||||
) {
|
||||
parameterMotionCurveCount++;
|
||||
|
||||
// Find parameter index.
|
||||
parameterIndex = model.getParameterIndex(curves.at(c).id);
|
||||
|
||||
// Skip curve evaluation if no value in sink.
|
||||
if (parameterIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const sourceValue: number = model.getParameterValueByIndex(
|
||||
parameterIndex
|
||||
);
|
||||
|
||||
// Evaluate curve and apply value.
|
||||
value = evaluateCurve(this._motionData, c, time);
|
||||
|
||||
if (eyeBlinkValue != Number.MAX_VALUE) {
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize;
|
||||
++i
|
||||
) {
|
||||
if (this._eyeBlinkParameterIds.at(i) == curves.at(c).id) {
|
||||
value *= eyeBlinkValue;
|
||||
eyeBlinkFlags |= 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lipSyncValue != Number.MAX_VALUE) {
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize;
|
||||
++i
|
||||
) {
|
||||
if (this._lipSyncParameterIds.at(i) == curves.at(c).id) {
|
||||
value += lipSyncValue;
|
||||
lipSyncFlags |= 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let v: number;
|
||||
|
||||
// パラメータごとのフェード
|
||||
if (curves.at(c).fadeInTime < 0.0 && curves.at(c).fadeOutTime < 0.0) {
|
||||
// モーションのフェードを適用
|
||||
v = sourceValue + (value - sourceValue) * fadeWeight;
|
||||
} else {
|
||||
// パラメータに対してフェードインかフェードアウトが設定してある場合はそちらを適用
|
||||
let fin: number;
|
||||
let fout: number;
|
||||
|
||||
if (curves.at(c).fadeInTime < 0.0) {
|
||||
fin = tmpFadeIn;
|
||||
} else {
|
||||
fin =
|
||||
curves.at(c).fadeInTime == 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(userTimeSeconds - motionQueueEntry.getFadeInStartTime()) /
|
||||
curves.at(c).fadeInTime
|
||||
);
|
||||
}
|
||||
|
||||
if (curves.at(c).fadeOutTime < 0.0) {
|
||||
fout = tmpFadeOut;
|
||||
} else {
|
||||
fout =
|
||||
curves.at(c).fadeOutTime == 0.0 ||
|
||||
motionQueueEntry.getEndTime() < 0.0
|
||||
? 1.0
|
||||
: CubismMath.getEasingSine(
|
||||
(motionQueueEntry.getEndTime() - userTimeSeconds) /
|
||||
curves.at(c).fadeOutTime
|
||||
);
|
||||
}
|
||||
|
||||
const paramWeight: number = this._weight * fin * fout;
|
||||
|
||||
// パラメータごとのフェードを適用
|
||||
v = sourceValue + (value - sourceValue) * paramWeight;
|
||||
}
|
||||
|
||||
model.setParameterValueByIndex(parameterIndex, v, 1.0);
|
||||
}
|
||||
|
||||
{
|
||||
if (eyeBlinkValue != Number.MAX_VALUE) {
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._eyeBlinkParameterIds.getSize() && i < MaxTargetSize;
|
||||
++i
|
||||
) {
|
||||
const sourceValue: number = model.getParameterValueById(
|
||||
this._eyeBlinkParameterIds.at(i)
|
||||
);
|
||||
|
||||
// モーションでの上書きがあった時にはまばたきは適用しない
|
||||
if ((eyeBlinkFlags >> i) & 0x01) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const v: number =
|
||||
sourceValue + (eyeBlinkValue - sourceValue) * fadeWeight;
|
||||
|
||||
model.setParameterValueById(this._eyeBlinkParameterIds.at(i), v);
|
||||
}
|
||||
}
|
||||
|
||||
if (lipSyncValue != Number.MAX_VALUE) {
|
||||
for (
|
||||
let i = 0;
|
||||
i < this._lipSyncParameterIds.getSize() && i < MaxTargetSize;
|
||||
++i
|
||||
) {
|
||||
const sourceValue: number = model.getParameterValueById(
|
||||
this._lipSyncParameterIds.at(i)
|
||||
);
|
||||
|
||||
// モーションでの上書きがあった時にはリップシンクは適用しない
|
||||
if ((lipSyncFlags >> i) & 0x01) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const v: number =
|
||||
sourceValue + (lipSyncValue - sourceValue) * fadeWeight;
|
||||
|
||||
model.setParameterValueById(this._lipSyncParameterIds.at(i), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (
|
||||
;
|
||||
c < this._motionData.curveCount &&
|
||||
curves.at(c).type ==
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity;
|
||||
++c
|
||||
) {
|
||||
// Find parameter index.
|
||||
parameterIndex = model.getParameterIndex(curves.at(c).id);
|
||||
|
||||
// Skip curve evaluation if no value in sink.
|
||||
if (parameterIndex == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Evaluate curve and apply value.
|
||||
value = evaluateCurve(this._motionData, c, time);
|
||||
|
||||
model.setParameterValueByIndex(parameterIndex, value);
|
||||
}
|
||||
|
||||
if (timeOffsetSeconds >= this._motionData.duration) {
|
||||
if (this._isLoop) {
|
||||
motionQueueEntry.setStartTime(userTimeSeconds); // 最初の状態へ
|
||||
if (this._isLoopFadeIn) {
|
||||
// ループ内でループ用フェードインが有効の時は、フェードイン設定し直し
|
||||
motionQueueEntry.setFadeInStartTime(userTimeSeconds);
|
||||
}
|
||||
} else {
|
||||
if (this._onFinishedMotion) {
|
||||
this._onFinishedMotion(this);
|
||||
}
|
||||
|
||||
motionQueueEntry.setIsFinished(true);
|
||||
}
|
||||
}
|
||||
this._lastWeight = fadeWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* ループ情報の設定
|
||||
* @param loop ループ情報
|
||||
*/
|
||||
public setIsLoop(loop: boolean): void {
|
||||
this._isLoop = loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* ループ情報の取得
|
||||
* @return true ループする
|
||||
* @return false ループしない
|
||||
*/
|
||||
public isLoop(): boolean {
|
||||
return this._isLoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* ループ時のフェードイン情報の設定
|
||||
* @param loopFadeIn ループ時のフェードイン情報
|
||||
*/
|
||||
public setIsLoopFadeIn(loopFadeIn: boolean): void {
|
||||
this._isLoopFadeIn = loopFadeIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* ループ時のフェードイン情報の取得
|
||||
*
|
||||
* @return true する
|
||||
* @return false しない
|
||||
*/
|
||||
public isLoopFadeIn(): boolean {
|
||||
return this._isLoopFadeIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの長さを取得する。
|
||||
*
|
||||
* @return モーションの長さ[秒]
|
||||
*/
|
||||
public getDuration(): number {
|
||||
return this._isLoop ? -1.0 : this._loopDurationSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのループ時の長さを取得する。
|
||||
*
|
||||
* @return モーションのループ時の長さ[秒]
|
||||
*/
|
||||
public getLoopDuration(): number {
|
||||
return this._loopDurationSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータに対するフェードインの時間を設定する。
|
||||
*
|
||||
* @param parameterId パラメータID
|
||||
* @param value フェードインにかかる時間[秒]
|
||||
*/
|
||||
public setParameterFadeInTime(
|
||||
parameterId: CubismIdHandle,
|
||||
value: number
|
||||
): void {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 0; i < this._motionData.curveCount; ++i) {
|
||||
if (parameterId == curves.at(i).id) {
|
||||
curves.at(i).fadeInTime = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータに対するフェードアウトの時間の設定
|
||||
* @param parameterId パラメータID
|
||||
* @param value フェードアウトにかかる時間[秒]
|
||||
*/
|
||||
public setParameterFadeOutTime(
|
||||
parameterId: CubismIdHandle,
|
||||
value: number
|
||||
): void {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 0; i < this._motionData.curveCount; ++i) {
|
||||
if (parameterId == curves.at(i).id) {
|
||||
curves.at(i).fadeOutTime = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータに対するフェードインの時間の取得
|
||||
* @param parameterId パラメータID
|
||||
* @return フェードインにかかる時間[秒]
|
||||
*/
|
||||
public getParameterFadeInTime(parameterId: CubismIdHandle): number {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 0; i < this._motionData.curveCount; ++i) {
|
||||
if (parameterId == curves.at(i).id) {
|
||||
return curves.at(i).fadeInTime;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* パラメータに対するフェードアウトの時間を取得
|
||||
*
|
||||
* @param parameterId パラメータID
|
||||
* @return フェードアウトにかかる時間[秒]
|
||||
*/
|
||||
public getParameterFadeOutTime(parameterId: CubismIdHandle): number {
|
||||
const curves: csmVector<CubismMotionCurve> = this._motionData.curves;
|
||||
|
||||
for (let i = 0; i < this._motionData.curveCount; ++i) {
|
||||
if (parameterId == curves.at(i).id) {
|
||||
return curves.at(i).fadeOutTime;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自動エフェクトがかかっているパラメータIDリストの設定
|
||||
* @param eyeBlinkParameterIds 自動まばたきがかかっているパラメータIDのリスト
|
||||
* @param lipSyncParameterIds リップシンクがかかっているパラメータIDのリスト
|
||||
*/
|
||||
public setEffectIds(
|
||||
eyeBlinkParameterIds: csmVector<CubismIdHandle>,
|
||||
lipSyncParameterIds: csmVector<CubismIdHandle>
|
||||
): void {
|
||||
this._eyeBlinkParameterIds = eyeBlinkParameterIds;
|
||||
this._lipSyncParameterIds = lipSyncParameterIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
super();
|
||||
this._sourceFrameRate = 30.0;
|
||||
this._loopDurationSeconds = -1.0;
|
||||
this._isLoop = false; // trueから false へデフォルトを変更
|
||||
this._isLoopFadeIn = true; // ループ時にフェードインが有効かどうかのフラグ
|
||||
this._lastWeight = 0.0;
|
||||
this._motionData = null;
|
||||
this._modelCurveIdEyeBlink = null;
|
||||
this._modelCurveIdLipSync = null;
|
||||
this._eyeBlinkParameterIds = null;
|
||||
this._lipSyncParameterIds = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
this._motionData = void 0;
|
||||
this._motionData = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* motion3.jsonをパースする。
|
||||
*
|
||||
* @param motionJson motion3.jsonが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
*/
|
||||
public parse(motionJson: ArrayBuffer, size: number): void {
|
||||
this._motionData = new CubismMotionData();
|
||||
|
||||
let json: CubismMotionJson = new CubismMotionJson(motionJson, size);
|
||||
|
||||
this._motionData.duration = json.getMotionDuration();
|
||||
this._motionData.loop = json.isMotionLoop();
|
||||
this._motionData.curveCount = json.getMotionCurveCount();
|
||||
this._motionData.fps = json.getMotionFps();
|
||||
this._motionData.eventCount = json.getEventCount();
|
||||
|
||||
if (json.isExistMotionFadeInTime()) {
|
||||
this._fadeInSeconds =
|
||||
json.getMotionFadeInTime() < 0.0 ? 1.0 : json.getMotionFadeInTime();
|
||||
} else {
|
||||
this._fadeInSeconds = 1.0;
|
||||
}
|
||||
|
||||
if (json.isExistMotionFadeOutTime()) {
|
||||
this._fadeOutSeconds =
|
||||
json.getMotionFadeOutTime() < 0.0 ? 1.0 : json.getMotionFadeOutTime();
|
||||
} else {
|
||||
this._fadeOutSeconds = 1.0;
|
||||
}
|
||||
|
||||
this._motionData.curves.updateSize(
|
||||
this._motionData.curveCount,
|
||||
CubismMotionCurve,
|
||||
true
|
||||
);
|
||||
this._motionData.segments.updateSize(
|
||||
json.getMotionTotalSegmentCount(),
|
||||
CubismMotionSegment,
|
||||
true
|
||||
);
|
||||
this._motionData.points.updateSize(
|
||||
json.getMotionTotalPointCount(),
|
||||
CubismMotionPoint,
|
||||
true
|
||||
);
|
||||
this._motionData.events.updateSize(
|
||||
this._motionData.eventCount,
|
||||
CubismMotionEvent,
|
||||
true
|
||||
);
|
||||
|
||||
let totalPointCount = 0;
|
||||
let totalSegmentCount = 0;
|
||||
|
||||
// Curves
|
||||
for (
|
||||
let curveCount = 0;
|
||||
curveCount < this._motionData.curveCount;
|
||||
++curveCount
|
||||
) {
|
||||
if (json.getMotionCurveTarget(curveCount) == TargetNameModel) {
|
||||
this._motionData.curves.at(curveCount).type =
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_Model;
|
||||
} else if (
|
||||
json.getMotionCurveTarget(curveCount) == TargetNameParameter
|
||||
) {
|
||||
this._motionData.curves.at(curveCount).type =
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_Parameter;
|
||||
} else if (
|
||||
json.getMotionCurveTarget(curveCount) == TargetNamePartOpacity
|
||||
) {
|
||||
this._motionData.curves.at(curveCount).type =
|
||||
CubismMotionCurveTarget.CubismMotionCurveTarget_PartOpacity;
|
||||
}
|
||||
|
||||
this._motionData.curves.at(curveCount).id = json.getMotionCurveId(
|
||||
curveCount
|
||||
);
|
||||
|
||||
this._motionData.curves.at(
|
||||
curveCount
|
||||
).baseSegmentIndex = totalSegmentCount;
|
||||
|
||||
this._motionData.curves.at(
|
||||
curveCount
|
||||
).fadeInTime = json.isExistMotionCurveFadeInTime(curveCount)
|
||||
? json.getMotionCurveFadeInTime(curveCount)
|
||||
: -1.0;
|
||||
this._motionData.curves.at(
|
||||
curveCount
|
||||
).fadeOutTime = json.isExistMotionCurveFadeOutTime(curveCount)
|
||||
? json.getMotionCurveFadeOutTime(curveCount)
|
||||
: -1.0;
|
||||
|
||||
// Segments
|
||||
for (
|
||||
let segmentPosition = 0;
|
||||
segmentPosition < json.getMotionCurveSegmentCount(curveCount);
|
||||
|
||||
) {
|
||||
if (segmentPosition == 0) {
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).basePointIndex = totalPointCount;
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(curveCount, segmentPosition);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
|
||||
totalPointCount += 1;
|
||||
segmentPosition += 2;
|
||||
} else {
|
||||
this._motionData.segments.at(totalSegmentCount).basePointIndex =
|
||||
totalPointCount - 1;
|
||||
}
|
||||
|
||||
const segment: number = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition
|
||||
);
|
||||
switch (segment) {
|
||||
case CubismMotionSegmentType.CubismMotionSegmentType_Linear: {
|
||||
this._motionData.segments.at(totalSegmentCount).segmentType =
|
||||
CubismMotionSegmentType.CubismMotionSegmentType_Linear;
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).evaluate = linearEvaluate;
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 2
|
||||
);
|
||||
|
||||
totalPointCount += 1;
|
||||
segmentPosition += 3;
|
||||
|
||||
break;
|
||||
}
|
||||
case CubismMotionSegmentType.CubismMotionSegmentType_Bezier: {
|
||||
this._motionData.segments.at(totalSegmentCount).segmentType =
|
||||
CubismMotionSegmentType.CubismMotionSegmentType_Bezier;
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).evaluate = bezierEvaluate;
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 2
|
||||
);
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 1
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 3
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 1
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 4
|
||||
);
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 2
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 5
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount + 2
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 6
|
||||
);
|
||||
|
||||
totalPointCount += 3;
|
||||
segmentPosition += 7;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CubismMotionSegmentType.CubismMotionSegmentType_Stepped: {
|
||||
this._motionData.segments.at(totalSegmentCount).segmentType =
|
||||
CubismMotionSegmentType.CubismMotionSegmentType_Stepped;
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).evaluate = steppedEvaluate;
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 2
|
||||
);
|
||||
|
||||
totalPointCount += 1;
|
||||
segmentPosition += 3;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped: {
|
||||
this._motionData.segments.at(totalSegmentCount).segmentType =
|
||||
CubismMotionSegmentType.CubismMotionSegmentType_InverseStepped;
|
||||
this._motionData.segments.at(
|
||||
totalSegmentCount
|
||||
).evaluate = inverseSteppedEvaluate;
|
||||
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).time = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 1
|
||||
);
|
||||
this._motionData.points.at(
|
||||
totalPointCount
|
||||
).value = json.getMotionCurveSegment(
|
||||
curveCount,
|
||||
segmentPosition + 2
|
||||
);
|
||||
|
||||
totalPointCount += 1;
|
||||
segmentPosition += 3;
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
CSM_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++this._motionData.curves.at(curveCount).segmentCount;
|
||||
++totalSegmentCount;
|
||||
}
|
||||
}
|
||||
|
||||
for (
|
||||
let userdatacount = 0;
|
||||
userdatacount < json.getEventCount();
|
||||
++userdatacount
|
||||
) {
|
||||
this._motionData.events.at(userdatacount).fireTime = json.getEventTime(
|
||||
userdatacount
|
||||
);
|
||||
this._motionData.events.at(userdatacount).value = json.getEventValue(
|
||||
userdatacount
|
||||
);
|
||||
}
|
||||
|
||||
json.release();
|
||||
json = void 0;
|
||||
json = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* モデルのパラメータ更新
|
||||
*
|
||||
* イベント発火のチェック。
|
||||
* 入力する時間は呼ばれるモーションタイミングを0とした秒数で行う。
|
||||
*
|
||||
* @param beforeCheckTimeSeconds 前回のイベントチェック時間[秒]
|
||||
* @param motionTimeSeconds 今回の再生時間[秒]
|
||||
*/
|
||||
public getFiredEvent(
|
||||
beforeCheckTimeSeconds: number,
|
||||
motionTimeSeconds: number
|
||||
): csmVector<csmString> {
|
||||
this._firedEventValues.updateSize(0);
|
||||
|
||||
// イベントの発火チェック
|
||||
for (let u = 0; u < this._motionData.eventCount; ++u) {
|
||||
if (
|
||||
this._motionData.events.at(u).fireTime > beforeCheckTimeSeconds &&
|
||||
this._motionData.events.at(u).fireTime <= motionTimeSeconds
|
||||
) {
|
||||
this._firedEventValues.pushBack(
|
||||
new csmString(this._motionData.events.at(u).value.s)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this._firedEventValues;
|
||||
}
|
||||
|
||||
public _sourceFrameRate: number; // ロードしたファイルのFPS。記述が無ければデフォルト値15fpsとなる
|
||||
public _loopDurationSeconds: number; // mtnファイルで定義される一連のモーションの長さ
|
||||
public _isLoop: boolean; // ループするか?
|
||||
public _isLoopFadeIn: boolean; // ループ時にフェードインが有効かどうかのフラグ。初期値では有効。
|
||||
public _lastWeight: number; // 最後に設定された重み
|
||||
|
||||
public _motionData: CubismMotionData; // 実際のモーションデータ本体
|
||||
|
||||
public _eyeBlinkParameterIds: csmVector<CubismIdHandle>; // 自動まばたきを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。
|
||||
public _lipSyncParameterIds: csmVector<CubismIdHandle>; // リップシンクを適用するパラメータIDハンドルのリスト。 モデル(モデルセッティング)とパラメータを対応付ける。
|
||||
|
||||
public _modelCurveIdEyeBlink: CubismIdHandle; // モデルが持つ自動まばたき用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||
public _modelCurveIdLipSync: CubismIdHandle; // モデルが持つリップシンク用パラメータIDのハンドル。 モデルとモーションを対応付ける。
|
||||
}
|
||||
}
|
140
src/motion/cubismmotioninternal.ts
Normal file
140
src/motion/cubismmotioninternal.ts
Normal file
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismid } from '../id/cubismid';
|
||||
import { Live2DCubismFramework as csmstring } from '../type/csmstring';
|
||||
import { Live2DCubismFramework as csmvector } from '../type/csmvector';
|
||||
import csmVector = csmvector.csmVector;
|
||||
import csmString = csmstring.csmString;
|
||||
import CubismIdHandle = cubismid.CubismIdHandle;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/**
|
||||
* @brief モーションカーブの種類
|
||||
*
|
||||
* モーションカーブの種類。
|
||||
*/
|
||||
export enum CubismMotionCurveTarget {
|
||||
CubismMotionCurveTarget_Model, // モデルに対して
|
||||
CubismMotionCurveTarget_Parameter, // パラメータに対して
|
||||
CubismMotionCurveTarget_PartOpacity // パーツの不透明度に対して
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief モーションカーブのセグメントの種類
|
||||
*
|
||||
* モーションカーブのセグメントの種類。
|
||||
*/
|
||||
export enum CubismMotionSegmentType {
|
||||
CubismMotionSegmentType_Linear = 0, // リニア
|
||||
CubismMotionSegmentType_Bezier = 1, // ベジェ曲線
|
||||
CubismMotionSegmentType_Stepped = 2, // ステップ
|
||||
CubismMotionSegmentType_InverseStepped = 3 // インバースステップ
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief モーションカーブの制御点
|
||||
*
|
||||
* モーションカーブの制御点。
|
||||
*/
|
||||
export class CubismMotionPoint {
|
||||
time = 0.0; // 時間[秒]
|
||||
value = 0.0; // 値
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションカーブのセグメントの評価関数
|
||||
*
|
||||
* @param points モーションカーブの制御点リスト
|
||||
* @param time 評価する時間[秒]
|
||||
*/
|
||||
export interface csmMotionSegmentEvaluationFunction {
|
||||
(points: CubismMotionPoint[], time: number): number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief モーションカーブのセグメント
|
||||
*
|
||||
* モーションカーブのセグメント。
|
||||
*/
|
||||
export class CubismMotionSegment {
|
||||
/**
|
||||
* @brief コンストラクタ
|
||||
*
|
||||
* コンストラクタ。
|
||||
*/
|
||||
public constructor() {
|
||||
this.evaluate = null;
|
||||
this.basePointIndex = 0;
|
||||
this.segmentType = 0;
|
||||
}
|
||||
|
||||
evaluate: csmMotionSegmentEvaluationFunction; // 使用する評価関数
|
||||
basePointIndex: number; // 最初のセグメントへのインデックス
|
||||
segmentType: number; // セグメントの種類
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief モーションカーブ
|
||||
*
|
||||
* モーションカーブ。
|
||||
*/
|
||||
export class CubismMotionCurve {
|
||||
public constructor() {
|
||||
this.type = CubismMotionCurveTarget.CubismMotionCurveTarget_Model;
|
||||
this.segmentCount = 0;
|
||||
this.baseSegmentIndex = 0;
|
||||
this.fadeInTime = 0.0;
|
||||
this.fadeOutTime = 0.0;
|
||||
}
|
||||
|
||||
type: CubismMotionCurveTarget; // カーブの種類
|
||||
id: CubismIdHandle; // カーブのID
|
||||
segmentCount: number; // セグメントの個数
|
||||
baseSegmentIndex: number; // 最初のセグメントのインデックス
|
||||
fadeInTime: number; // フェードインにかかる時間[秒]
|
||||
fadeOutTime: number; // フェードアウトにかかる時間[秒]
|
||||
}
|
||||
|
||||
/**
|
||||
* イベント。
|
||||
*/
|
||||
export class CubismMotionEvent {
|
||||
fireTime = 0.0;
|
||||
value: csmString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief モーションデータ
|
||||
*
|
||||
* モーションデータ。
|
||||
*/
|
||||
export class CubismMotionData {
|
||||
public constructor() {
|
||||
this.duration = 0.0;
|
||||
this.loop = false;
|
||||
this.curveCount = 0;
|
||||
this.eventCount = 0;
|
||||
this.fps = 0.0;
|
||||
|
||||
this.curves = new csmVector<CubismMotionCurve>();
|
||||
this.segments = new csmVector<CubismMotionSegment>();
|
||||
this.points = new csmVector<CubismMotionPoint>();
|
||||
this.events = new csmVector<CubismMotionEvent>();
|
||||
}
|
||||
|
||||
duration: number; // モーションの長さ[秒]
|
||||
loop: boolean; // ループするかどうか
|
||||
curveCount: number; // カーブの個数
|
||||
eventCount: number; // UserDataの個数
|
||||
fps: number; // フレームレート
|
||||
curves: csmVector<CubismMotionCurve>; // カーブのリスト
|
||||
segments: csmVector<CubismMotionSegment>; // セグメントのリスト
|
||||
points: csmVector<CubismMotionPoint>; // ポイントのリスト
|
||||
events: csmVector<CubismMotionEvent>; // イベントのリスト
|
||||
}
|
||||
}
|
359
src/motion/cubismmotionjson.ts
Normal file
359
src/motion/cubismmotionjson.ts
Normal file
@ -0,0 +1,359 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismjson } from '../utils/cubismjson';
|
||||
import { Live2DCubismFramework as cubismid } from '../id/cubismid';
|
||||
import { Live2DCubismFramework as cubismframework } from '../live2dcubismframework';
|
||||
import { Live2DCubismFramework as csmstring } from '../type/csmstring';
|
||||
import csmString = csmstring.csmString;
|
||||
import CubismFramework = cubismframework.CubismFramework;
|
||||
import CubismIdHandle = cubismid.CubismIdHandle;
|
||||
import CubismJson = cubismjson.CubismJson;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
// JSON keys
|
||||
const Meta = 'Meta';
|
||||
const Duration = 'Duration';
|
||||
const Loop = 'Loop';
|
||||
const CurveCount = 'CurveCount';
|
||||
const Fps = 'Fps';
|
||||
const TotalSegmentCount = 'TotalSegmentCount';
|
||||
const TotalPointCount = 'TotalPointCount';
|
||||
const Curves = 'Curves';
|
||||
const Target = 'Target';
|
||||
const Id = 'Id';
|
||||
const FadeInTime = 'FadeInTime';
|
||||
const FadeOutTime = 'FadeOutTime';
|
||||
const Segments = 'Segments';
|
||||
const UserData = 'UserData';
|
||||
const UserDataCount = 'UserDataCount';
|
||||
const TotalUserDataSize = 'TotalUserDataSize';
|
||||
const Time = 'Time';
|
||||
const Value = 'Value';
|
||||
|
||||
/**
|
||||
* motion3.jsonのコンテナ。
|
||||
*/
|
||||
export class CubismMotionJson {
|
||||
/**
|
||||
* コンストラクタ
|
||||
* @param buffer motion3.jsonが読み込まれているバッファ
|
||||
* @param size バッファのサイズ
|
||||
*/
|
||||
public constructor(buffer: ArrayBuffer, size: number) {
|
||||
this._json = CubismJson.create(buffer, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
CubismJson.delete(this._json);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの長さを取得する
|
||||
* @return モーションの長さ[秒]
|
||||
*/
|
||||
public getMotionDuration(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Duration)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのループ情報の取得
|
||||
* @return true ループする
|
||||
* @return false ループしない
|
||||
*/
|
||||
public isMotionLoop(): boolean {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Loop)
|
||||
.toBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションカーブの個数の取得
|
||||
* @return モーションカーブの個数
|
||||
*/
|
||||
public getMotionCurveCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(CurveCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフレームレートの取得
|
||||
* @return フレームレート[FPS]
|
||||
*/
|
||||
public getMotionFps(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(Fps)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのセグメントの総合計の取得
|
||||
* @return モーションのセグメントの取得
|
||||
*/
|
||||
public getMotionTotalSegmentCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalSegmentCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブの制御店の総合計の取得
|
||||
* @return モーションのカーブの制御点の総合計
|
||||
*/
|
||||
public getMotionTotalPointCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalPointCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードイン時間の存在
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionFadeInTime(): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeInTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードアウト時間の存在
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionFadeOutTime(): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeOutTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードイン時間の取得
|
||||
* @return フェードイン時間[秒]
|
||||
*/
|
||||
public getMotionFadeInTime(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeInTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのフェードアウト時間の取得
|
||||
* @return フェードアウト時間[秒]
|
||||
*/
|
||||
public getMotionFadeOutTime(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(FadeOutTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブの種類の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return カーブの種類
|
||||
*/
|
||||
public getMotionCurveTarget(curveIndex: number): string {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Target)
|
||||
.getRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのIDの取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return カーブのID
|
||||
*/
|
||||
public getMotionCurveId(curveIndex: number): CubismIdHandle {
|
||||
return CubismFramework.getIdManager().getId(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Id)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードイン時間の存在
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionCurveFadeInTime(curveIndex: number): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeInTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードアウト時間の存在
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return true 存在する
|
||||
* @return false 存在しない
|
||||
*/
|
||||
public isExistMotionCurveFadeOutTime(curveIndex: number): boolean {
|
||||
return !this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeOutTime)
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードイン時間の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return フェードイン時間[秒]
|
||||
*/
|
||||
public getMotionCurveFadeInTime(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeInTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのフェードアウト時間の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return フェードアウト時間[秒]
|
||||
*/
|
||||
public getMotionCurveFadeOutTime(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(FadeOutTime)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのセグメントの個数を取得する
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @return モーションのカーブのセグメントの個数
|
||||
*/
|
||||
public getMotionCurveSegmentCount(curveIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Segments)
|
||||
.getVector()
|
||||
.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションのカーブのセグメントの値の取得
|
||||
* @param curveIndex カーブのインデックス
|
||||
* @param segmentIndex セグメントのインデックス
|
||||
* @return セグメントの値
|
||||
*/
|
||||
public getMotionCurveSegment(
|
||||
curveIndex: number,
|
||||
segmentIndex: number
|
||||
): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Curves)
|
||||
.getValueByIndex(curveIndex)
|
||||
.getValueByString(Segments)
|
||||
.getValueByIndex(segmentIndex)
|
||||
.toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの個数の取得
|
||||
* @return イベントの個数
|
||||
*/
|
||||
public getEventCount(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(UserDataCount)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの総文字数の取得
|
||||
* @return イベントの総文字数
|
||||
*/
|
||||
public getTotalEventValueSize(): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(Meta)
|
||||
.getValueByString(TotalUserDataSize)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの時間の取得
|
||||
* @param userDataIndex イベントのインデックス
|
||||
* @return イベントの時間[秒]
|
||||
*/
|
||||
public getEventTime(userDataIndex: number): number {
|
||||
return this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(userDataIndex)
|
||||
.getValueByString(Time)
|
||||
.toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントの取得
|
||||
* @param userDataIndex イベントのインデックス
|
||||
* @return イベントの文字列
|
||||
*/
|
||||
public getEventValue(userDataIndex: number): csmString {
|
||||
return new csmString(
|
||||
this._json
|
||||
.getRoot()
|
||||
.getValueByString(UserData)
|
||||
.getValueByIndex(userDataIndex)
|
||||
.getValueByString(Value)
|
||||
.getRawString()
|
||||
);
|
||||
}
|
||||
|
||||
_json: CubismJson; // motion3.jsonのデータ
|
||||
}
|
||||
}
|
124
src/motion/cubismmotionmanager.ts
Normal file
124
src/motion/cubismmotionmanager.ts
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as cubismmotionqueuemanager } from './cubismmotionqueuemanager';
|
||||
import { Live2DCubismFramework as acubismmotion } from './acubismmotion';
|
||||
import { Live2DCubismFramework as cubismmodel } from '../model/cubismmodel';
|
||||
import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import ACubismMotion = acubismmotion.ACubismMotion;
|
||||
import CubismMotionQueueManager = cubismmotionqueuemanager.CubismMotionQueueManager;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/**
|
||||
* モーションの管理
|
||||
*
|
||||
* モーションの管理を行うクラス
|
||||
*/
|
||||
export class CubismMotionManager extends CubismMotionQueueManager {
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
super();
|
||||
this._currentPriority = 0;
|
||||
this._reservePriority = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 再生中のモーションの優先度の取得
|
||||
* @return モーションの優先度
|
||||
*/
|
||||
public getCurrentPriority(): number {
|
||||
return this._currentPriority;
|
||||
}
|
||||
|
||||
/**
|
||||
* 予約中のモーションの優先度を取得する。
|
||||
* @return モーションの優先度
|
||||
*/
|
||||
public getReservePriority(): number {
|
||||
return this._reservePriority;
|
||||
}
|
||||
|
||||
/**
|
||||
* 予約中のモーションの優先度を設定する。
|
||||
* @param val 優先度
|
||||
*/
|
||||
public setReservePriority(val: number): void {
|
||||
this._reservePriority = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* 優先度を設定してモーションを開始する。
|
||||
*
|
||||
* @param motion モーション
|
||||
* @param autoDelete 再生が狩猟したモーションのインスタンスを削除するならtrue
|
||||
* @param priority 優先度
|
||||
* @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
|
||||
*/
|
||||
public startMotionPriority(
|
||||
motion: ACubismMotion,
|
||||
autoDelete: boolean,
|
||||
priority: number
|
||||
): CubismMotionQueueEntryHandle {
|
||||
if (priority == this._reservePriority) {
|
||||
this._reservePriority = 0; // 予約を解除
|
||||
}
|
||||
|
||||
this._currentPriority = priority; // 再生中モーションの優先度を設定
|
||||
|
||||
return super.startMotion(motion, autoDelete, this._userTimeSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションを更新して、モデルにパラメータ値を反映する。
|
||||
*
|
||||
* @param model 対象のモデル
|
||||
* @param deltaTimeSeconds デルタ時間[秒]
|
||||
* @return true 更新されている
|
||||
* @return false 更新されていない
|
||||
*/
|
||||
public updateMotion(model: CubismModel, deltaTimeSeconds: number): boolean {
|
||||
this._userTimeSeconds += deltaTimeSeconds;
|
||||
|
||||
const updated: boolean = super.doUpdateMotion(
|
||||
model,
|
||||
this._userTimeSeconds
|
||||
);
|
||||
|
||||
if (this.isFinished()) {
|
||||
this._currentPriority = 0; // 再生中のモーションの優先度を解除
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションを予約する。
|
||||
*
|
||||
* @param priority 優先度
|
||||
* @return true 予約できた
|
||||
* @return false 予約できなかった
|
||||
*/
|
||||
public reserveMotion(priority: number): boolean {
|
||||
if (
|
||||
priority <= this._reservePriority ||
|
||||
priority <= this._currentPriority
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._reservePriority = priority;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_currentPriority: number; // 現在再生中のモーションの優先度
|
||||
_reservePriority: number; // 再生予定のモーションの優先度。再生中は0になる。モーションファイルを別スレッドで読み込むときの機能。
|
||||
}
|
||||
}
|
219
src/motion/cubismmotionqueueentry.ts
Normal file
219
src/motion/cubismmotionqueueentry.ts
Normal file
@ -0,0 +1,219 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as acubismmotion } from './acubismmotion';
|
||||
import { Live2DCubismFramework as cubismmotionqueuemanager } from './cubismmotionqueuemanager';
|
||||
import CubismMotionQueueEntryHandle = cubismmotionqueuemanager.CubismMotionQueueEntryHandle;
|
||||
import ACubismMotion = acubismmotion.ACubismMotion;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/**
|
||||
* CubismMotionQueueManagerで再生している各モーションの管理クラス。
|
||||
*/
|
||||
export class CubismMotionQueueEntry {
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
this._autoDelete = false;
|
||||
this._motion = null;
|
||||
this._available = true;
|
||||
this._finished = false;
|
||||
this._started = false;
|
||||
this._startTimeSeconds = -1.0;
|
||||
this._fadeInStartTimeSeconds = 0.0;
|
||||
this._endTimeSeconds = -1.0;
|
||||
this._stateTimeSeconds = 0.0;
|
||||
this._stateWeight = 0.0;
|
||||
this._lastEventCheckSeconds = 0.0;
|
||||
this._motionQueueEntryHandle = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ相当の処理
|
||||
*/
|
||||
public release(): void {
|
||||
if (this._autoDelete && this._motion) {
|
||||
ACubismMotion.delete(this._motion); //
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードアウトの開始
|
||||
* @param fadeOutSeconds フェードアウトにかかる時間[秒]
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
*/
|
||||
public startFadeout(fadeoutSeconds: number, userTimeSeconds: number): void {
|
||||
const newEndTimeSeconds: number = userTimeSeconds + fadeoutSeconds;
|
||||
|
||||
if (
|
||||
this._endTimeSeconds < 0.0 ||
|
||||
newEndTimeSeconds < this._endTimeSeconds
|
||||
) {
|
||||
this._endTimeSeconds = newEndTimeSeconds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの終了の確認
|
||||
*
|
||||
* @return true モーションが終了した
|
||||
* @return false 終了していない
|
||||
*/
|
||||
public isFinished(): boolean {
|
||||
return this._finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの開始の確認
|
||||
* @return true モーションが開始した
|
||||
* @return false 開始していない
|
||||
*/
|
||||
public isStarted(): boolean {
|
||||
return this._started;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの開始時刻の取得
|
||||
* @return モーションの開始時刻[秒]
|
||||
*/
|
||||
public getStartTime(): number {
|
||||
return this._startTimeSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインの開始時刻の取得
|
||||
* @return フェードインの開始時刻[秒]
|
||||
*/
|
||||
public getFadeInStartTime(): number {
|
||||
return this._fadeInStartTimeSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインの終了時刻の取得
|
||||
* @return フェードインの終了時刻の取得
|
||||
*/
|
||||
public getEndTime(): number {
|
||||
return this._endTimeSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの開始時刻の設定
|
||||
* @param startTime モーションの開始時刻
|
||||
*/
|
||||
public setStartTime(startTime: number): void {
|
||||
this._startTimeSeconds = startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインの開始時刻の設定
|
||||
* @param startTime フェードインの開始時刻[秒]
|
||||
*/
|
||||
public setFadeInStartTime(startTime: number): void {
|
||||
this._fadeInStartTimeSeconds = startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* フェードインの終了時刻の設定
|
||||
* @param endTime フェードインの終了時刻[秒]
|
||||
*/
|
||||
public setEndTime(endTime: number): void {
|
||||
this._endTimeSeconds = endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの終了の設定
|
||||
* @param f trueならモーションの終了
|
||||
*/
|
||||
public setIsFinished(f: boolean): void {
|
||||
this._finished = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーション開始の設定
|
||||
* @param f trueならモーションの開始
|
||||
*/
|
||||
public setIsStarted(f: boolean): void {
|
||||
this._started = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの有効性の確認
|
||||
* @return true モーションは有効
|
||||
* @return false モーションは無効
|
||||
*/
|
||||
public isAvailable(): boolean {
|
||||
return this._available;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの有効性の設定
|
||||
* @param v trueならモーションは有効
|
||||
*/
|
||||
public setIsAvailable(v: boolean): void {
|
||||
this._available = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの状態の設定
|
||||
* @param timeSeconds 現在時刻[秒]
|
||||
* @param weight モーション尾重み
|
||||
*/
|
||||
public setState(timeSeconds: number, weight: number): void {
|
||||
this._stateTimeSeconds = timeSeconds;
|
||||
this._stateWeight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの現在時刻の取得
|
||||
* @return モーションの現在時刻[秒]
|
||||
*/
|
||||
public getStateTime(): number {
|
||||
return this._stateTimeSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの重みの取得
|
||||
* @return モーションの重み
|
||||
*/
|
||||
public getStateWeight(): number {
|
||||
return this._stateWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最後にイベントの発火をチェックした時間を取得
|
||||
*
|
||||
* @return 最後にイベントの発火をチェックした時間[秒]
|
||||
*/
|
||||
public getLastCheckEventTime(): number {
|
||||
return this._lastEventCheckSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最後にイベントをチェックした時間を設定
|
||||
* @param checkTime 最後にイベントをチェックした時間[秒]
|
||||
*/
|
||||
public setLastCheckEventTime(checkTime: number): void {
|
||||
this._lastEventCheckSeconds = checkTime;
|
||||
}
|
||||
|
||||
_autoDelete: boolean; // 自動削除
|
||||
_motion: ACubismMotion; // モーション
|
||||
|
||||
_available: boolean; // 有効化フラグ
|
||||
_finished: boolean; // 終了フラグ
|
||||
_started: boolean; // 開始フラグ
|
||||
_startTimeSeconds: number; // モーション再生開始時刻[秒]
|
||||
_fadeInStartTimeSeconds: number; // フェードイン開始時刻(ループの時は初回のみ)[秒]
|
||||
_endTimeSeconds: number; // 終了予定時刻[秒]
|
||||
_stateTimeSeconds: number; // 時刻の状態[秒]
|
||||
_stateWeight: number; // 重みの状態
|
||||
_lastEventCheckSeconds: number; // 最終のMotion側のチェックした時間
|
||||
|
||||
_motionQueueEntryHandle: CubismMotionQueueEntryHandle; // インスタンスごとに一意の値を持つ識別番号
|
||||
}
|
||||
}
|
347
src/motion/cubismmotionqueuemanager.ts
Normal file
347
src/motion/cubismmotionqueuemanager.ts
Normal file
@ -0,0 +1,347 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { Live2DCubismFramework as acubismmotion } from './acubismmotion';
|
||||
import { Live2DCubismFramework as cubismmotionqueueentry } from './cubismmotionqueueentry';
|
||||
import { Live2DCubismFramework as csmvector } from '../type/csmvector';
|
||||
import { Live2DCubismFramework as cubismmodel } from '../model/cubismmodel';
|
||||
import { Live2DCubismFramework as csmstring } from '../type/csmstring';
|
||||
import csmString = csmstring.csmString;
|
||||
import CubismModel = cubismmodel.CubismModel;
|
||||
import csmVector = csmvector.csmVector;
|
||||
import iterator = csmvector.iterator;
|
||||
import CubismMotionQueueEntry = cubismmotionqueueentry.CubismMotionQueueEntry;
|
||||
import ACubismMotion = acubismmotion.ACubismMotion;
|
||||
|
||||
export namespace Live2DCubismFramework {
|
||||
/**
|
||||
* モーション再生の管理
|
||||
*
|
||||
* モーション再生の管理用クラス。CubismMotionモーションなどACubismMotionのサブクラスを再生するために使用する。
|
||||
*
|
||||
* @note 再生中に別のモーションが StartMotion()された場合は、新しいモーションに滑らかに変化し旧モーションは中断する。
|
||||
* 表情用モーション、体用モーションなどを分けてモーション化した場合など、
|
||||
* 複数のモーションを同時に再生させる場合は、複数のCubismMotionQueueManagerインスタンスを使用する。
|
||||
*/
|
||||
export class CubismMotionQueueManager {
|
||||
/**
|
||||
* コンストラクタ
|
||||
*/
|
||||
public constructor() {
|
||||
this._userTimeSeconds = 0.0;
|
||||
this._eventCallBack = null;
|
||||
this._eventCustomData = null;
|
||||
this._motions = new csmVector<CubismMotionQueueEntry>();
|
||||
}
|
||||
|
||||
/**
|
||||
* デストラクタ
|
||||
*/
|
||||
public release(): void {
|
||||
for (let i = 0; i < this._motions.getSize(); ++i) {
|
||||
if (this._motions.at(i)) {
|
||||
this._motions.at(i).release();
|
||||
this._motions.set(i, void 0);
|
||||
this._motions.set(i, null);
|
||||
}
|
||||
}
|
||||
|
||||
this._motions = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したモーションの開始
|
||||
*
|
||||
* 指定したモーションを開始する。同じタイプのモーションが既にある場合は、既存のモーションに終了フラグを立て、フェードアウトを開始させる。
|
||||
*
|
||||
* @param motion 開始するモーション
|
||||
* @param autoDelete 再生が終了したモーションのインスタンスを削除するなら true
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
* @return 開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
|
||||
*/
|
||||
public startMotion(
|
||||
motion: ACubismMotion,
|
||||
autoDelete: boolean,
|
||||
userTimeSeconds: number
|
||||
): CubismMotionQueueEntryHandle {
|
||||
if (motion == null) {
|
||||
return InvalidMotionQueueEntryHandleValue;
|
||||
}
|
||||
|
||||
let motionQueueEntry: CubismMotionQueueEntry = null;
|
||||
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
for (let i = 0; i < this._motions.getSize(); ++i) {
|
||||
motionQueueEntry = this._motions.at(i);
|
||||
if (motionQueueEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
motionQueueEntry.startFadeout(
|
||||
motionQueueEntry._motion.getFadeOutTime(),
|
||||
userTimeSeconds
|
||||
); // フェードアウトを開始し終了する
|
||||
}
|
||||
|
||||
motionQueueEntry = new CubismMotionQueueEntry(); // 終了時に破棄する
|
||||
motionQueueEntry._autoDelete = autoDelete;
|
||||
motionQueueEntry._motion = motion;
|
||||
|
||||
this._motions.pushBack(motionQueueEntry);
|
||||
|
||||
return motionQueueEntry._motionQueueEntryHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全てのモーションの終了の確認
|
||||
* @return true 全て終了している
|
||||
* @return false 終了していない
|
||||
*/
|
||||
public isFinished(): boolean {
|
||||
// ------- 処理を行う -------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
|
||||
) {
|
||||
let motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
continue;
|
||||
}
|
||||
|
||||
const motion: ACubismMotion = motionQueueEntry._motion;
|
||||
|
||||
if (motion == null) {
|
||||
motionQueueEntry.release();
|
||||
motionQueueEntry = void 0;
|
||||
motionQueueEntry = null;
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
continue;
|
||||
}
|
||||
|
||||
// ----- 終了済みの処理があれば削除する ------
|
||||
if (!motionQueueEntry.isFinished()) {
|
||||
return false;
|
||||
} else {
|
||||
ite.preIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したモーションの終了の確認
|
||||
* @param motionQueueEntryNumber モーションの識別番号
|
||||
* @return true 全て終了している
|
||||
* @return false 終了していない
|
||||
*/
|
||||
public isFinishedByHandle(
|
||||
motionQueueEntryNumber: CubismMotionQueueEntryHandle
|
||||
): boolean {
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
ite.increment()
|
||||
) {
|
||||
const motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber &&
|
||||
!motionQueueEntry.isFinished()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全てのモーションを停止する
|
||||
*/
|
||||
public stopAllMotions(): void {
|
||||
// ------- 処理を行う -------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
|
||||
) {
|
||||
let motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
ite = this._motions.erase(ite);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// ----- 終了済みの処理があれば削除する ------
|
||||
motionQueueEntry.release();
|
||||
motionQueueEntry = void 0;
|
||||
motionQueueEntry = null;
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定したCubismMotionQueueEntryの取得
|
||||
|
||||
* @param motionQueueEntryNumber モーションの識別番号
|
||||
* @return 指定したCubismMotionQueueEntry
|
||||
* @return null 見つからなかった
|
||||
*/
|
||||
public getCubismMotionQueueEntry(
|
||||
motionQueueEntryNumber: any
|
||||
): CubismMotionQueueEntry {
|
||||
//------- 処理を行う -------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
ite.preIncrement()
|
||||
) {
|
||||
const motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
motionQueueEntry._motionQueueEntryHandle == motionQueueEntryNumber
|
||||
) {
|
||||
return motionQueueEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントを受け取るCallbackの登録
|
||||
*
|
||||
* @param callback コールバック関数
|
||||
* @param customData コールバックに返されるデータ
|
||||
*/
|
||||
public setEventCallback(
|
||||
callback: CubismMotionEventFunction,
|
||||
customData: any = null
|
||||
): void {
|
||||
this._eventCallBack = callback;
|
||||
this._eventCustomData = customData;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションを更新して、モデルにパラメータ値を反映する。
|
||||
*
|
||||
* @param model 対象のモデル
|
||||
* @param userTimeSeconds デルタ時間の積算値[秒]
|
||||
* @return true モデルへパラメータ値の反映あり
|
||||
* @return false モデルへパラメータ値の反映なし(モーションの変化なし)
|
||||
*/
|
||||
public doUpdateMotion(
|
||||
model: CubismModel,
|
||||
userTimeSeconds: number
|
||||
): boolean {
|
||||
let updated = false;
|
||||
|
||||
// ------- 処理を行う --------
|
||||
// 既にモーションがあれば終了フラグを立てる
|
||||
|
||||
for (
|
||||
let ite: iterator<CubismMotionQueueEntry> = this._motions.begin();
|
||||
ite.notEqual(this._motions.end());
|
||||
|
||||
) {
|
||||
let motionQueueEntry: CubismMotionQueueEntry = ite.ptr();
|
||||
|
||||
if (motionQueueEntry == null) {
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
continue;
|
||||
}
|
||||
|
||||
const motion: ACubismMotion = motionQueueEntry._motion;
|
||||
|
||||
if (motion == null) {
|
||||
motionQueueEntry.release();
|
||||
motionQueueEntry = void 0;
|
||||
motionQueueEntry = null;
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// ------ 値を反映する ------
|
||||
motion.updateParameters(model, motionQueueEntry, userTimeSeconds);
|
||||
updated = true;
|
||||
|
||||
// ------ ユーザトリガーイベントを検査する ----
|
||||
const firedList: csmVector<csmString> = motion.getFiredEvent(
|
||||
motionQueueEntry.getLastCheckEventTime() -
|
||||
motionQueueEntry.getStartTime(),
|
||||
userTimeSeconds - motionQueueEntry.getStartTime()
|
||||
);
|
||||
|
||||
for (let i = 0; i < firedList.getSize(); ++i) {
|
||||
this._eventCallBack(this, firedList.at(i), this._eventCustomData);
|
||||
}
|
||||
|
||||
motionQueueEntry.setLastCheckEventTime(userTimeSeconds);
|
||||
|
||||
// ------ 終了済みの処理があれば削除する ------
|
||||
if (motionQueueEntry.isFinished()) {
|
||||
motionQueueEntry.release();
|
||||
motionQueueEntry = void 0;
|
||||
motionQueueEntry = null;
|
||||
ite = this._motions.erase(ite); // 削除
|
||||
} else {
|
||||
ite.preIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
_userTimeSeconds: number; // デルタ時間の積算値[秒]
|
||||
|
||||
_motions: csmVector<CubismMotionQueueEntry>; // モーション
|
||||
_eventCallBack: CubismMotionEventFunction; // コールバック関数
|
||||
_eventCustomData: any; // コールバックに戻されるデータ
|
||||
}
|
||||
|
||||
/**
|
||||
* イベントのコールバック関数を定義
|
||||
*
|
||||
* イベントのコールバックに登録できる関数の型情報
|
||||
* @param caller 発火したイベントを再生させたCubismMotionQueueManager
|
||||
* @param eventValue 発火したイベントの文字列データ
|
||||
* @param customData コールバックに返される登録時に指定されたデータ
|
||||
*/
|
||||
export interface CubismMotionEventFunction {
|
||||
(
|
||||
caller: CubismMotionQueueManager,
|
||||
eventValue: csmString,
|
||||
customData: any
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* モーションの識別番号
|
||||
*
|
||||
* モーションの識別番号の定義
|
||||
*/
|
||||
export declare type CubismMotionQueueEntryHandle = any;
|
||||
export const InvalidMotionQueueEntryHandleValue: CubismMotionQueueEntryHandle = -1;
|
||||
}
|
Reference in New Issue
Block a user