diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index aca2444..ce52e0c 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -18,9 +18,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
- ref: ${{github.ref_name}}
submodules: true
- fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
- uses: actions/setup-node@v3
with:
diff --git a/README.md b/README.md
index e179761..bec07b3 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Live2D models on a high level without the need to learn how the internal system
#### Requirements
-- PixiJS: 6.x
+- PixiJS: 7.x
- Cubism core: 2.1 or 4
- Browser: WebGL, ES6
@@ -108,7 +108,7 @@ import { Live2DModel } from 'pixi-live2d-display/cubism4';
-
+
@@ -172,7 +172,7 @@ window.PIXI = PIXI;
* Time to code
```js
var category_name = "Idle" // name of the morion category
-var animation_index = 0 // index of animation under that motion category
+var animation_index = 0 // index of animation under that motion category [null => random]
var priority_number = 3 // if you want to keep the current animation going or move to new animation by force [0: no priority, 1: idle, 2: normal, 3: forced]
var audio_link = "https://cdn.jsdelivr.net/gh/RaSan147/pixi-live2d-display@v1.0.3/playground/test.mp3" //[Optional arg, can be null or empty] [relative or full url path] [mp3 or wav file]
var volume = 1; //[Optional arg, can be null or empty] [0.0 - 1.0]
diff --git a/src/Live2DModel.ts b/src/Live2DModel.ts
index c2473cf..30bce1f 100644
--- a/src/Live2DModel.ts
+++ b/src/Live2DModel.ts
@@ -1,5 +1,4 @@
-import type { InternalModel, ModelSettings } from "@/cubism-common";
-import { MotionPriority } from "@/cubism-common";
+import type { InternalModel, ModelSettings, MotionPriority } from "@/cubism-common";
import type { MotionManagerOptions } from "@/cubism-common/MotionManager";
import { VOLUME } from "@/cubism-common/SoundManager";
import type { Live2DFactoryOptions } from "@/factory/Live2DFactory";
@@ -168,8 +167,8 @@ export class Live2DModel extends Conta
*/
motion(
group: string,
- index: number,
- priority: MotionPriority = MotionPriority.NORMAL,
+ index?: number,
+ priority?: MotionPriority,
{
sound = undefined,
volume = VOLUME,
diff --git a/src/cubism-common/MotionManager.ts b/src/cubism-common/MotionManager.ts
index a06ba04..825d784 100644
--- a/src/cubism-common/MotionManager.ts
+++ b/src/cubism-common/MotionManager.ts
@@ -302,7 +302,7 @@ export abstract class MotionManager extends util
}
if (audio) {
- let playSuccess = false;
+ let playSuccess = true;
const readyToPlay = SoundManager.play(audio).catch((e) => {
logger.warn(this.tag, "Failed to play audio", audio!.src, e);
playSuccess = false;
@@ -361,17 +361,16 @@ export abstract class MotionManager extends util
crossOrigin?: string;
} = {},
): Promise {
+ if (!this.state.reserve(group, index, priority)) {
+ return false;
+ }
// Does not start a new motion if audio is still playing
if (this.currentAudio) {
- if (!this.currentAudio.ended) {
+ if (!this.currentAudio.ended && priority != MotionPriority.FORCE) {
return false;
}
}
- if (!this.state.reserve(group, index, priority)) {
- return false;
- }
-
const definition = this.definitions[group]?.[index];
if (!definition) {
@@ -387,59 +386,58 @@ export abstract class MotionManager extends util
let analyzer: AnalyserNode | undefined;
let context: AudioContext | undefined;
- if (config.sound) {
- const isBase64Content = sound && sound.startsWith("data:audio/wav;base64");
- if (sound && !isBase64Content) {
- const A = document.createElement("a");
- A.href = sound;
- sound = A.href; // This should be the absolute url
- // since resolveURL is not working for some reason
- }
- const isUrlPath = sound && (sound.startsWith("http") || sound.startsWith("blob"));
- const soundURL = this.getSoundFile(definition);
- let file = soundURL;
+ let soundURL: string | undefined;
+ const isBase64Content = sound && sound.startsWith("data:");
+
+ if (sound && !isBase64Content) {
+ const A = document.createElement("a");
+ A.href = sound;
+ sound = A.href; // This should be the absolute url
+ // since resolveURL is not working for some reason
+ soundURL = sound;
+ } else {
+ soundURL = this.getSoundFile(definition);
if (soundURL) {
- file = this.settings.resolveURL(soundURL) + "?cache-buster=" + new Date().getTime();
+ soundURL = this.settings.resolveURL(soundURL);
}
- if (isUrlPath || isBase64Content) {
- file = sound;
- }
- if (file) {
- try {
- // start to load the audio
- audio = SoundManager.add(
- file,
- (that = this) => {
- resetExpression &&
- expression &&
- that.expressionManager &&
- that.expressionManager.resetExpression();
- that.currentAudio = undefined;
- }, // reset expression when audio is done
- (e, that = this) => {
- resetExpression &&
- expression &&
- that.expressionManager &&
- that.expressionManager.resetExpression();
- that.currentAudio = undefined;
- }, // on error
- crossOrigin,
- );
-
- this.currentAudio = audio!;
-
- SoundManager.volume = volume;
-
- // Add context
- context = SoundManager.addContext(this.currentAudio);
- this.currentContext = context;
-
- // Add analyzer
- analyzer = SoundManager.addAnalyzer(this.currentAudio, this.currentContext);
- this.currentAnalyzer = analyzer;
- } catch (e) {
- logger.warn(this.tag, "Failed to create audio", soundURL, e);
- }
+ }
+ const file: string | undefined = soundURL;
+
+ if (file) {
+ try {
+ // start to load the audio
+ audio = SoundManager.add(
+ file,
+ (that = this) => {
+ resetExpression &&
+ expression &&
+ that.expressionManager &&
+ that.expressionManager.resetExpression();
+ that.currentAudio = undefined;
+ }, // reset expression when audio is done
+ (e, that = this) => {
+ resetExpression &&
+ expression &&
+ that.expressionManager &&
+ that.expressionManager.resetExpression();
+ that.currentAudio = undefined;
+ }, // on error
+ crossOrigin,
+ );
+
+ this.currentAudio = audio!;
+
+ SoundManager.volume = volume;
+
+ // Add context
+ context = SoundManager.addContext(this.currentAudio);
+ this.currentContext = context;
+
+ // Add analyzer
+ analyzer = SoundManager.addAnalyzer(this.currentAudio, this.currentContext);
+ this.currentAnalyzer = analyzer;
+ } catch (e) {
+ logger.warn(this.tag, "Failed to create audio", soundURL, e);
}
}
diff --git a/src/cubism2/Cubism2InternalModel.ts b/src/cubism2/Cubism2InternalModel.ts
index 828fcb0..862d9af 100644
--- a/src/cubism2/Cubism2InternalModel.ts
+++ b/src/cubism2/Cubism2InternalModel.ts
@@ -36,7 +36,7 @@ export class Cubism2InternalModel extends InternalModel {
angleZParamIndex: number;
bodyAngleXParamIndex: number;
breathParamIndex: number;
- mouthFormIndex: number;
+ // mouthFormIndex: number;
textureFlipY = true;
@@ -74,7 +74,7 @@ export class Cubism2InternalModel extends InternalModel {
this.angleZParamIndex = coreModel.getParamIndex("PARAM_ANGLE_Z");
this.bodyAngleXParamIndex = coreModel.getParamIndex("PARAM_BODY_ANGLE_X");
this.breathParamIndex = coreModel.getParamIndex("PARAM_BREATH");
- this.mouthFormIndex = coreModel.getParamIndex("PARAM_MOUTH_FORM");
+ // this.mouthFormIndex = coreModel.getParamIndex("PARAM_MOUTH_FORM");
this.init();
}
@@ -250,11 +250,13 @@ export class Cubism2InternalModel extends InternalModel {
let value = this.motionManager.mouthSync();
let min_ = 0;
const max_ = 1;
- const weight = 1.2;
- if (value > 0) {
+ const bias_weight = 1.2;
+ const bias_power = 0.7;
+ if (value > 0.0) {
min_ = 0.4;
}
- value = clamp(value * weight, min_, max_);
+ value = Math.pow(value, bias_power);
+ value = clamp(value * bias_weight, min_, max_);
for (let i = 0; i < this.motionManager.lipSyncIds.length; ++i) {
this.coreModel.setParamFloat(
diff --git a/src/cubism4/Cubism4MotionManager.ts b/src/cubism4/Cubism4MotionManager.ts
index 20192ba..8a8b66a 100644
--- a/src/cubism4/Cubism4MotionManager.ts
+++ b/src/cubism4/Cubism4MotionManager.ts
@@ -25,15 +25,19 @@ export class Cubism4MotionManager extends MotionManager