roavatar-renderer 1.2.14 → 1.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -9
- package/dist/index.d.ts +24 -4
- package/dist/index.js +133 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
# Renderer for RoAvatar
|
|
2
|
-
|
|
2
|
+
The Roblox Avatar renderer used by https://github.com/steinann/RoAvatar
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Links: [npm](https://www.npmjs.com/package/roavatar-renderer) | [GitHub](https://github.com/steinann/RoAvatar-Renderer)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
> **IMPORTANT** <br>
|
|
7
|
+
> Assets are *NOT* included in the npm module or this repository, you have to get them from the main RoAvatar repository OR set
|
|
8
|
+
> ```FLAGS.ONLINE_ASSETS = true```
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Basic example on how to load an avatar using OutfitRenderer (to make it simpler):
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
**HTML:**
|
|
11
13
|
```html
|
|
12
|
-
<!--
|
|
14
|
+
<!--This script has to be loaded in before loading any meshes-->
|
|
13
15
|
<script src="/draco_decoder.js"></script>
|
|
14
16
|
```
|
|
17
|
+
**TYPESCRIPT:**
|
|
15
18
|
```ts
|
|
16
19
|
//setup flags that are compatible with you environment
|
|
17
|
-
FLAGS.ONLINE_ASSETS =
|
|
20
|
+
FLAGS.ONLINE_ASSETS = true //set false to true if you want assets to be loaded locally
|
|
18
21
|
|
|
22
|
+
//if we arent using online assets we have to provide the renderer with the paths
|
|
19
23
|
if (!FLAGS.ONLINE_ASSETS) {
|
|
20
24
|
//path to asset files from RoAvatar
|
|
21
25
|
FLAGS.ASSETS_PATH = chrome.runtime.getURL("assets/rbxasset/")
|
|
@@ -47,9 +51,11 @@ if (!(outfit instanceof Outfit)) throw new Error("Failed to get outfit")
|
|
|
47
51
|
//used by api
|
|
48
52
|
const auth = new Authentication()
|
|
49
53
|
//manages outfit rendering for you
|
|
50
|
-
const outfitRenderer = new OutfitRenderer(auth, outfit
|
|
54
|
+
const outfitRenderer = new OutfitRenderer(auth, outfit)
|
|
51
55
|
outfitRenderer.startAnimating()
|
|
52
56
|
outfitRenderer.setMainAnimation("idle")
|
|
53
57
|
```
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
More info available in ```/docs```
|
|
60
|
+
|
|
61
|
+
Also the OutfitRenderer code or RoAvatar source code is useful, especially ```avatarPreview.ts```
|
package/dist/index.d.ts
CHANGED
|
@@ -295,6 +295,10 @@ export declare const API: {
|
|
|
295
295
|
PremiumFeatures: {
|
|
296
296
|
GetSubscription: (userId: number) => Promise<Response | GetSubscription_Result>;
|
|
297
297
|
};
|
|
298
|
+
RBLXGet: typeof RBLXGet;
|
|
299
|
+
RBLXPost: typeof RBLXPost;
|
|
300
|
+
RBLXDelete: typeof RBLXDelete;
|
|
301
|
+
RBLXPatch: typeof RBLXPatch;
|
|
298
302
|
};
|
|
299
303
|
|
|
300
304
|
export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
@@ -880,6 +884,10 @@ declare class Event_2 {
|
|
|
880
884
|
}
|
|
881
885
|
export { Event_2 as Event }
|
|
882
886
|
|
|
887
|
+
export declare function exposeAPI(): void;
|
|
888
|
+
|
|
889
|
+
export declare function exposeMesh(): void;
|
|
890
|
+
|
|
883
891
|
export declare const FaceControlNames: string[];
|
|
884
892
|
|
|
885
893
|
export declare class FaceControlsWrapper extends InstanceWrapper {
|
|
@@ -1279,7 +1287,7 @@ export declare class Instance {
|
|
|
1279
1287
|
PropOrDefault(name: string, def: unknown): unknown;
|
|
1280
1288
|
PropertyType(name: string): number | undefined;
|
|
1281
1289
|
getPropertyNames(): string[];
|
|
1282
|
-
setParent(instance: Instance | undefined | null): void;
|
|
1290
|
+
setParent(instance: Instance | undefined | null, fireEvents?: boolean): void;
|
|
1283
1291
|
Destroy(): void;
|
|
1284
1292
|
GetFullName(): string;
|
|
1285
1293
|
GetChildren(): Instance[];
|
|
@@ -1541,6 +1549,8 @@ export declare const magic = "<roblox!";
|
|
|
1541
1549
|
|
|
1542
1550
|
export declare function magnitude(v: Vec3): number;
|
|
1543
1551
|
|
|
1552
|
+
export declare const MakeupAssetTypes: string[];
|
|
1553
|
+
|
|
1544
1554
|
export declare class MakeupDescriptionWrapper extends InstanceWrapper {
|
|
1545
1555
|
static className: string;
|
|
1546
1556
|
static requiredProperties: string[];
|
|
@@ -1882,13 +1892,15 @@ export declare class OutfitRenderer {
|
|
|
1882
1892
|
hasNewUpdate: boolean;
|
|
1883
1893
|
lastFrameTime: number;
|
|
1884
1894
|
animationInterval?: NodeJS.Timeout;
|
|
1895
|
+
animationFPS: number;
|
|
1896
|
+
deltaTimeMultiplier: number;
|
|
1885
1897
|
/**
|
|
1886
1898
|
* Creates a new OutfitRenderer which makes it easy to render outfits
|
|
1887
1899
|
* @param auth The authentication object, you should have one you use for everything
|
|
1888
1900
|
* @param outfit The outfit you want to render, it can be updated later by calling setOutfit()
|
|
1889
|
-
* @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm,
|
|
1901
|
+
* @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm, should always be "roavatar://" as rig path is now controlled by FLAGS
|
|
1890
1902
|
*/
|
|
1891
|
-
constructor(auth: Authentication, outfit: Outfit, rigPath
|
|
1903
|
+
constructor(auth: Authentication, outfit: Outfit, rigPath?: string);
|
|
1892
1904
|
/**
|
|
1893
1905
|
* Updates the current rig, called internally by _updateOutfit()
|
|
1894
1906
|
*/
|
|
@@ -2054,6 +2066,14 @@ export declare class RBFDeformerPatch {
|
|
|
2054
2066
|
deformMesh(): void;
|
|
2055
2067
|
}
|
|
2056
2068
|
|
|
2069
|
+
declare function RBLXDelete(url: string, auth: Authentication, body: any, attempt?: number): Promise<Response>;
|
|
2070
|
+
|
|
2071
|
+
declare function RBLXGet(url: string, headers?: any, includeCredentials?: boolean): Promise<Response>;
|
|
2072
|
+
|
|
2073
|
+
declare function RBLXPatch(url: string, auth: Authentication, body: any, attempt?: number): Promise<Response>;
|
|
2074
|
+
|
|
2075
|
+
declare function RBLXPost(url: string, auth: Authentication | undefined, body: any, attempt?: number, method?: string): Promise<Response>;
|
|
2076
|
+
|
|
2057
2077
|
export declare class RBX {
|
|
2058
2078
|
classCount: number;
|
|
2059
2079
|
instanceCount: number;
|
|
@@ -2604,7 +2624,7 @@ declare type ValidationIssue = {
|
|
|
2604
2624
|
assetIndex?: number;
|
|
2605
2625
|
};
|
|
2606
2626
|
|
|
2607
|
-
declare type ValidationIssueType = "AccessoryLimit" | "LayeredLimit" | "OneOfTypeLimit" | "DuplicateId" | "NotWearable" | "MissingLayeredMeta" | "InvalidAsset";
|
|
2627
|
+
declare type ValidationIssueType = "AccessoryLimit" | "LayeredLimit" | "OneOfTypeLimit" | "DuplicateId" | "NotWearable" | "MissingLayeredMeta" | "InvalidAsset" | "MakeupLimit";
|
|
2608
2628
|
|
|
2609
2629
|
export declare type Vec2 = [number, number];
|
|
2610
2630
|
|
package/dist/index.js
CHANGED
|
@@ -287,6 +287,11 @@ const LayeredClothingAssetOrder = {
|
|
|
287
287
|
90: 16
|
|
288
288
|
// EyeMakeup
|
|
289
289
|
};
|
|
290
|
+
const MakeupAssetTypes = [
|
|
291
|
+
"FaceMakeup",
|
|
292
|
+
"LipMakeup",
|
|
293
|
+
"EyeMakeup"
|
|
294
|
+
];
|
|
290
295
|
const MaxPerAsset = {
|
|
291
296
|
"Head": 1,
|
|
292
297
|
"TShirt": 1,
|
|
@@ -26700,6 +26705,7 @@ class WebGLRenderer {
|
|
|
26700
26705
|
gl.unpackColorSpace = ColorManagement._getUnpackColorSpace();
|
|
26701
26706
|
}
|
|
26702
26707
|
}
|
|
26708
|
+
const textDecoder$1 = new TextDecoder();
|
|
26703
26709
|
class SimpleView {
|
|
26704
26710
|
view;
|
|
26705
26711
|
viewOffset;
|
|
@@ -26757,7 +26763,7 @@ class SimpleView {
|
|
|
26757
26763
|
if (!stringLength) {
|
|
26758
26764
|
stringLength = this.readUint32();
|
|
26759
26765
|
}
|
|
26760
|
-
const string =
|
|
26766
|
+
const string = textDecoder$1.decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
|
|
26761
26767
|
this.viewOffset += stringLength;
|
|
26762
26768
|
return string;
|
|
26763
26769
|
}
|
|
@@ -26889,6 +26895,7 @@ function intToRgb(colorInt) {
|
|
|
26889
26895
|
const B = colorInt & 255;
|
|
26890
26896
|
return { R, G, B };
|
|
26891
26897
|
}
|
|
26898
|
+
const textDecoder = new TextDecoder();
|
|
26892
26899
|
class RBXSimpleView {
|
|
26893
26900
|
view;
|
|
26894
26901
|
viewOffset;
|
|
@@ -26926,7 +26933,7 @@ class RBXSimpleView {
|
|
|
26926
26933
|
if (!stringLength) {
|
|
26927
26934
|
stringLength = this.readUint32();
|
|
26928
26935
|
}
|
|
26929
|
-
const string =
|
|
26936
|
+
const string = textDecoder.decode(new Uint8Array(this.view.buffer).subarray(this.viewOffset, this.viewOffset + stringLength));
|
|
26930
26937
|
this.viewOffset += stringLength;
|
|
26931
26938
|
return string;
|
|
26932
26939
|
}
|
|
@@ -29238,7 +29245,7 @@ function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {
|
|
|
29238
29245
|
}
|
|
29239
29246
|
return best;
|
|
29240
29247
|
}
|
|
29241
|
-
const jsContent = '(function() {\n "use strict";\n const FullBodyColorPalette = [\n {\n "brickColorId": 361,\n "hexColor": "#564236",\n "name": "Dirt brown"\n },\n {\n "brickColorId": 192,\n "hexColor": "#694028",\n "name": "Reddish brown"\n },\n {\n "brickColorId": 217,\n "hexColor": "#7C5C46",\n "name": "Brown"\n },\n {\n "brickColorId": 153,\n "hexColor": "#957977",\n "name": "Sand red"\n },\n {\n "brickColorId": 359,\n "hexColor": "#AF9483",\n "name": "Linen"\n },\n {\n "brickColorId": 352,\n "hexColor": "#C7AC78",\n "name": "Burlap"\n },\n {\n "brickColorId": 5,\n "hexColor": "#D7C59A",\n "name": "Brick yellow"\n },\n {\n "brickColorId": 101,\n "hexColor": "#DA867A",\n "name": "Medium red"\n },\n {\n "brickColorId": 1007,\n "hexColor": "#A34B4B",\n "name": "Dusty Rose"\n },\n {\n "brickColorId": 1014,\n "hexColor": "#AA5500",\n "name": "CGA brown"\n },\n {\n "brickColorId": 38,\n "hexColor": "#A05F35",\n "name": "Dark orange"\n },\n {\n "brickColorId": 18,\n "hexColor": "#CC8E69",\n "name": "Nougat"\n },\n {\n "brickColorId": 125,\n "hexColor": "#EAB892",\n "name": "Light orange"\n },\n {\n "brickColorId": 1030,\n "hexColor": "#FFCC99",\n "name": "Pastel brown"\n },\n {\n "brickColorId": 133,\n "hexColor": "#D5733D",\n "name": "Neon orange"\n },\n {\n "brickColorId": 106,\n "hexColor": "#DA8541",\n "name": "Bright orange"\n },\n {\n "brickColorId": 105,\n "hexColor": "#E29B40",\n "name": "Br. yellowish orange"\n },\n {\n "brickColorId": 1017,\n "hexColor": "#FFAF00",\n "name": "Deep orange"\n },\n {\n "brickColorId": 24,\n "hexColor": "#F5CD30",\n "name": "Bright yellow"\n },\n {\n "brickColorId": 334,\n "hexColor": "#F8D96D",\n "name": "Daisy orange"\n },\n {\n "brickColorId": 226,\n "hexColor": "#FDEA8D",\n "name": "Cool yellow"\n },\n {\n "brickColorId": 141,\n "hexColor": "#27462D",\n "name": "Earth green"\n },\n {\n "brickColorId": 1021,\n "hexColor": "#3A7D15",\n "name": "Camo"\n },\n {\n "brickColorId": 28,\n "hexColor": "#287F47",\n "name": "Dark green"\n },\n {\n "brickColorId": 37,\n "hexColor": "#4B974B",\n "name": "Bright green"\n },\n {\n "brickColorId": 310,\n "hexColor": "#5B9A4C",\n "name": "Shamrock"\n },\n {\n "brickColorId": 317,\n "hexColor": "#7C9C6B",\n "name": "Moss"\n },\n {\n "brickColorId": 119,\n "hexColor": "#A4BD47",\n "name": "Br. yellowish green"\n },\n {\n "brickColorId": 1011,\n "hexColor": "#002060",\n "name": "Navy blue"\n },\n {\n "brickColorId": 1012,\n "hexColor": "#2154B9",\n "name": "Deep blue"\n },\n {\n "brickColorId": 1010,\n "hexColor": "#0000FF",\n "name": "Really blue"\n },\n {\n "brickColorId": 23,\n "hexColor": "#0D69AC",\n "name": "Bright blue"\n },\n {\n "brickColorId": 305,\n "hexColor": "#527CAE",\n "name": "Steel blue"\n },\n {\n "brickColorId": 102,\n "hexColor": "#6E99CA",\n "name": "Medium blue"\n },\n {\n "brickColorId": 45,\n "hexColor": "#B4D2E4",\n "name": "Light blue"\n },\n {\n "brickColorId": 107,\n "hexColor": "#008F9C",\n "name": "Bright bluish green"\n },\n {\n "brickColorId": 1018,\n "hexColor": "#12EED4",\n "name": "Teal"\n },\n {\n "brickColorId": 1027,\n "hexColor": "#9FF3E9",\n "name": "Pastel blue-green"\n },\n {\n "brickColorId": 1019,\n "hexColor": "#00FFFF",\n "name": "Toothpaste"\n },\n {\n "brickColorId": 1013,\n "hexColor": "#04AFEC",\n "name": "Cyan"\n },\n {\n "brickColorId": 11,\n "hexColor": "#80BBDC",\n "name": "Pastel Blue"\n },\n {\n "brickColorId": 1024,\n "hexColor": "#AFDDFF",\n "name": "Pastel light blue"\n },\n {\n "brickColorId": 104,\n "hexColor": "#6B327C",\n "name": "Bright violet"\n },\n {\n "brickColorId": 1023,\n "hexColor": "#8C5B9F",\n "name": "Lavender"\n },\n {\n "brickColorId": 321,\n "hexColor": "#A75E9B",\n "name": "Lilac"\n },\n {\n "brickColorId": 1015,\n "hexColor": "#AA00AA",\n "name": "Magenta"\n },\n {\n "brickColorId": 1031,\n "hexColor": "#6225D1",\n "name": "Royal purple"\n },\n {\n "brickColorId": 1006,\n "hexColor": "#B480FF",\n "name": "Alder"\n },\n {\n "brickColorId": 1026,\n "hexColor": "#B1A7FF",\n "name": "Pastel violet"\n },\n {\n "brickColorId": 21,\n "hexColor": "#C4281C",\n "name": "Bright red"\n },\n {\n "brickColorId": 1004,\n "hexColor": "#FF0000",\n "name": "Really red"\n },\n {\n "brickColorId": 1032,\n "hexColor": "#FF00BF",\n "name": "Hot pink"\n },\n {\n "brickColorId": 1016,\n "hexColor": "#FF66CC",\n "name": "Pink"\n },\n {\n "brickColorId": 330,\n "hexColor": "#FF98DC",\n "name": "Carnation pink"\n },\n {\n "brickColorId": 9,\n "hexColor": "#E8BAC8",\n "name": "Light reddish violet"\n },\n {\n "brickColorId": 1025,\n "hexColor": "#FFC9C9",\n "name": "Pastel orange"\n },\n {\n "brickColorId": 364,\n "hexColor": "#5A4C42",\n "name": "Dark taupe"\n },\n {\n "brickColorId": 351,\n "hexColor": "#BC9B5D",\n "name": "Cork"\n },\n {\n "brickColorId": 1008,\n "hexColor": "#C1BE42",\n "name": "Olive"\n },\n {\n "brickColorId": 29,\n "hexColor": "#A1C48C",\n "name": "Medium green"\n },\n {\n "brickColorId": 1022,\n "hexColor": "#7F8E64",\n "name": "Grime"\n },\n {\n "brickColorId": 151,\n "hexColor": "#789082",\n "name": "Sand green"\n },\n {\n "brickColorId": 135,\n "hexColor": "#74869D",\n "name": "Sand blue"\n },\n {\n "brickColorId": 1020,\n "hexColor": "#00FF00",\n "name": "Lime green"\n },\n {\n "brickColorId": 1028,\n "hexColor": "#CCFFCC",\n "name": "Pastel green"\n },\n {\n "brickColorId": 1009,\n "hexColor": "#FFFF00",\n "name": "New Yeller"\n },\n {\n "brickColorId": 1029,\n "hexColor": "#FFFFCC",\n "name": "Pastel yellow"\n },\n {\n "brickColorId": 1003,\n "hexColor": "#111111",\n "name": "Really black"\n },\n {\n "brickColorId": 26,\n "hexColor": "#1B2A35",\n "name": "Black"\n },\n {\n "brickColorId": 199,\n "hexColor": "#635F62",\n "name": "Dark stone grey"\n },\n {\n "brickColorId": 194,\n "hexColor": "#A3A2A5",\n "name": "Medium stone grey"\n },\n {\n "brickColorId": 1002,\n "hexColor": "#CDCDCD",\n "name": "Mid gray"\n },\n {\n "brickColorId": 208,\n "hexColor": "#E5E4DF",\n "name": "Light stone grey"\n },\n {\n "brickColorId": 1,\n "hexColor": "#F2F3F3",\n "name": "White"\n },\n {\n "brickColorId": 1001,\n "hexColor": "#F8F8F8",\n "name": "Institutional white"\n }\n ];\n const RegularBodyColors = [\n "5A4C42",\n "7C5C46",\n "AF9483",\n "CC8E69",\n "EAB892",\n "564236",\n "694028",\n "BC9B5D",\n "c7ac78",\n "d7c59a",\n "957977",\n "a34b4b",\n "da867a",\n "ffc9c9",\n "ff98dc",\n "74869d",\n "527cae",\n "80bbdc",\n "b1a7ff",\n "a75e9b",\n "008f9c",\n "5b9a4c",\n "7c9c6b",\n "a1c48c",\n "e29b40",\n "f5cd30",\n "f8d96d",\n "635f62",\n "cdcdcd",\n "f8f8f8"\n ];\n for (let i = 0; i < RegularBodyColors.length; i++) {\n const color = RegularBodyColors[i];\n RegularBodyColors[i] = color.toUpperCase();\n }\n const FullBodyColors = [];\n for (const colorDetails of FullBodyColorPalette) {\n FullBodyColors.push(colorDetails.hexColor.substring(1));\n }\n function calculateMagnitude3D(x, y, z) {\n return Math.sqrt(x * x + y * y + z * z);\n }\n function magnitude(v) {\n return calculateMagnitude3D(v[0], v[1], v[2]);\n }\n function minus(v0, v1) {\n return [v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]];\n }\n function distance(v0, v1) {\n return magnitude(minus(v1, v0));\n }\n class KDNode {\n point;\n index;\n axis;\n left = null;\n right = null;\n constructor(point, index, axis) {\n this.point = point;\n this.index = index;\n this.axis = axis;\n }\n }\n function buildKDTree(points, indices, depth = 0) {\n if (points.length === 0) return null;\n const axis = depth % 3;\n const sorted = points.map((p, i) => ({ p, index: indices[i] })).sort((a, b) => a.p[axis] - b.p[axis]);\n const mid = Math.floor(sorted.length / 2);\n const node = new KDNode(sorted[mid].p, sorted[mid].index, axis);\n const leftPoints = sorted.slice(0, mid).map((x) => x.p);\n const leftIndices = sorted.slice(0, mid).map((x) => x.index);\n const rightPoints = sorted.slice(mid + 1).map((x) => x.p);\n const rightIndices = sorted.slice(mid + 1).map((x) => x.index);\n node.left = buildKDTree(leftPoints, leftIndices, depth + 1);\n node.right = buildKDTree(rightPoints, rightIndices, depth + 1);\n return node;\n }\n function siftUp(heap, i) {\n while (i > 0) {\n const p = i - 1 >> 1;\n if (heap[p].dist >= heap[i].dist) break;\n const tmp = heap[p];\n heap[p] = heap[i];\n heap[i] = tmp;\n i = p;\n }\n }\n function siftDown(heap, i) {\n const n = heap.length;\n while (true) {\n let largest = i;\n const l = (i << 1) + 1;\n const r = l + 1;\n if (l < n && heap[l].dist > heap[largest].dist) largest = l;\n if (r < n && heap[r].dist > heap[largest].dist) largest = r;\n if (largest === i) break;\n const tmp = heap[i];\n heap[i] = heap[largest];\n heap[largest] = tmp;\n i = largest;\n }\n }\n function heapPushMax(heap, item, k) {\n if (heap.length < k) {\n heap.push(item);\n siftUp(heap, heap.length - 1);\n return;\n }\n if (item.dist >= heap[0].dist) return;\n heap[0] = item;\n siftDown(heap, 0);\n }\n function distSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n }\n function knnSearch(node, target, k, heap = []) {\n if (!node) return heap;\n const axis = node.axis;\n const dist = distSq(target, node.point);\n heapPushMax(heap, { dist, index: node.index }, k);\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n knnSearch(primary, target, k, heap);\n const worstDist = heap.length < k ? Infinity : heap[0].dist;\n if (diff * diff < worstDist) {\n knnSearch(secondary, target, k, heap);\n }\n if (node === null) {\n heap.sort((a, b) => a.dist - b.dist);\n }\n return heap;\n }\n function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {\n if (!node) return best;\n const dist = distance(target, node.point);\n if (dist < best.dist) {\n best = { dist, index: node.index };\n }\n const axis = node.axis;\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n best = nearestSearch(primary, target, best);\n if (Math.abs(diff) < best.dist) {\n best = nearestSearch(secondary, target, best);\n }\n return best;\n }\n function luDecompose(A) {\n const n = A.length;\n const LU = A;\n const P = new Int32Array(n);\n for (let i = 0; i < n; i++) P[i] = i;\n for (let k = 0; k < n; k++) {\n let pivot = k;\n for (let i = k + 1; i < n; i++) {\n if (Math.abs(LU[i][k]) > Math.abs(LU[pivot][k])) {\n pivot = i;\n }\n }\n if (pivot !== k) {\n const tmpRow = LU[k];\n LU[k] = LU[pivot];\n LU[pivot] = tmpRow;\n const tmpP = P[k];\n P[k] = P[pivot];\n P[pivot] = tmpP;\n }\n const pivotVal = LU[k][k];\n for (let i = k + 1; i < n; i++) {\n LU[i][k] /= pivotVal;\n const mult = LU[i][k];\n const rowI = LU[i];\n const rowK = LU[k];\n for (let j = k + 1; j < n; j++) {\n rowI[j] -= mult * rowK[j];\n }\n }\n }\n return { LU, P };\n }\n function luSolve({ LU, P }, b) {\n const n = LU.length;\n const x = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = b[P[i]];\n }\n for (let i = 0; i < n; i++) {\n const row = LU[i];\n let sum = x[i];\n for (let j = 0; j < i; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum;\n }\n for (let i = n - 1; i >= 0; i--) {\n const row = LU[i];\n let sum = x[i];\n for (let j = i + 1; j < n; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum / row[i];\n }\n return x;\n }\n function patchRBFWorkerFunc([_A, _bx, _by, _bz]) {\n const A = _A.map((r) => new Float32Array(r));\n const bx = new Float32Array(_bx);\n const by = new Float32Array(_by);\n const bz = new Float32Array(_bz);\n const LU = luDecompose(A);\n const wx = luSolve(LU, bx);\n const wy = luSolve(LU, by);\n const wz = luSolve(LU, bz);\n const n = wx.length;\n const result = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n result[i * 3 + 0] = wx[i];\n result[i * 3 + 1] = wy[i];\n result[i * 3 + 2] = wz[i];\n }\n return result.buffer;\n }\n function RBFDeformerSolveAsync([patchCount, detailsCount, epsilon, importantIndicesBuf, refVertsBuf, distVertsBuf, meshVertsBuf, meshBonesBuf]) {\n const importantIndices = new Uint16Array(importantIndicesBuf);\n const refVerts = new Float32Array(refVertsBuf);\n const distVerts = new Float32Array(distVertsBuf);\n const meshVerts = new Float32Array(meshVertsBuf);\n const meshBones = new Float32Array(meshBonesBuf);\n const refCount = refVerts.length / 3;\n const meshVertCount = meshVerts.length / 3;\n const meshBoneCount = meshBones.length / 3;\n const points = new Array(refCount);\n const indices = new Array(refCount);\n for (let i = 0; i < refCount; i++) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n points[i] = refPos;\n indices[i] = i;\n }\n const controlKD = buildKDTree(points, indices);\n const step = Math.max(1, Math.floor(refCount / patchCount));\n const patchCenters = [];\n for (let i = 0; i < refCount; i += step) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n patchCenters.push(refPos);\n if (patchCenters.length >= patchCount) break;\n }\n const neighborIndices = new Array(patchCenters.length);\n const weights = new Array(patchCenters.length);\n const patchIndices = patchCenters.map((_, i) => i);\n const patchKD = buildKDTree(patchCenters, patchIndices);\n const isUsedArr = new Array(patchCenters.length).fill(false);\n const nearestPatch = new Uint16Array(meshVertCount + meshBoneCount);\n for (let i = 0; i < meshVertCount; i++) {\n const vec = [meshVerts[i * 3 + 0], meshVerts[i * 3 + 1], meshVerts[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i] = nearestPatchNode.index;\n }\n for (let i = 0; i < meshBoneCount; i++) {\n const vec = [meshBones[i * 3 + 0], meshBones[i * 3 + 1], meshBones[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i + meshVertCount] = nearestPatchNode.index;\n }\n for (let i = 0; i < patchCenters.length; i++) {\n if (!isUsedArr[i]) {\n continue;\n }\n const centerPos = patchCenters[i];\n const neighbors = knnSearch(controlKD, centerPos, detailsCount);\n const foundNeighborIndices = neighbors.map((n) => n.index);\n for (const important of importantIndices) {\n if (!foundNeighborIndices.includes(important)) {\n foundNeighborIndices.push(important);\n }\n }\n neighborIndices[i] = new Uint16Array(foundNeighborIndices);\n }\n const A_array = new Array(patchCenters.length);\n for (let p = 0; p < patchCenters.length; p++) {\n const patchNeighborIndices = neighborIndices[p];\n if (!patchNeighborIndices) continue;\n const K = patchNeighborIndices.length;\n const positions = new Array(patchNeighborIndices.length);\n for (let i = 0; i < patchNeighborIndices.length; i++) {\n const j = patchNeighborIndices[i];\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n positions[i] = refPos;\n }\n const A = new Array(K);\n for (let i = 0; i < K; i++) {\n A[i] = new Float32Array(K);\n }\n for (let i = 0; i < K; i++) {\n const [pix, piy, piz] = positions[i];\n for (let j = i + 1; j < K; j++) {\n const [pjx, pjy, pjz] = positions[j];\n const dist = Math.sqrt((pix - pjx) * (pix - pjx) + (piy - pjy) * (piy - pjy) + (piz - pjz) * (piz - pjz));\n A[i][j] = dist;\n A[j][i] = dist;\n }\n A[i][i] = epsilon;\n }\n A_array[p] = A;\n }\n for (let p = 0; p < patchCenters.length; p++) {\n if (!isUsedArr[p]) {\n continue;\n }\n const patchNeighborIndices = neighborIndices[p];\n const K = patchNeighborIndices.length;\n const usedRef = new Array(K);\n const usedDist = new Array(K);\n for (let i = 0; i < K; i++) {\n const idx = patchNeighborIndices[i];\n const j = idx;\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n const distPos = [distVerts[j * 3 + 0], distVerts[j * 3 + 1], distVerts[j * 3 + 2]];\n usedRef[i] = refPos;\n usedDist[i] = distPos;\n }\n const A = A_array[p];\n const bx = new Float32Array(K);\n const by = new Float32Array(K);\n const bz = new Float32Array(K);\n for (let i = 0; i < K; i++) {\n const dr = usedDist[i];\n const rr = usedRef[i];\n bx[i] = dr[0] - rr[0];\n by[i] = dr[1] - rr[1];\n bz[i] = dr[2] - rr[2];\n }\n const Abuffers = A.map((r) => r.buffer);\n weights[p] = new Float32Array(patchRBFWorkerFunc([Abuffers, bx.buffer, by.buffer, bz.buffer]));\n }\n const neighborIndicesBuf = neighborIndices.map((a) => {\n return a.buffer;\n });\n const weightsBuf = weights.map((a) => {\n return a.buffer;\n });\n return [neighborIndicesBuf, weightsBuf, nearestPatch.buffer];\n }\n const WorkerTypeToFunction = {\n "patchRBF": patchRBFWorkerFunc,\n "RBFDeformerSolveAsync": RBFDeformerSolveAsync\n };\n function getWorkerOnMessage() {\n return function(event) {\n const [id, type, data] = event.data;\n const func = WorkerTypeToFunction[type];\n self.postMessage([id, func(data)]);\n };\n }\n onmessage = getWorkerOnMessage();\n})();\n';
|
|
29248
|
+
const jsContent = '(function() {\n "use strict";\n new TextDecoder();\n new TextDecoder();\n const FullBodyColorPalette = [\n {\n "brickColorId": 361,\n "hexColor": "#564236",\n "name": "Dirt brown"\n },\n {\n "brickColorId": 192,\n "hexColor": "#694028",\n "name": "Reddish brown"\n },\n {\n "brickColorId": 217,\n "hexColor": "#7C5C46",\n "name": "Brown"\n },\n {\n "brickColorId": 153,\n "hexColor": "#957977",\n "name": "Sand red"\n },\n {\n "brickColorId": 359,\n "hexColor": "#AF9483",\n "name": "Linen"\n },\n {\n "brickColorId": 352,\n "hexColor": "#C7AC78",\n "name": "Burlap"\n },\n {\n "brickColorId": 5,\n "hexColor": "#D7C59A",\n "name": "Brick yellow"\n },\n {\n "brickColorId": 101,\n "hexColor": "#DA867A",\n "name": "Medium red"\n },\n {\n "brickColorId": 1007,\n "hexColor": "#A34B4B",\n "name": "Dusty Rose"\n },\n {\n "brickColorId": 1014,\n "hexColor": "#AA5500",\n "name": "CGA brown"\n },\n {\n "brickColorId": 38,\n "hexColor": "#A05F35",\n "name": "Dark orange"\n },\n {\n "brickColorId": 18,\n "hexColor": "#CC8E69",\n "name": "Nougat"\n },\n {\n "brickColorId": 125,\n "hexColor": "#EAB892",\n "name": "Light orange"\n },\n {\n "brickColorId": 1030,\n "hexColor": "#FFCC99",\n "name": "Pastel brown"\n },\n {\n "brickColorId": 133,\n "hexColor": "#D5733D",\n "name": "Neon orange"\n },\n {\n "brickColorId": 106,\n "hexColor": "#DA8541",\n "name": "Bright orange"\n },\n {\n "brickColorId": 105,\n "hexColor": "#E29B40",\n "name": "Br. yellowish orange"\n },\n {\n "brickColorId": 1017,\n "hexColor": "#FFAF00",\n "name": "Deep orange"\n },\n {\n "brickColorId": 24,\n "hexColor": "#F5CD30",\n "name": "Bright yellow"\n },\n {\n "brickColorId": 334,\n "hexColor": "#F8D96D",\n "name": "Daisy orange"\n },\n {\n "brickColorId": 226,\n "hexColor": "#FDEA8D",\n "name": "Cool yellow"\n },\n {\n "brickColorId": 141,\n "hexColor": "#27462D",\n "name": "Earth green"\n },\n {\n "brickColorId": 1021,\n "hexColor": "#3A7D15",\n "name": "Camo"\n },\n {\n "brickColorId": 28,\n "hexColor": "#287F47",\n "name": "Dark green"\n },\n {\n "brickColorId": 37,\n "hexColor": "#4B974B",\n "name": "Bright green"\n },\n {\n "brickColorId": 310,\n "hexColor": "#5B9A4C",\n "name": "Shamrock"\n },\n {\n "brickColorId": 317,\n "hexColor": "#7C9C6B",\n "name": "Moss"\n },\n {\n "brickColorId": 119,\n "hexColor": "#A4BD47",\n "name": "Br. yellowish green"\n },\n {\n "brickColorId": 1011,\n "hexColor": "#002060",\n "name": "Navy blue"\n },\n {\n "brickColorId": 1012,\n "hexColor": "#2154B9",\n "name": "Deep blue"\n },\n {\n "brickColorId": 1010,\n "hexColor": "#0000FF",\n "name": "Really blue"\n },\n {\n "brickColorId": 23,\n "hexColor": "#0D69AC",\n "name": "Bright blue"\n },\n {\n "brickColorId": 305,\n "hexColor": "#527CAE",\n "name": "Steel blue"\n },\n {\n "brickColorId": 102,\n "hexColor": "#6E99CA",\n "name": "Medium blue"\n },\n {\n "brickColorId": 45,\n "hexColor": "#B4D2E4",\n "name": "Light blue"\n },\n {\n "brickColorId": 107,\n "hexColor": "#008F9C",\n "name": "Bright bluish green"\n },\n {\n "brickColorId": 1018,\n "hexColor": "#12EED4",\n "name": "Teal"\n },\n {\n "brickColorId": 1027,\n "hexColor": "#9FF3E9",\n "name": "Pastel blue-green"\n },\n {\n "brickColorId": 1019,\n "hexColor": "#00FFFF",\n "name": "Toothpaste"\n },\n {\n "brickColorId": 1013,\n "hexColor": "#04AFEC",\n "name": "Cyan"\n },\n {\n "brickColorId": 11,\n "hexColor": "#80BBDC",\n "name": "Pastel Blue"\n },\n {\n "brickColorId": 1024,\n "hexColor": "#AFDDFF",\n "name": "Pastel light blue"\n },\n {\n "brickColorId": 104,\n "hexColor": "#6B327C",\n "name": "Bright violet"\n },\n {\n "brickColorId": 1023,\n "hexColor": "#8C5B9F",\n "name": "Lavender"\n },\n {\n "brickColorId": 321,\n "hexColor": "#A75E9B",\n "name": "Lilac"\n },\n {\n "brickColorId": 1015,\n "hexColor": "#AA00AA",\n "name": "Magenta"\n },\n {\n "brickColorId": 1031,\n "hexColor": "#6225D1",\n "name": "Royal purple"\n },\n {\n "brickColorId": 1006,\n "hexColor": "#B480FF",\n "name": "Alder"\n },\n {\n "brickColorId": 1026,\n "hexColor": "#B1A7FF",\n "name": "Pastel violet"\n },\n {\n "brickColorId": 21,\n "hexColor": "#C4281C",\n "name": "Bright red"\n },\n {\n "brickColorId": 1004,\n "hexColor": "#FF0000",\n "name": "Really red"\n },\n {\n "brickColorId": 1032,\n "hexColor": "#FF00BF",\n "name": "Hot pink"\n },\n {\n "brickColorId": 1016,\n "hexColor": "#FF66CC",\n "name": "Pink"\n },\n {\n "brickColorId": 330,\n "hexColor": "#FF98DC",\n "name": "Carnation pink"\n },\n {\n "brickColorId": 9,\n "hexColor": "#E8BAC8",\n "name": "Light reddish violet"\n },\n {\n "brickColorId": 1025,\n "hexColor": "#FFC9C9",\n "name": "Pastel orange"\n },\n {\n "brickColorId": 364,\n "hexColor": "#5A4C42",\n "name": "Dark taupe"\n },\n {\n "brickColorId": 351,\n "hexColor": "#BC9B5D",\n "name": "Cork"\n },\n {\n "brickColorId": 1008,\n "hexColor": "#C1BE42",\n "name": "Olive"\n },\n {\n "brickColorId": 29,\n "hexColor": "#A1C48C",\n "name": "Medium green"\n },\n {\n "brickColorId": 1022,\n "hexColor": "#7F8E64",\n "name": "Grime"\n },\n {\n "brickColorId": 151,\n "hexColor": "#789082",\n "name": "Sand green"\n },\n {\n "brickColorId": 135,\n "hexColor": "#74869D",\n "name": "Sand blue"\n },\n {\n "brickColorId": 1020,\n "hexColor": "#00FF00",\n "name": "Lime green"\n },\n {\n "brickColorId": 1028,\n "hexColor": "#CCFFCC",\n "name": "Pastel green"\n },\n {\n "brickColorId": 1009,\n "hexColor": "#FFFF00",\n "name": "New Yeller"\n },\n {\n "brickColorId": 1029,\n "hexColor": "#FFFFCC",\n "name": "Pastel yellow"\n },\n {\n "brickColorId": 1003,\n "hexColor": "#111111",\n "name": "Really black"\n },\n {\n "brickColorId": 26,\n "hexColor": "#1B2A35",\n "name": "Black"\n },\n {\n "brickColorId": 199,\n "hexColor": "#635F62",\n "name": "Dark stone grey"\n },\n {\n "brickColorId": 194,\n "hexColor": "#A3A2A5",\n "name": "Medium stone grey"\n },\n {\n "brickColorId": 1002,\n "hexColor": "#CDCDCD",\n "name": "Mid gray"\n },\n {\n "brickColorId": 208,\n "hexColor": "#E5E4DF",\n "name": "Light stone grey"\n },\n {\n "brickColorId": 1,\n "hexColor": "#F2F3F3",\n "name": "White"\n },\n {\n "brickColorId": 1001,\n "hexColor": "#F8F8F8",\n "name": "Institutional white"\n }\n ];\n const RegularBodyColors = [\n "5A4C42",\n "7C5C46",\n "AF9483",\n "CC8E69",\n "EAB892",\n "564236",\n "694028",\n "BC9B5D",\n "c7ac78",\n "d7c59a",\n "957977",\n "a34b4b",\n "da867a",\n "ffc9c9",\n "ff98dc",\n "74869d",\n "527cae",\n "80bbdc",\n "b1a7ff",\n "a75e9b",\n "008f9c",\n "5b9a4c",\n "7c9c6b",\n "a1c48c",\n "e29b40",\n "f5cd30",\n "f8d96d",\n "635f62",\n "cdcdcd",\n "f8f8f8"\n ];\n for (let i = 0; i < RegularBodyColors.length; i++) {\n const color = RegularBodyColors[i];\n RegularBodyColors[i] = color.toUpperCase();\n }\n const FullBodyColors = [];\n for (const colorDetails of FullBodyColorPalette) {\n FullBodyColors.push(colorDetails.hexColor.substring(1));\n }\n function calculateMagnitude3D(x, y, z) {\n return Math.sqrt(x * x + y * y + z * z);\n }\n function magnitude(v) {\n return calculateMagnitude3D(v[0], v[1], v[2]);\n }\n function minus(v0, v1) {\n return [v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]];\n }\n function distance(v0, v1) {\n return magnitude(minus(v1, v0));\n }\n class KDNode {\n point;\n index;\n axis;\n left = null;\n right = null;\n constructor(point, index, axis) {\n this.point = point;\n this.index = index;\n this.axis = axis;\n }\n }\n function buildKDTree(points, indices, depth = 0) {\n if (points.length === 0) return null;\n const axis = depth % 3;\n const sorted = points.map((p, i) => ({ p, index: indices[i] })).sort((a, b) => a.p[axis] - b.p[axis]);\n const mid = Math.floor(sorted.length / 2);\n const node = new KDNode(sorted[mid].p, sorted[mid].index, axis);\n const leftPoints = sorted.slice(0, mid).map((x) => x.p);\n const leftIndices = sorted.slice(0, mid).map((x) => x.index);\n const rightPoints = sorted.slice(mid + 1).map((x) => x.p);\n const rightIndices = sorted.slice(mid + 1).map((x) => x.index);\n node.left = buildKDTree(leftPoints, leftIndices, depth + 1);\n node.right = buildKDTree(rightPoints, rightIndices, depth + 1);\n return node;\n }\n function siftUp(heap, i) {\n while (i > 0) {\n const p = i - 1 >> 1;\n if (heap[p].dist >= heap[i].dist) break;\n const tmp = heap[p];\n heap[p] = heap[i];\n heap[i] = tmp;\n i = p;\n }\n }\n function siftDown(heap, i) {\n const n = heap.length;\n while (true) {\n let largest = i;\n const l = (i << 1) + 1;\n const r = l + 1;\n if (l < n && heap[l].dist > heap[largest].dist) largest = l;\n if (r < n && heap[r].dist > heap[largest].dist) largest = r;\n if (largest === i) break;\n const tmp = heap[i];\n heap[i] = heap[largest];\n heap[largest] = tmp;\n i = largest;\n }\n }\n function heapPushMax(heap, item, k) {\n if (heap.length < k) {\n heap.push(item);\n siftUp(heap, heap.length - 1);\n return;\n }\n if (item.dist >= heap[0].dist) return;\n heap[0] = item;\n siftDown(heap, 0);\n }\n function distSq(a, b) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n }\n function knnSearch(node, target, k, heap = []) {\n if (!node) return heap;\n const axis = node.axis;\n const dist = distSq(target, node.point);\n heapPushMax(heap, { dist, index: node.index }, k);\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n knnSearch(primary, target, k, heap);\n const worstDist = heap.length < k ? Infinity : heap[0].dist;\n if (diff * diff < worstDist) {\n knnSearch(secondary, target, k, heap);\n }\n if (node === null) {\n heap.sort((a, b) => a.dist - b.dist);\n }\n return heap;\n }\n function nearestSearch(node, target, best = { dist: Infinity, index: -1 }) {\n if (!node) return best;\n const dist = distance(target, node.point);\n if (dist < best.dist) {\n best = { dist, index: node.index };\n }\n const axis = node.axis;\n const diff = target[axis] - node.point[axis];\n const primary = diff < 0 ? node.left : node.right;\n const secondary = diff < 0 ? node.right : node.left;\n best = nearestSearch(primary, target, best);\n if (Math.abs(diff) < best.dist) {\n best = nearestSearch(secondary, target, best);\n }\n return best;\n }\n function luDecompose(A) {\n const n = A.length;\n const LU = A;\n const P = new Int32Array(n);\n for (let i = 0; i < n; i++) P[i] = i;\n for (let k = 0; k < n; k++) {\n let pivot = k;\n for (let i = k + 1; i < n; i++) {\n if (Math.abs(LU[i][k]) > Math.abs(LU[pivot][k])) {\n pivot = i;\n }\n }\n if (pivot !== k) {\n const tmpRow = LU[k];\n LU[k] = LU[pivot];\n LU[pivot] = tmpRow;\n const tmpP = P[k];\n P[k] = P[pivot];\n P[pivot] = tmpP;\n }\n const pivotVal = LU[k][k];\n for (let i = k + 1; i < n; i++) {\n LU[i][k] /= pivotVal;\n const mult = LU[i][k];\n const rowI = LU[i];\n const rowK = LU[k];\n for (let j = k + 1; j < n; j++) {\n rowI[j] -= mult * rowK[j];\n }\n }\n }\n return { LU, P };\n }\n function luSolve({ LU, P }, b) {\n const n = LU.length;\n const x = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n x[i] = b[P[i]];\n }\n for (let i = 0; i < n; i++) {\n const row = LU[i];\n let sum = x[i];\n for (let j = 0; j < i; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum;\n }\n for (let i = n - 1; i >= 0; i--) {\n const row = LU[i];\n let sum = x[i];\n for (let j = i + 1; j < n; j++) {\n sum -= row[j] * x[j];\n }\n x[i] = sum / row[i];\n }\n return x;\n }\n function patchRBFWorkerFunc([_A, _bx, _by, _bz]) {\n const A = _A.map((r) => new Float32Array(r));\n const bx = new Float32Array(_bx);\n const by = new Float32Array(_by);\n const bz = new Float32Array(_bz);\n const LU = luDecompose(A);\n const wx = luSolve(LU, bx);\n const wy = luSolve(LU, by);\n const wz = luSolve(LU, bz);\n const n = wx.length;\n const result = new Float32Array(n * 3);\n for (let i = 0; i < n; i++) {\n result[i * 3 + 0] = wx[i];\n result[i * 3 + 1] = wy[i];\n result[i * 3 + 2] = wz[i];\n }\n return result.buffer;\n }\n function RBFDeformerSolveAsync([patchCount, detailsCount, epsilon, importantIndicesBuf, refVertsBuf, distVertsBuf, meshVertsBuf, meshBonesBuf]) {\n const importantIndices = new Uint16Array(importantIndicesBuf);\n const refVerts = new Float32Array(refVertsBuf);\n const distVerts = new Float32Array(distVertsBuf);\n const meshVerts = new Float32Array(meshVertsBuf);\n const meshBones = new Float32Array(meshBonesBuf);\n const refCount = refVerts.length / 3;\n const meshVertCount = meshVerts.length / 3;\n const meshBoneCount = meshBones.length / 3;\n const points = new Array(refCount);\n const indices = new Array(refCount);\n for (let i = 0; i < refCount; i++) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n points[i] = refPos;\n indices[i] = i;\n }\n const controlKD = buildKDTree(points, indices);\n const step = Math.max(1, Math.floor(refCount / patchCount));\n const patchCenters = [];\n for (let i = 0; i < refCount; i += step) {\n const refPos = [refVerts[i * 3 + 0], refVerts[i * 3 + 1], refVerts[i * 3 + 2]];\n patchCenters.push(refPos);\n if (patchCenters.length >= patchCount) break;\n }\n const neighborIndices = new Array(patchCenters.length);\n const weights = new Array(patchCenters.length);\n const patchIndices = patchCenters.map((_, i) => i);\n const patchKD = buildKDTree(patchCenters, patchIndices);\n const isUsedArr = new Array(patchCenters.length).fill(false);\n const nearestPatch = new Uint16Array(meshVertCount + meshBoneCount);\n for (let i = 0; i < meshVertCount; i++) {\n const vec = [meshVerts[i * 3 + 0], meshVerts[i * 3 + 1], meshVerts[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i] = nearestPatchNode.index;\n }\n for (let i = 0; i < meshBoneCount; i++) {\n const vec = [meshBones[i * 3 + 0], meshBones[i * 3 + 1], meshBones[i * 3 + 2]];\n const nearestPatchNode = nearestSearch(patchKD, vec);\n isUsedArr[nearestPatchNode.index] = true;\n nearestPatch[i + meshVertCount] = nearestPatchNode.index;\n }\n for (let i = 0; i < patchCenters.length; i++) {\n if (!isUsedArr[i]) {\n continue;\n }\n const centerPos = patchCenters[i];\n const neighbors = knnSearch(controlKD, centerPos, detailsCount);\n const foundNeighborIndices = neighbors.map((n) => n.index);\n for (const important of importantIndices) {\n if (!foundNeighborIndices.includes(important)) {\n foundNeighborIndices.push(important);\n }\n }\n neighborIndices[i] = new Uint16Array(foundNeighborIndices);\n }\n const A_array = new Array(patchCenters.length);\n for (let p = 0; p < patchCenters.length; p++) {\n const patchNeighborIndices = neighborIndices[p];\n if (!patchNeighborIndices) continue;\n const K = patchNeighborIndices.length;\n const positions = new Array(patchNeighborIndices.length);\n for (let i = 0; i < patchNeighborIndices.length; i++) {\n const j = patchNeighborIndices[i];\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n positions[i] = refPos;\n }\n const A = new Array(K);\n for (let i = 0; i < K; i++) {\n A[i] = new Float32Array(K);\n }\n for (let i = 0; i < K; i++) {\n const [pix, piy, piz] = positions[i];\n for (let j = i + 1; j < K; j++) {\n const [pjx, pjy, pjz] = positions[j];\n const dist = Math.sqrt((pix - pjx) * (pix - pjx) + (piy - pjy) * (piy - pjy) + (piz - pjz) * (piz - pjz));\n A[i][j] = dist;\n A[j][i] = dist;\n }\n A[i][i] = epsilon;\n }\n A_array[p] = A;\n }\n for (let p = 0; p < patchCenters.length; p++) {\n if (!isUsedArr[p]) {\n continue;\n }\n const patchNeighborIndices = neighborIndices[p];\n const K = patchNeighborIndices.length;\n const usedRef = new Array(K);\n const usedDist = new Array(K);\n for (let i = 0; i < K; i++) {\n const idx = patchNeighborIndices[i];\n const j = idx;\n const refPos = [refVerts[j * 3 + 0], refVerts[j * 3 + 1], refVerts[j * 3 + 2]];\n const distPos = [distVerts[j * 3 + 0], distVerts[j * 3 + 1], distVerts[j * 3 + 2]];\n usedRef[i] = refPos;\n usedDist[i] = distPos;\n }\n const A = A_array[p];\n const bx = new Float32Array(K);\n const by = new Float32Array(K);\n const bz = new Float32Array(K);\n for (let i = 0; i < K; i++) {\n const dr = usedDist[i];\n const rr = usedRef[i];\n bx[i] = dr[0] - rr[0];\n by[i] = dr[1] - rr[1];\n bz[i] = dr[2] - rr[2];\n }\n const Abuffers = A.map((r) => r.buffer);\n weights[p] = new Float32Array(patchRBFWorkerFunc([Abuffers, bx.buffer, by.buffer, bz.buffer]));\n }\n const neighborIndicesBuf = neighborIndices.map((a) => {\n return a.buffer;\n });\n const weightsBuf = weights.map((a) => {\n return a.buffer;\n });\n return [neighborIndicesBuf, weightsBuf, nearestPatch.buffer];\n }\n const WorkerTypeToFunction = {\n "patchRBF": patchRBFWorkerFunc,\n "RBFDeformerSolveAsync": RBFDeformerSolveAsync\n };\n function getWorkerOnMessage() {\n return function(event) {\n const [id, type, data] = event.data;\n const func = WorkerTypeToFunction[type];\n self.postMessage([id, func(data)]);\n };\n }\n onmessage = getWorkerOnMessage();\n})();\n';
|
|
29242
29249
|
const blob = typeof self !== "undefined" && self.Blob && new Blob(["(self.URL || self.webkitURL).revokeObjectURL(self.location.href);", jsContent], { type: "text/javascript;charset=utf-8" });
|
|
29243
29250
|
function WorkerWrapper(options) {
|
|
29244
29251
|
let objURL;
|
|
@@ -29537,16 +29544,16 @@ const FLAGS = {
|
|
|
29537
29544
|
};
|
|
29538
29545
|
function log(critical, ...args) {
|
|
29539
29546
|
if (critical || FLAGS.VERBOSE_LOGGING) {
|
|
29540
|
-
console.log(args);
|
|
29547
|
+
console.log(...args);
|
|
29541
29548
|
}
|
|
29542
29549
|
}
|
|
29543
29550
|
function warn(critical, ...args) {
|
|
29544
29551
|
if (critical || FLAGS.VERBOSE_LOGGING) {
|
|
29545
|
-
console.warn(args);
|
|
29552
|
+
console.warn(...args);
|
|
29546
29553
|
}
|
|
29547
29554
|
}
|
|
29548
29555
|
function error(...args) {
|
|
29549
|
-
console.error(args);
|
|
29556
|
+
console.error(...args);
|
|
29550
29557
|
}
|
|
29551
29558
|
function time(label) {
|
|
29552
29559
|
if (FLAGS.VERBOSE_LOGGING) {
|
|
@@ -30266,7 +30273,7 @@ class Instance {
|
|
|
30266
30273
|
getPropertyNames() {
|
|
30267
30274
|
return Array.from(this._properties.keys());
|
|
30268
30275
|
}
|
|
30269
|
-
setParent(instance) {
|
|
30276
|
+
setParent(instance, fireEvents = true) {
|
|
30270
30277
|
if (!instance) {
|
|
30271
30278
|
instance = void 0;
|
|
30272
30279
|
}
|
|
@@ -30286,10 +30293,14 @@ class Instance {
|
|
|
30286
30293
|
}
|
|
30287
30294
|
if (instance) {
|
|
30288
30295
|
instance.children.push(this);
|
|
30289
|
-
instance.ChildAdded.Fire(this);
|
|
30290
|
-
instance.AncestryChanged.Fire(this, instance);
|
|
30291
30296
|
}
|
|
30292
|
-
|
|
30297
|
+
if (fireEvents) {
|
|
30298
|
+
if (instance) {
|
|
30299
|
+
instance.ChildAdded.Fire(this);
|
|
30300
|
+
instance.AncestryChanged.Fire(this, instance);
|
|
30301
|
+
}
|
|
30302
|
+
this.AncestryChanged.Fire(this, instance);
|
|
30303
|
+
}
|
|
30293
30304
|
}
|
|
30294
30305
|
Destroy() {
|
|
30295
30306
|
for (const connection of this._connectionReferences) {
|
|
@@ -30344,8 +30355,8 @@ class Instance {
|
|
|
30344
30355
|
return childrenList;
|
|
30345
30356
|
}
|
|
30346
30357
|
GetDescendants() {
|
|
30347
|
-
let descendants = this.
|
|
30348
|
-
for (const child of this.
|
|
30358
|
+
let descendants = this.GetChildren();
|
|
30359
|
+
for (const child of this.GetChildren()) {
|
|
30349
30360
|
descendants = descendants.concat(child.GetDescendants());
|
|
30350
30361
|
}
|
|
30351
30362
|
return descendants;
|
|
@@ -30840,6 +30851,7 @@ class RBX {
|
|
|
30840
30851
|
const content = new Content();
|
|
30841
30852
|
content.sourceType = sourceTypes[i];
|
|
30842
30853
|
switch (content.sourceType) {
|
|
30854
|
+
//2 - Uri, 0 - Object/None,
|
|
30843
30855
|
case 0:
|
|
30844
30856
|
break;
|
|
30845
30857
|
case 1:
|
|
@@ -32583,6 +32595,7 @@ class Outfit {
|
|
|
32583
32595
|
const usedIds = [];
|
|
32584
32596
|
let totalAccessories = 0;
|
|
32585
32597
|
let totalLayered = 0;
|
|
32598
|
+
let totalMakeup = 0;
|
|
32586
32599
|
for (let i = 0; i < this.assets.length; i++) {
|
|
32587
32600
|
const asset = this.assets[i];
|
|
32588
32601
|
if (!(asset instanceof Asset)) {
|
|
@@ -32623,7 +32636,7 @@ class Outfit {
|
|
|
32623
32636
|
});
|
|
32624
32637
|
}
|
|
32625
32638
|
}
|
|
32626
|
-
if (LayeredAssetTypes.includes(asset.assetType.name)) {
|
|
32639
|
+
if (LayeredAssetTypes.includes(asset.assetType.name) && !MakeupAssetTypes.includes(asset.assetType.name)) {
|
|
32627
32640
|
totalLayered += 1;
|
|
32628
32641
|
if (totalLayered > 10) {
|
|
32629
32642
|
issues.push({
|
|
@@ -32633,6 +32646,16 @@ class Outfit {
|
|
|
32633
32646
|
});
|
|
32634
32647
|
}
|
|
32635
32648
|
}
|
|
32649
|
+
if (MakeupAssetTypes.includes(asset.assetType.name)) {
|
|
32650
|
+
totalMakeup += 1;
|
|
32651
|
+
if (totalMakeup > 6) {
|
|
32652
|
+
issues.push({
|
|
32653
|
+
"type": "MakeupLimit",
|
|
32654
|
+
"text": "Too much makeup",
|
|
32655
|
+
assetIndex: i
|
|
32656
|
+
});
|
|
32657
|
+
}
|
|
32658
|
+
}
|
|
32636
32659
|
if (MaxOneOfAssetTypes.includes(asset.assetType.name)) {
|
|
32637
32660
|
for (let j = 0; j < this.assets.length; j++) {
|
|
32638
32661
|
const otherAsset = this.assets[j];
|
|
@@ -34527,7 +34550,7 @@ class FileMesh {
|
|
|
34527
34550
|
decoderModule.destroy(faceArray);
|
|
34528
34551
|
decoderModule.destroy(mesh);
|
|
34529
34552
|
decoderModule.destroy(decoder);
|
|
34530
|
-
|
|
34553
|
+
log(false, this.coreMesh);
|
|
34531
34554
|
}
|
|
34532
34555
|
}
|
|
34533
34556
|
readChunkFACS(view, version) {
|
|
@@ -36069,7 +36092,11 @@ const API = {
|
|
|
36069
36092
|
}
|
|
36070
36093
|
return await response.json();
|
|
36071
36094
|
}
|
|
36072
|
-
}
|
|
36095
|
+
},
|
|
36096
|
+
"RBLXGet": RBLXGet,
|
|
36097
|
+
"RBLXPost": RBLXPost,
|
|
36098
|
+
"RBLXDelete": RBLXDelete,
|
|
36099
|
+
"RBLXPatch": RBLXPatch
|
|
36073
36100
|
};
|
|
36074
36101
|
let currentLoadingThumbnails = false;
|
|
36075
36102
|
function requestIdFromThumbnailInfo(thumbnailInfo) {
|
|
@@ -41185,7 +41212,7 @@ function TraverseRigFromAttachmentsInternal(self2, part, characterParts, buildJo
|
|
|
41185
41212
|
if (attachment.className === "Attachment") {
|
|
41186
41213
|
const attachmentName = attachment.Prop("Name");
|
|
41187
41214
|
const findPos = attachmentName.indexOf(rigAttachmentName);
|
|
41188
|
-
if (findPos) {
|
|
41215
|
+
if (findPos !== -1) {
|
|
41189
41216
|
const jointName = attachmentName.substring(0, findPos);
|
|
41190
41217
|
const joint = part.FindFirstChild(jointName);
|
|
41191
41218
|
if (!joint || joint.className !== "Motor6D") {
|
|
@@ -41193,6 +41220,7 @@ function TraverseRigFromAttachmentsInternal(self2, part, characterParts, buildJo
|
|
|
41193
41220
|
if (part !== characterPart) {
|
|
41194
41221
|
const matchingAttachment = characterPart.FindFirstChild(attachmentName);
|
|
41195
41222
|
if (matchingAttachment && matchingAttachment.className === "Attachment") {
|
|
41223
|
+
log(false, "matchingAtt", part, characterPart, attachmentName);
|
|
41196
41224
|
AdjustRootRigAttachmentPosition(self2, part, characterPart, attachment, matchingAttachment);
|
|
41197
41225
|
{
|
|
41198
41226
|
createJoint(jointName, attachment, matchingAttachment);
|
|
@@ -42630,6 +42658,26 @@ class MeshDesc {
|
|
|
42630
42658
|
const meshIdStr = child.Property("MeshId");
|
|
42631
42659
|
this.mesh = meshIdStr;
|
|
42632
42660
|
this.scaleIsRelative = true;
|
|
42661
|
+
if (!FLAGS.AVATAR_JOINT_UPGRADE) {
|
|
42662
|
+
if (child.FindFirstChildOfClass("Bone")) {
|
|
42663
|
+
this.canHaveSkinning = false;
|
|
42664
|
+
} else {
|
|
42665
|
+
if (child.Prop("Name").includes("Arm")) {
|
|
42666
|
+
const rig = child.parent;
|
|
42667
|
+
if (rig) {
|
|
42668
|
+
const humanoid = rig.FindFirstChildOfClass("Humanoid");
|
|
42669
|
+
if (humanoid) {
|
|
42670
|
+
const side = child.Prop("Name").startsWith("Right") ? "Right" : "Left";
|
|
42671
|
+
const handName = side + "Hand";
|
|
42672
|
+
const hand = rig.FindFirstChild(handName);
|
|
42673
|
+
if (hand && hand.FindFirstChildOfClass("Bone")) {
|
|
42674
|
+
this.canHaveSkinning = false;
|
|
42675
|
+
}
|
|
42676
|
+
}
|
|
42677
|
+
}
|
|
42678
|
+
}
|
|
42679
|
+
}
|
|
42680
|
+
}
|
|
42633
42681
|
const surfaceAppearance = child.FindLastChildOfClass("SurfaceAppearance");
|
|
42634
42682
|
if (surfaceAppearance) {
|
|
42635
42683
|
const color = surfaceAppearance.HasProperty("Color") ? surfaceAppearance.Prop("Color") : new Color3(1, 1, 1);
|
|
@@ -43980,6 +44028,7 @@ function setBoneToCFrame$1(bone, cf) {
|
|
|
43980
44028
|
bone.rotation.y = rad(cf.Orientation[1]);
|
|
43981
44029
|
bone.rotation.z = rad(cf.Orientation[2]);
|
|
43982
44030
|
}
|
|
44031
|
+
const BaseR15Bones = ["Root", "HumanoidRootNode", "LowerTorso", "UpperTorso", "RightUpperArm", "RightLowerArm", "RightHand", "LeftUpperArm", "LeftLowerArm", "LeftHand", "Head", "DynamicHead"];
|
|
43983
44032
|
function getJointForInstances$1(parent, child, includeTransform) {
|
|
43984
44033
|
const childMotor = child.FindFirstChildOfClass("Motor6D");
|
|
43985
44034
|
const parentMotor = parent.FindFirstChildOfClass("Motor6D");
|
|
@@ -44007,6 +44056,21 @@ function boneIsChildOf(bone, parentName) {
|
|
|
44007
44056
|
}
|
|
44008
44057
|
return false;
|
|
44009
44058
|
}
|
|
44059
|
+
function getBoneBaseR15Parent(bone) {
|
|
44060
|
+
let currentParent = bone.parent;
|
|
44061
|
+
if (!currentParent) return;
|
|
44062
|
+
while (currentParent && !BaseR15Bones.includes(currentParent.name)) {
|
|
44063
|
+
currentParent = currentParent.parent;
|
|
44064
|
+
}
|
|
44065
|
+
if (!currentParent) {
|
|
44066
|
+
return bone.parent;
|
|
44067
|
+
} else {
|
|
44068
|
+
return currentParent;
|
|
44069
|
+
}
|
|
44070
|
+
}
|
|
44071
|
+
function boneIsBaseR15(bone) {
|
|
44072
|
+
return BaseR15Bones.includes(bone.name);
|
|
44073
|
+
}
|
|
44010
44074
|
function getMotorsInRig(rigChildren) {
|
|
44011
44075
|
const motors = [];
|
|
44012
44076
|
for (const child of rigChildren) {
|
|
@@ -44025,15 +44089,17 @@ function getBoneDependencies(rig) {
|
|
|
44025
44089
|
let currentSearchOrigin = hrp ? ["Root"] : [];
|
|
44026
44090
|
const children = rig.GetChildren();
|
|
44027
44091
|
const motors = getMotorsInRig(children);
|
|
44092
|
+
const searchedParts = [];
|
|
44028
44093
|
while (currentSearch.length > 0 && currentSearch[0]) {
|
|
44029
44094
|
const newCurrentSearch = [];
|
|
44030
44095
|
const newCurrentSearchOrigin = [];
|
|
44031
44096
|
for (let i = 0; i < currentSearch.length; i++) {
|
|
44032
44097
|
const toSearch = currentSearch[i];
|
|
44098
|
+
searchedParts.push(toSearch);
|
|
44033
44099
|
const selfName = toSearch === hrp ? "HumanoidRootNode" : toSearch.Prop("Name");
|
|
44034
44100
|
names.set(selfName, currentSearchOrigin[i]);
|
|
44035
44101
|
for (const motor of motors) {
|
|
44036
|
-
if (motor.Prop("Part0") === toSearch) {
|
|
44102
|
+
if (motor.Prop("Part0") === toSearch && !searchedParts.includes(motor.parent)) {
|
|
44037
44103
|
newCurrentSearch.push(motor.parent);
|
|
44038
44104
|
newCurrentSearchOrigin.push(selfName);
|
|
44039
44105
|
}
|
|
@@ -44237,7 +44303,8 @@ let SkeletonDesc$1 = class SkeletonDesc {
|
|
|
44237
44303
|
for (let i = 0; i < this.bones.length; i++) {
|
|
44238
44304
|
const bone = this.bones[i];
|
|
44239
44305
|
const partEquivalent = this.getPartEquivalent(selfInstance, bone.name);
|
|
44240
|
-
const
|
|
44306
|
+
const boneParent = boneIsBaseR15(bone) ? getBoneBaseR15Parent(bone) : bone.parent;
|
|
44307
|
+
const parentPartEquivalent = boneParent ? boneParent.name !== "HumanoidRootNode" ? this.getPartEquivalent(selfInstance, boneParent.name) : humanoidRootPartEquivalent : void 0;
|
|
44241
44308
|
let rootBoneCF = new CFrame();
|
|
44242
44309
|
if (bone.name === "Root") {
|
|
44243
44310
|
rootBoneCF = rootBoneCFog;
|
|
@@ -46129,7 +46196,6 @@ class AnimationTrack {
|
|
|
46129
46196
|
partKeyframe.easingStyle = pose.Prop("EasingStyle");
|
|
46130
46197
|
}
|
|
46131
46198
|
} else {
|
|
46132
|
-
warn(false, `Missing either part0 or part1 with names: ${part0Name} ${part1Name}`);
|
|
46133
46199
|
return [void 0, void 0, void 0];
|
|
46134
46200
|
}
|
|
46135
46201
|
if (!motorName || !motorParentName || !partKeyframe) {
|
|
@@ -47206,6 +47272,32 @@ function isSameAccessoryDesc(desc0, desc1) {
|
|
|
47206
47272
|
function isSameMakeupDesc(desc0, desc1) {
|
|
47207
47273
|
return hasSameVal(desc0, desc1, "AssetId") && hasSameVal(desc0, desc1, "MakeupType") && hasSameVal(desc0, desc1, "Order");
|
|
47208
47274
|
}
|
|
47275
|
+
function moveAttachmentsToBase(rigPart) {
|
|
47276
|
+
let nextCollapse = rigPart.GetChildren();
|
|
47277
|
+
let cframeHierarchy = new Array(nextCollapse.length).fill(new CFrame());
|
|
47278
|
+
while (nextCollapse.length > 0) {
|
|
47279
|
+
const newNextCollapse = [];
|
|
47280
|
+
const newCFrameHierarchy = [];
|
|
47281
|
+
for (let i = 0; i < nextCollapse.length; i++) {
|
|
47282
|
+
const child = nextCollapse[i];
|
|
47283
|
+
if (child.className !== "Bone" && child.className !== "Attachment" || !child.HasProperty("CFrame")) {
|
|
47284
|
+
continue;
|
|
47285
|
+
}
|
|
47286
|
+
const selfCFrameHierarchy = cframeHierarchy[i];
|
|
47287
|
+
const originalCFrame = child.Prop("CFrame");
|
|
47288
|
+
const newCFrame = selfCFrameHierarchy.multiply(originalCFrame);
|
|
47289
|
+
child.setProperty("CFrame", newCFrame);
|
|
47290
|
+
const childChildren = child.GetChildren();
|
|
47291
|
+
for (const childChild of childChildren) {
|
|
47292
|
+
newNextCollapse.push(childChild);
|
|
47293
|
+
newCFrameHierarchy.push(newCFrame);
|
|
47294
|
+
}
|
|
47295
|
+
child.setParent(rigPart);
|
|
47296
|
+
}
|
|
47297
|
+
nextCollapse = newNextCollapse;
|
|
47298
|
+
cframeHierarchy = newCFrameHierarchy;
|
|
47299
|
+
}
|
|
47300
|
+
}
|
|
47209
47301
|
class HumanoidDescriptionWrapper extends InstanceWrapper {
|
|
47210
47302
|
static className = "HumanoidDescription";
|
|
47211
47303
|
static requiredProperties = [
|
|
@@ -47860,6 +47952,9 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
|
|
|
47860
47952
|
if (R15Folder) {
|
|
47861
47953
|
const children = R15Folder.GetChildren();
|
|
47862
47954
|
for (const child of children) {
|
|
47955
|
+
if (!FLAGS.AVATAR_JOINT_UPGRADE) {
|
|
47956
|
+
moveAttachmentsToBase(child);
|
|
47957
|
+
}
|
|
47863
47958
|
replaceBodyPart(rig, child);
|
|
47864
47959
|
}
|
|
47865
47960
|
}
|
|
@@ -49473,6 +49568,14 @@ class HSR {
|
|
|
49473
49568
|
}
|
|
49474
49569
|
}
|
|
49475
49570
|
}
|
|
49571
|
+
function exposeAPI() {
|
|
49572
|
+
globalThis.API = API;
|
|
49573
|
+
globalThis.APICACHE = CACHE;
|
|
49574
|
+
globalThis.Authentication = Authentication;
|
|
49575
|
+
}
|
|
49576
|
+
function exposeMesh() {
|
|
49577
|
+
globalThis.fileMeshToTHREEGeometry = fileMeshToTHREEGeometry;
|
|
49578
|
+
}
|
|
49476
49579
|
function getCorners(cframe, size) {
|
|
49477
49580
|
const halfX = size.X / 2;
|
|
49478
49581
|
const halfY = size.Y / 2;
|
|
@@ -49586,13 +49689,15 @@ class OutfitRenderer {
|
|
|
49586
49689
|
hasNewUpdate = false;
|
|
49587
49690
|
lastFrameTime = Date.now() / 100;
|
|
49588
49691
|
animationInterval;
|
|
49692
|
+
animationFPS = 60;
|
|
49693
|
+
deltaTimeMultiplier = 1;
|
|
49589
49694
|
/**
|
|
49590
49695
|
* Creates a new OutfitRenderer which makes it easy to render outfits
|
|
49591
49696
|
* @param auth The authentication object, you should have one you use for everything
|
|
49592
49697
|
* @param outfit The outfit you want to render, it can be updated later by calling setOutfit()
|
|
49593
|
-
* @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm,
|
|
49698
|
+
* @param rigPath The path that contains RigR6.rbxm and RigR15.rbxm, should always be "roavatar://" as rig path is now controlled by FLAGS
|
|
49594
49699
|
*/
|
|
49595
|
-
constructor(auth, outfit, rigPath) {
|
|
49700
|
+
constructor(auth, outfit, rigPath = "roavatar://") {
|
|
49596
49701
|
this.auth = auth;
|
|
49597
49702
|
this.outfit = outfit;
|
|
49598
49703
|
this.currentRigType = outfit.playerAvatarType;
|
|
@@ -49703,7 +49808,7 @@ class OutfitRenderer {
|
|
|
49703
49808
|
*/
|
|
49704
49809
|
startAnimating() {
|
|
49705
49810
|
if (this.animationInterval !== void 0) return;
|
|
49706
|
-
this.lastFrameTime = Date.now() /
|
|
49811
|
+
this.lastFrameTime = Date.now() / 1e3;
|
|
49707
49812
|
this.animationInterval = setInterval(() => {
|
|
49708
49813
|
if (this.currentRig && this.doCameraUpdate) {
|
|
49709
49814
|
this.centerCamera();
|
|
@@ -49713,7 +49818,7 @@ class OutfitRenderer {
|
|
|
49713
49818
|
if (humanoid) {
|
|
49714
49819
|
const animator = humanoid.FindFirstChildOfClass("Animator");
|
|
49715
49820
|
if (animator) {
|
|
49716
|
-
const deltaTime = Date.now() / 1e3 - this.lastFrameTime;
|
|
49821
|
+
const deltaTime = (Date.now() / 1e3 - this.lastFrameTime) * this.deltaTimeMultiplier;
|
|
49717
49822
|
this.lastFrameTime = Date.now() / 1e3;
|
|
49718
49823
|
const animatorW = new AnimatorWrapper(animator);
|
|
49719
49824
|
animatorW.renderAnimation(deltaTime);
|
|
@@ -49722,7 +49827,7 @@ class OutfitRenderer {
|
|
|
49722
49827
|
}
|
|
49723
49828
|
}
|
|
49724
49829
|
}
|
|
49725
|
-
}, 1e3 /
|
|
49830
|
+
}, 1e3 / this.animationFPS);
|
|
49726
49831
|
}
|
|
49727
49832
|
/**
|
|
49728
49833
|
* Stops updating the animation of the outfit per frame
|
|
@@ -49730,6 +49835,7 @@ class OutfitRenderer {
|
|
|
49730
49835
|
stopAnimating() {
|
|
49731
49836
|
if (this.animationInterval) {
|
|
49732
49837
|
clearInterval(this.animationInterval);
|
|
49838
|
+
this.animationInterval = void 0;
|
|
49733
49839
|
}
|
|
49734
49840
|
}
|
|
49735
49841
|
/**
|
|
@@ -49828,6 +49934,7 @@ export {
|
|
|
49828
49934
|
LayeredAssetTypes,
|
|
49829
49935
|
LayeredClothingAssetOrder,
|
|
49830
49936
|
LocalOutfit,
|
|
49937
|
+
MakeupAssetTypes,
|
|
49831
49938
|
MakeupDescriptionWrapper,
|
|
49832
49939
|
MakeupType,
|
|
49833
49940
|
MaxOneOfAssetTypes,
|
|
@@ -49913,6 +50020,8 @@ export {
|
|
|
49913
50020
|
divide,
|
|
49914
50021
|
dot,
|
|
49915
50022
|
download,
|
|
50023
|
+
exposeAPI,
|
|
50024
|
+
exposeMesh,
|
|
49916
50025
|
floor,
|
|
49917
50026
|
gaussian_rbf,
|
|
49918
50027
|
generateUUIDv4,
|