diff --git a/examples/animation-controls/animation-controls.js b/examples/animation-controls/animation-controls.js index 692ab7c1..0c9400f3 100644 --- a/examples/animation-controls/animation-controls.js +++ b/examples/animation-controls/animation-controls.js @@ -10,14 +10,18 @@ const animationNames = { updateAnimationMixer = () => { - const data = {} + const data = {useRegExp: true} data.clip = 'none' Object.entries(animationNames).forEach((name) => { - const el = document.getElementById(name[0]) - + const regExpEscape = (s) => { + return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); + } + + el = document.getElementById(name[0]) if (el.checked) { - data.clip = name[1] + if (data.clip) data.clip += "|" + data.clip += regExpEscape(name[1]) } }) diff --git a/examples/animation-controls/index.html b/examples/animation-controls/index.html index 1f2f452a..cc6563ea 100644 --- a/examples/animation-controls/index.html +++ b/examples/animation-controls/index.html @@ -14,20 +14,18 @@
Controls
- - - + - + - + - + - + - + diff --git a/examples/bundle.js b/examples/bundle.js index bcb458ed..aa116bb7 100644 --- a/examples/bundle.js +++ b/examples/bundle.js @@ -45064,6 +45064,7 @@ var LoopMode = { module.exports = AFRAME.registerComponent('animation-mixer', { schema: { clip: { default: '*' }, + useRegExp: { default: false }, duration: { default: 0 }, clampWhenFinished: { default: false, type: 'boolean' }, crossFadeDuration: { default: 0 }, @@ -45158,7 +45159,7 @@ module.exports = AFRAME.registerComponent('animation-mixer', { if (!clips.length) return; - var re = wildcardToRegExp(data.clip); + var re = data.useRegExp ? data.clip : wildcardToRegExp(data.clip); for (var clip, i = 0; clip = clips[i]; i++) { if (clip.name.match(re)) { diff --git a/src/loaders/README.md b/src/loaders/README.md index 6b850e73..a9c90fed 100644 --- a/src/loaders/README.md +++ b/src/loaders/README.md @@ -33,6 +33,8 @@ an animation and its duration: | Property | Default | Description | |-------------------|----------|-----------------------------------------------------------| | clip | * | Name of the animation clip(s) to play. Accepts wildcards. | +| useRegExp | false | If true, interpret the `clip` string as a regular expression. If false, it is treated as a literal string, except for the * character, which is treated as a variable-length wildcard. | + | duration | 0 | Duration of one cycle of the animation clip, in seconds. This provides the same functionality as timeScale (apart from pausing), with duration = clipLength/timeScale. This property only has an effect if timeScale is set to 1, otherwise the value of timeScale is used to determine animation playback speed. | | crossFadeDuration | 0 | Duration of cross-fades between clips, in seconds. | | loop | repeat | `once`, `repeat`, or `pingpong`. In `repeat` and `pingpong` modes, the clip plays once plus the specified number of repetitions. For `pingpong`, every second clip plays in reverse. | @@ -41,9 +43,7 @@ an animation and its duration: | clampWhenFinished | false | If true, halts the animation at the last frame. | | startAt | 0 | Configures the animation clip to begin at a specific start time (in milliseconds). This is useful when you need to jump to an exact time in an animation. The input parameter will be scaled by the mixer's timeScale. Negative values will result in a pause before the animation begins. | -A list of available animations can usually be found by inspecting the model file or its documentation. All animations will play by default. To play only a specific set of animations, use wildcards: `animation-mixer="clip: run_*"`. - -There is no provided syntax to specify multiple animations, except via the * wildcard. For example: `animation-mixer="clip: run,walk"` will match neither `run` nor `walk`, and would only match a clip named `run,walk`. +A list of available animations can usually be found by inspecting the model file or its documentation. All animations will play by default. To play only a specific set of animations, use wildcards: `animation-mixer="clip: run_*"`, or use the useRegExp flag to enable full regular expression matching, e.g. `animation-mixer="useRegExp: true; clip: run|walk"`. ### Animation Events diff --git a/src/loaders/animation-mixer.js b/src/loaders/animation-mixer.js index d9a2211c..b04e0bdf 100644 --- a/src/loaders/animation-mixer.js +++ b/src/loaders/animation-mixer.js @@ -14,6 +14,7 @@ const LoopMode = { module.exports = AFRAME.registerComponent('animation-mixer', { schema: { clip: { default: '*' }, + useRegExp: {default: false}, duration: { default: 0 }, clampWhenFinished: { default: false, type: 'boolean' }, crossFadeDuration: { default: 0 }, @@ -108,7 +109,7 @@ module.exports = AFRAME.registerComponent('animation-mixer', { if (!clips.length) return; - const re = wildcardToRegExp(data.clip); + const re = data.useRegExp ? data.clip : wildcardToRegExp(data.clip); for (let clip, i = 0; (clip = clips[i]); i++) { if (clip.name.match(re)) {