@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
102 lines (77 loc) • 2.84 kB
JavaScript
import { assert } from "../../../../../core/assert.js";
import { string_compute_common_prefix } from "../../../../../core/primitives/strings/string_compute_common_prefix.js";
import { string_compute_similarity } from "../../../../../core/primitives/strings/string_compute_similarity.js";
import { HumanoidBoneType } from "./HumanoidBoneType.js";
/**
*
* @param {{distance:number}} a
* @param {{distance:number}} b
* @returns {number}
*/
function byDistance(a, b) {
return b.distance - a.distance;
}
export class BoneMapping {
constructor() {
this.mapping = [];
}
/**
*
* @param {string[]} names
*/
build(names) {
//strip common prefix
const commonPrefix = string_compute_common_prefix(names);
const commonPrefixLength = commonPrefix.length;
const conditionedNames = names.map(function (name) {
return name.substring(commonPrefixLength);
});
const boneValues = Object.values(HumanoidBoneType);
//compute probability distribution for each name to a known bone
const matches = [];
boneValues.forEach(function (boneName, boneIndex) {
conditionedNames.forEach(function (name, inputIndex) {
const distance = string_compute_similarity(name, boneName);
const match = {
boneIndex,
inputIndex,
distance
};
matches.push(match);
});
});
//sort distribution according to distance
matches.sort(byDistance);
//assign mapping
let numMatches = matches.length;
while (numMatches > 0) {
const match = matches.pop();
numMatches--;
const boneIndex = match.boneIndex;
const inputIndex = match.inputIndex;
const boneValue = boneValues[boneIndex];
this.mapping[inputIndex] = boneValue;
//remove all references to this bone index and input
for (let i = 0; i < numMatches; i++) {
const match = matches[i];
if (match.boneIndex === boneIndex || match.inputIndex === inputIndex) {
matches.splice(i, 1);
numMatches--;
i--;
}
}
}
}
/**
* @param {Bone[]} bones
*/
apply(bones) {
assert.ok(Array.isArray(bones), 'bones argument must be an array');
const numBones = bones.length;
for (let i = 0; i < numBones; i++) {
const bone = bones[i];
const boneType = this.mapping[i];
bone.boneType = boneType;
}
}
}