phaser4-rex-plugins
Version:
344 lines (291 loc) • 11.3 kB
text/typescript
/**
* 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 { ACubismMotion } from './acubismmotion';
import { CubismMotionQueueEntry } from './cubismmotionqueueentry';
import { csmVector, iterator } from '../type/csmvector';
import { CubismModel } from '../model/cubismmodel';
import { csmString } from '../type/csmstring';
/**
* モーション再生の管理
*
* モーション再生の管理用クラス。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, 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.setFadeOut(motionQueueEntry._motion.getFadeOutTime()); // フェードアウト設定
}
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 = 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 = 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 = null;
ite = this._motions.erase(ite); // 削除
continue;
}
// ------ 値を反映する ------
motion.updateParameters(model, motionQueueEntry, userTimeSeconds);
updated = true;
// ------ ユーザトリガーイベントを検査する ----
const firedList: csmVector<csmString> = motion.getFiredEvent(
motionQueueEntry.getLastCheckEventSeconds() -
motionQueueEntry.getStartTime(),
userTimeSeconds - motionQueueEntry.getStartTime()
);
for (let i = 0; i < firedList.getSize(); ++i) {
this._eventCallBack(this, firedList.at(i), this._eventCustomData);
}
motionQueueEntry.setLastCheckEventSeconds(userTimeSeconds);
// ------ 終了済みの処理があれば削除する ------
if (motionQueueEntry.isFinished()) {
motionQueueEntry.release();
motionQueueEntry = null;
ite = this._motions.erase(ite); // 削除
} else {
if (motionQueueEntry.isTriggeredFadeOut()) {
motionQueueEntry.startFadeOut(
motionQueueEntry.getFadeOutSeconds(),
userTimeSeconds
);
}
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;
// Namespace definition for compatibility.
import * as $ from './cubismmotionqueuemanager';
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace Live2DCubismFramework {
export const CubismMotionQueueManager = $.CubismMotionQueueManager;
export type CubismMotionQueueManager = $.CubismMotionQueueManager;
export const InvalidMotionQueueEntryHandleValue =
$.InvalidMotionQueueEntryHandleValue;
export type CubismMotionQueueEntryHandle = $.CubismMotionQueueEntryHandle;
export type CubismMotionEventFunction = $.CubismMotionEventFunction;
}