roavatar-renderer 1.3.6 → 1.4.0
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/dist/index.d.ts +56 -1
- package/dist/index.js +430 -76
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -97,7 +97,7 @@ export declare class AnimationConstraintWrapper extends InstanceWrapper {
|
|
|
97
97
|
setup(): void;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
export declare type AnimationProp = "ClimbAnimation" | "FallAnimation" | "IdleAnimation" | "JumpAnimation" | "MoodAnimation" | "RunAnimation" | "SwimAnimation" | "WalkAnimation" | "dance1" | "dance2" | "dance3" | "toolnone";
|
|
100
|
+
export declare type AnimationProp = "ClimbAnimation" | "FallAnimation" | "IdleAnimation" | "JumpAnimation" | "MoodAnimation" | "RunAnimation" | "SwimAnimation" | "WalkAnimation" | "dance1" | "dance2" | "dance3" | "toolnone" | "pose";
|
|
101
101
|
|
|
102
102
|
export declare const AnimationPropToName: {
|
|
103
103
|
[K in AnimationProp]: string;
|
|
@@ -309,6 +309,9 @@ export declare const API: {
|
|
|
309
309
|
PremiumFeatures: {
|
|
310
310
|
GetSubscription: (userId: number) => Promise<Response | GetSubscription_Result>;
|
|
311
311
|
};
|
|
312
|
+
Subscriptions: {
|
|
313
|
+
HasPlus: () => Promise<Response | boolean>;
|
|
314
|
+
};
|
|
312
315
|
RBLXGet: typeof RBLXGet;
|
|
313
316
|
RBLXPost: typeof RBLXPost;
|
|
314
317
|
RBLXDelete: typeof RBLXDelete;
|
|
@@ -418,6 +421,13 @@ export declare const AssetTypeToMakeupType: {
|
|
|
418
421
|
EyeMakeup: number;
|
|
419
422
|
};
|
|
420
423
|
|
|
424
|
+
export declare class AttachmentWrapper extends InstanceWrapper {
|
|
425
|
+
static className: string;
|
|
426
|
+
static requiredProperties: string[];
|
|
427
|
+
setup(): void;
|
|
428
|
+
getWorldCFrame(): CFrame;
|
|
429
|
+
}
|
|
430
|
+
|
|
421
431
|
export declare class Authentication {
|
|
422
432
|
TOKEN?: string;
|
|
423
433
|
SessionUUID?: string;
|
|
@@ -810,6 +820,9 @@ declare class COREMESH {
|
|
|
810
820
|
getColors(): Uint8Array;
|
|
811
821
|
getIndices(): Uint16Array;
|
|
812
822
|
getTouchingVerts(index: number): number[];
|
|
823
|
+
getEdgeId(v0: number, v1: number): bigint;
|
|
824
|
+
getFaceEdges(i: number): [bigint, bigint, bigint];
|
|
825
|
+
getEdgeCounts(): Map<bigint, number>;
|
|
813
826
|
}
|
|
814
827
|
|
|
815
828
|
export declare function createContentMap(): void;
|
|
@@ -893,6 +906,8 @@ declare class DisposableDesc {
|
|
|
893
906
|
dispose(_renderer: THREE.WebGLRenderer, _scene: THREE.Scene): void;
|
|
894
907
|
}
|
|
895
908
|
|
|
909
|
+
export declare function disposeMesh(scene: THREE.Scene, mesh: THREE.Mesh): void;
|
|
910
|
+
|
|
896
911
|
export declare function distance(v0: Vec3, v1: Vec3): number;
|
|
897
912
|
|
|
898
913
|
export declare function divide(v0: Vec3, v1: Vec3): Vec3;
|
|
@@ -914,8 +929,12 @@ export { Event_2 as Event }
|
|
|
914
929
|
|
|
915
930
|
export declare function exposeAPI(): void;
|
|
916
931
|
|
|
932
|
+
export declare function exposeFLAGS(): void;
|
|
933
|
+
|
|
917
934
|
export declare function exposeMesh(): void;
|
|
918
935
|
|
|
936
|
+
export declare function exposeThumbnailGenerator(): void;
|
|
937
|
+
|
|
919
938
|
export declare const FaceControlNames: string[];
|
|
920
939
|
|
|
921
940
|
export declare class FaceControlsWrapper extends InstanceWrapper {
|
|
@@ -1012,6 +1031,8 @@ export declare class FileMeshSubset {
|
|
|
1012
1031
|
|
|
1013
1032
|
export declare function fileMeshToTHREEGeometry(mesh: FileMesh, canIncludeSkinning?: boolean, forceVertexColor?: Vector3): THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>;
|
|
1014
1033
|
|
|
1034
|
+
export declare function FindFirstMatchingAttachment(attachmentName: string, rig: Instance): Instance | null;
|
|
1035
|
+
|
|
1015
1036
|
export declare const FLAGS: {
|
|
1016
1037
|
HAIR_IS_BODYPART: boolean;
|
|
1017
1038
|
AVATAR_JOINT_UPGRADE: boolean;
|
|
@@ -1045,6 +1066,8 @@ export declare const FLAGS: {
|
|
|
1045
1066
|
LEGACY_WELD_BEHAVIOR: boolean;
|
|
1046
1067
|
USE_RENDERTARGET: boolean;
|
|
1047
1068
|
AUTO_RESTORE_CONTEXT: boolean;
|
|
1069
|
+
RENDERTARGET_TO_CANVASTEXTURE: boolean;
|
|
1070
|
+
THUMBNAIL_TIMEOUT: number;
|
|
1048
1071
|
SHOW_SKELETON_HELPER: boolean;
|
|
1049
1072
|
UPDATE_SKELETON: boolean;
|
|
1050
1073
|
ANIMATE_SKELETON: boolean;
|
|
@@ -1085,16 +1108,26 @@ export declare const FullBodyColors: string[];
|
|
|
1085
1108
|
|
|
1086
1109
|
export declare function gaussian_rbf(v0: Vec3, v1: Vec3, sigma?: number): number;
|
|
1087
1110
|
|
|
1111
|
+
export declare function generateModelThumbnail(auth: Authentication, renderScene: RBXRendererScene, model: Instance, size?: Vec2, type?: ThumbnailType, quality?: number, gltfAutoDownload?: boolean): Promise<ThumbnailResult>;
|
|
1112
|
+
|
|
1113
|
+
export declare function generateOutfitThumbnail(auth: Authentication, outfit: Outfit, size?: Vec2, type?: ThumbnailType, quality?: number, gltfAutoDownload?: boolean): Promise<ThumbnailResult>;
|
|
1114
|
+
|
|
1088
1115
|
export declare function generateUUIDv4(): string;
|
|
1089
1116
|
|
|
1090
1117
|
export declare function GetAttachedPart(accessory: Instance, rig: Instance): Instance | undefined;
|
|
1091
1118
|
|
|
1119
|
+
export declare function getCameraCFrameForAvatarNonCustomized(rig: Instance): CFrame | undefined;
|
|
1120
|
+
|
|
1092
1121
|
export declare function getCameraCFrameForHeadshotCustomized(rig: Instance, fov: number, yRot: number, distance: number): CFrame | undefined;
|
|
1093
1122
|
|
|
1123
|
+
export declare function getCameraOffset(fov: number, extentsSize: Vector3): number;
|
|
1124
|
+
|
|
1094
1125
|
export declare function getDistIndexArray(ref: FileMesh, dist: FileMesh): (number | undefined)[];
|
|
1095
1126
|
|
|
1096
1127
|
export declare function getExtents(cframe: CFrame, parts: Instance[]): [Vector3, Vector3];
|
|
1097
1128
|
|
|
1129
|
+
export declare function getExtentsCenter(extents: [Vector3, Vector3]): Vector3;
|
|
1130
|
+
|
|
1098
1131
|
/**@deprecated this is SO broken */
|
|
1099
1132
|
export declare function getExtentsForParts(parts: Instance[], includeTransform?: boolean): [Vector3, Vector3];
|
|
1100
1133
|
|
|
@@ -1113,10 +1146,16 @@ export declare interface GetInfoForId_Result {
|
|
|
1113
1146
|
|
|
1114
1147
|
export declare function getOffsetArray(inner: FileMesh, outer: FileMesh): ([Vec3, THREE.Quaternion, number] | undefined)[];
|
|
1115
1148
|
|
|
1149
|
+
export declare function getOriginalAttachmentOrientation(attachment: Instance): Vector3;
|
|
1150
|
+
|
|
1151
|
+
export declare function getOriginalAttachmentPosition(attachment: Instance): Vector3;
|
|
1152
|
+
|
|
1116
1153
|
export declare function getOriginalSize(part: Instance): Vector3;
|
|
1117
1154
|
|
|
1118
1155
|
export declare function getRandomBetweenInclusive(min: number, max: number): number;
|
|
1119
1156
|
|
|
1157
|
+
export declare function getRigExtentsWorld(rig: Instance): [Vector3, Vector3];
|
|
1158
|
+
|
|
1120
1159
|
export declare interface GetSubscription_Result {
|
|
1121
1160
|
"subscriptionProductModel": {
|
|
1122
1161
|
"premiumFeatureId": number;
|
|
@@ -2254,6 +2293,8 @@ export declare class RBXRendererScene {
|
|
|
2254
2293
|
scene: THREE.Scene;
|
|
2255
2294
|
camera: THREE.PerspectiveCamera;
|
|
2256
2295
|
controls: OrbitControls | undefined;
|
|
2296
|
+
shouldAnimate: boolean;
|
|
2297
|
+
destroyed: boolean;
|
|
2257
2298
|
effectComposer: EffectComposer | undefined;
|
|
2258
2299
|
scissor?: [number, number, number, number];
|
|
2259
2300
|
viewport?: [number, number, number, number];
|
|
@@ -2274,6 +2315,10 @@ export declare class RBXRendererScene {
|
|
|
2274
2315
|
directionalLight2?: THREE.DirectionalLight;
|
|
2275
2316
|
setRect(bounds: DOMRect): void;
|
|
2276
2317
|
noRect(): void;
|
|
2318
|
+
destroy(): void;
|
|
2319
|
+
exportGLTF(name?: string, autoDownload?: boolean): Promise<ArrayBuffer | {
|
|
2320
|
+
[key: string]: unknown;
|
|
2321
|
+
}>;
|
|
2277
2322
|
}
|
|
2278
2323
|
|
|
2279
2324
|
declare class RBXSimpleView {
|
|
@@ -2503,6 +2548,8 @@ export declare interface Search_Result {
|
|
|
2503
2548
|
}[];
|
|
2504
2549
|
}
|
|
2505
2550
|
|
|
2551
|
+
export declare function setupThumbnailScene(renderScene: RBXRendererScene): void;
|
|
2552
|
+
|
|
2506
2553
|
declare class SimpleView {
|
|
2507
2554
|
view: DataView;
|
|
2508
2555
|
viewOffset: number;
|
|
@@ -2606,6 +2653,10 @@ export declare interface ThumbnailCustomizations_Result {
|
|
|
2606
2653
|
}[];
|
|
2607
2654
|
}
|
|
2608
2655
|
|
|
2656
|
+
export declare type ThumbnailResult = ArrayBuffer | {
|
|
2657
|
+
[key: string]: unknown;
|
|
2658
|
+
} | string | undefined;
|
|
2659
|
+
|
|
2609
2660
|
export declare interface ThumbnailsCustomization_Payload {
|
|
2610
2661
|
thumbnailType: number;
|
|
2611
2662
|
emoteAssetId: number;
|
|
@@ -2616,6 +2667,8 @@ export declare interface ThumbnailsCustomization_Payload {
|
|
|
2616
2667
|
};
|
|
2617
2668
|
}
|
|
2618
2669
|
|
|
2670
|
+
export declare type ThumbnailType = "png" | "webp" | "gltf";
|
|
2671
|
+
|
|
2619
2672
|
export declare class ToolWrapper extends InstanceWrapper {
|
|
2620
2673
|
static className: string;
|
|
2621
2674
|
static requiredProperties: string[];
|
|
@@ -2803,4 +2856,6 @@ export declare const xmlMagic = "<roblox ";
|
|
|
2803
2856
|
|
|
2804
2857
|
export declare function zoomExtents(cameraCFrame: CFrame, modelCFrame: CFrame, modelSize: Vector3, targetFOV: number, distanceScale: number): void;
|
|
2805
2858
|
|
|
2859
|
+
export declare function zoomToExtents(cameraCFrame: CFrame, modelCFrame: CFrame, modelSize: Vector3, fov?: number): void;
|
|
2860
|
+
|
|
2806
2861
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -27277,7 +27277,8 @@ const AnimationPropToName = {
|
|
|
27277
27277
|
"dance1": "dance1",
|
|
27278
27278
|
"dance2": "dance2",
|
|
27279
27279
|
"dance3": "dance3",
|
|
27280
|
-
"toolnone": "toolnone"
|
|
27280
|
+
"toolnone": "toolnone",
|
|
27281
|
+
"pose": "pose"
|
|
27281
27282
|
};
|
|
27282
27283
|
const DefaultAnimations = {
|
|
27283
27284
|
"ClimbAnimation": ["climb", [["ClimbAnim", 507765644n]]],
|
|
@@ -27292,7 +27293,8 @@ const DefaultAnimations = {
|
|
|
27292
27293
|
"dance1": ["dance1", [["2", 507772104n]]],
|
|
27293
27294
|
"dance2": ["dance2", [["2", 507776879n]]],
|
|
27294
27295
|
"dance3": ["dance3", [["2", 507777623n]]],
|
|
27295
|
-
"toolnone": ["toolnone", [["ToolNoneAnim", 507768375n]]]
|
|
27296
|
+
"toolnone": ["toolnone", [["ToolNoneAnim", 507768375n]]],
|
|
27297
|
+
"pose": ["pose", [["pose", 11600209531n]]]
|
|
27296
27298
|
};
|
|
27297
27299
|
const DefaultAnimationsR6 = {
|
|
27298
27300
|
"ClimbAnimation": ["climb", [["ClimbAnim", 180436334n]]],
|
|
@@ -27307,7 +27309,8 @@ const DefaultAnimationsR6 = {
|
|
|
27307
27309
|
"dance1": ["dance1", [["2", 182491065n]]],
|
|
27308
27310
|
"dance2": ["dance2", [["2", 182491277n]]],
|
|
27309
27311
|
"dance3": ["dance3", [["2", 182491423n]]],
|
|
27310
|
-
"toolnone": ["toolnone", [["ToolNoneAnim", 182393478n]]]
|
|
27312
|
+
"toolnone": ["toolnone", [["ToolNoneAnim", 182393478n]]],
|
|
27313
|
+
"pose": ["pose", []]
|
|
27311
27314
|
};
|
|
27312
27315
|
const animNamesR6 = {
|
|
27313
27316
|
idle: [
|
|
@@ -27410,6 +27413,9 @@ const animNamesR15 = {
|
|
|
27410
27413
|
],
|
|
27411
27414
|
mood: [
|
|
27412
27415
|
{ id: "http://www.roblox.com/asset/?id=14366558676", weight: 10 }
|
|
27416
|
+
],
|
|
27417
|
+
pose: [
|
|
27418
|
+
{ id: "http://www.roblox.com/asset/?id=11600209531", weight: 10 }
|
|
27413
27419
|
]
|
|
27414
27420
|
/*wave: [
|
|
27415
27421
|
{ id: "http://www.roblox.com/asset/?id=507770239", weight: 10 }
|
|
@@ -28490,7 +28496,7 @@ function hashVec3Safe(a, b, c) {
|
|
|
28490
28496
|
a = BigInt(a);
|
|
28491
28497
|
b = BigInt(b);
|
|
28492
28498
|
c = BigInt(c);
|
|
28493
|
-
return a *
|
|
28499
|
+
return a * 10000000n + b * 1000n + c * 1n;
|
|
28494
28500
|
}
|
|
28495
28501
|
function calculateMagnitude3D(x, y, z) {
|
|
28496
28502
|
return Math.sqrt(x * x + y * y + z * z);
|
|
@@ -28663,6 +28669,7 @@ function buildVertKD(mesh) {
|
|
|
28663
28669
|
function inheritUV(to, from) {
|
|
28664
28670
|
const meshCollider = new MeshCollider(to);
|
|
28665
28671
|
const faceKD = buildFaceKD(from);
|
|
28672
|
+
const edgeCountMap = from.coreMesh.getEdgeCounts();
|
|
28666
28673
|
for (let i = 0; i < to.coreMesh.numverts; i++) {
|
|
28667
28674
|
const pos = to.coreMesh.getPos(i);
|
|
28668
28675
|
const closest = nearestSearch(faceKD, pos);
|
|
@@ -28671,6 +28678,7 @@ function inheritUV(to, from) {
|
|
|
28671
28678
|
const va = from.coreMesh.getUV(face[0]);
|
|
28672
28679
|
const vb = from.coreMesh.getUV(face[1]);
|
|
28673
28680
|
const vc = from.coreMesh.getUV(face[2]);
|
|
28681
|
+
let newAlpha = 255;
|
|
28674
28682
|
const triangle = from.coreMesh.getTriangle(closestI);
|
|
28675
28683
|
const closestPointPos = closestPointTriangle(pos, triangle);
|
|
28676
28684
|
const barycentricPos = barycentric(closestPointPos, triangle);
|
|
@@ -28678,15 +28686,27 @@ function inheritUV(to, from) {
|
|
|
28678
28686
|
barycentricPos[0] * va[0] + barycentricPos[1] * vb[0] + barycentricPos[2] * vc[0],
|
|
28679
28687
|
barycentricPos[0] * va[1] + barycentricPos[1] * vb[1] + barycentricPos[2] * vc[1]
|
|
28680
28688
|
];
|
|
28689
|
+
if (barycentricPos[0] <= 0.1) {
|
|
28690
|
+
const edgeId = from.coreMesh.getEdgeId(face[1], face[2]);
|
|
28691
|
+
const edgeCount = edgeCountMap.get(edgeId) || 999;
|
|
28692
|
+
if (edgeCount <= 1) newAlpha = 0;
|
|
28693
|
+
} else if (barycentricPos[1] <= 0.1) {
|
|
28694
|
+
const edgeId = from.coreMesh.getEdgeId(face[0], face[2]);
|
|
28695
|
+
const edgeCount = edgeCountMap.get(edgeId) || 999;
|
|
28696
|
+
if (edgeCount <= 1) newAlpha = 0;
|
|
28697
|
+
} else if (barycentricPos[2] <= 0.1) {
|
|
28698
|
+
const edgeId = from.coreMesh.getEdgeId(face[0], face[1]);
|
|
28699
|
+
const edgeCount = edgeCountMap.get(edgeId) || 999;
|
|
28700
|
+
if (edgeCount <= 1) newAlpha = 0;
|
|
28701
|
+
}
|
|
28681
28702
|
const ray = new Ray$1(pos, closestPointPos);
|
|
28682
28703
|
if (meshCollider.raycast(ray)) {
|
|
28683
|
-
|
|
28684
|
-
newUV[1] = -Infinity;
|
|
28704
|
+
newAlpha = 0;
|
|
28685
28705
|
}
|
|
28686
28706
|
if (magnitude(minus(closestPointPos, pos)) > 0.1) {
|
|
28687
|
-
|
|
28688
|
-
newUV[1] = -Infinity;
|
|
28707
|
+
newAlpha = 0;
|
|
28689
28708
|
}
|
|
28709
|
+
to.coreMesh.setColor(i, [255, 255, 255, newAlpha]);
|
|
28690
28710
|
to.coreMesh.setUV(i, newUV);
|
|
28691
28711
|
}
|
|
28692
28712
|
}
|
|
@@ -29505,7 +29525,7 @@ const FLAGS = {
|
|
|
29505
29525
|
//only used by linear algorithms
|
|
29506
29526
|
LAYERED_CLOTHING_ALGORITHM: "rbf",
|
|
29507
29527
|
SHOW_CAGE: false,
|
|
29508
|
-
LAYERED_CLOTHING_COOLDOWN: 0.
|
|
29528
|
+
LAYERED_CLOTHING_COOLDOWN: 0.25,
|
|
29509
29529
|
GET_WORKER_FUNC: DefaultGetWorkerFunc,
|
|
29510
29530
|
RBF_PATCH_COUNT: 300,
|
|
29511
29531
|
//amount of "patches" that are used for layered clothing, multiple verts share the same patch
|
|
@@ -29524,6 +29544,8 @@ const FLAGS = {
|
|
|
29524
29544
|
LEGACY_WELD_BEHAVIOR: false,
|
|
29525
29545
|
USE_RENDERTARGET: true,
|
|
29526
29546
|
AUTO_RESTORE_CONTEXT: true,
|
|
29547
|
+
RENDERTARGET_TO_CANVASTEXTURE: false,
|
|
29548
|
+
THUMBNAIL_TIMEOUT: 750,
|
|
29527
29549
|
//skeleton
|
|
29528
29550
|
SHOW_SKELETON_HELPER: false,
|
|
29529
29551
|
UPDATE_SKELETON: true,
|
|
@@ -33962,6 +33984,36 @@ class COREMESH {
|
|
|
33962
33984
|
}
|
|
33963
33985
|
return touchingVerts;
|
|
33964
33986
|
}
|
|
33987
|
+
getEdgeId(v0, v1) {
|
|
33988
|
+
const [x0, y0, z0] = this.getPos(v0);
|
|
33989
|
+
const [x1, y1, z1] = this.getPos(v1);
|
|
33990
|
+
const v0h = hashVec3Safe(Math.round(x0 * 1e3), Math.round(y0 * 1e3), Math.round(z0 * 1e3));
|
|
33991
|
+
const v1h = hashVec3Safe(Math.round(x1 * 1e3), Math.round(y1 * 1e3), Math.round(z1 * 1e3));
|
|
33992
|
+
const tv0 = v0h < v1h ? v0h : v1h;
|
|
33993
|
+
const tv1 = v0h > v1h ? v0h : v1h;
|
|
33994
|
+
return tv1 * 10000000n + tv0;
|
|
33995
|
+
}
|
|
33996
|
+
getFaceEdges(i) {
|
|
33997
|
+
const face = this.getFace(i);
|
|
33998
|
+
const edge0 = this.getEdgeId(face[0], face[1]);
|
|
33999
|
+
const edge1 = this.getEdgeId(face[1], face[2]);
|
|
34000
|
+
const edge2 = this.getEdgeId(face[2], face[0]);
|
|
34001
|
+
return [edge0, edge1, edge2];
|
|
34002
|
+
}
|
|
34003
|
+
getEdgeCounts() {
|
|
34004
|
+
const edgeCountMap = /* @__PURE__ */ new Map();
|
|
34005
|
+
for (let i = 0; i < this.numfaces; i++) {
|
|
34006
|
+
const edges = this.getFaceEdges(i);
|
|
34007
|
+
for (const edge of edges) {
|
|
34008
|
+
if (!edgeCountMap.has(edge)) {
|
|
34009
|
+
edgeCountMap.set(edge, 1);
|
|
34010
|
+
} else {
|
|
34011
|
+
edgeCountMap.set(edge, edgeCountMap.get(edge) + 1);
|
|
34012
|
+
}
|
|
34013
|
+
}
|
|
34014
|
+
}
|
|
34015
|
+
return edgeCountMap;
|
|
34016
|
+
}
|
|
33965
34017
|
}
|
|
33966
34018
|
class LODS {
|
|
33967
34019
|
lodType = LodType.Unknown;
|
|
@@ -36096,6 +36148,15 @@ const API = {
|
|
|
36096
36148
|
return await response.json();
|
|
36097
36149
|
}
|
|
36098
36150
|
},
|
|
36151
|
+
"Subscriptions": {
|
|
36152
|
+
HasPlus: async function() {
|
|
36153
|
+
const response = await RBLXGet("https://apis.roblox.com/subscriptions/v2/user/subscriptions?ProductType=Blackbird&ResultsPerPage=1");
|
|
36154
|
+
if (response.status !== 200) {
|
|
36155
|
+
return response;
|
|
36156
|
+
}
|
|
36157
|
+
return (await response.json()).subscriptions.length > 0;
|
|
36158
|
+
}
|
|
36159
|
+
},
|
|
36099
36160
|
"RBLXGet": RBLXGet,
|
|
36100
36161
|
"RBLXPost": RBLXPost,
|
|
36101
36162
|
"RBLXDelete": RBLXDelete,
|
|
@@ -42317,27 +42378,7 @@ class MeshDesc {
|
|
|
42317
42378
|
}
|
|
42318
42379
|
return true;
|
|
42319
42380
|
}
|
|
42320
|
-
async
|
|
42321
|
-
if (!this.mesh) {
|
|
42322
|
-
return void 0;
|
|
42323
|
-
}
|
|
42324
|
-
const meshToLoad = this.mesh;
|
|
42325
|
-
const mesh = await API.Asset.GetMesh(meshToLoad, void 0);
|
|
42326
|
-
if (mesh instanceof Response) {
|
|
42327
|
-
warn(true, "Failed to get mesh for compileMesh", mesh);
|
|
42328
|
-
return mesh;
|
|
42329
|
-
}
|
|
42330
|
-
if (!mesh.facs && this.headMesh && mesh.skinning.skinnings.length > 0) {
|
|
42331
|
-
const headMesh = await API.Asset.GetMesh(this.headMesh, void 0, true);
|
|
42332
|
-
if (headMesh instanceof Response) {
|
|
42333
|
-
warn(true, "Failed to get headMesh for compileMesh", headMesh);
|
|
42334
|
-
return headMesh;
|
|
42335
|
-
}
|
|
42336
|
-
if (headMesh.facs) {
|
|
42337
|
-
mesh.facs = headMesh.facs.clone();
|
|
42338
|
-
}
|
|
42339
|
-
}
|
|
42340
|
-
let the_ref_mesh = void 0;
|
|
42381
|
+
async wrapDeformer(mesh) {
|
|
42341
42382
|
if (this.deformerDesc) {
|
|
42342
42383
|
const meshMap = /* @__PURE__ */ new Map();
|
|
42343
42384
|
const meshPromises = [];
|
|
@@ -42366,6 +42407,9 @@ class MeshDesc {
|
|
|
42366
42407
|
await targetDeformer.solveAsync();
|
|
42367
42408
|
targetDeformer.deformMesh();
|
|
42368
42409
|
}
|
|
42410
|
+
}
|
|
42411
|
+
async wrapLayer(mesh) {
|
|
42412
|
+
let the_ref_mesh = void 0;
|
|
42369
42413
|
if (this.layerDesc && this.modelLayersDesc && this.modelLayersDesc.targetCages && this.modelLayersDesc.targetCages.length > 0 && this.modelLayersDesc.targetCFrames && this.modelLayersDesc.targetSizes && this.modelLayersDesc.layers) {
|
|
42370
42414
|
const meshMap = /* @__PURE__ */ new Map();
|
|
42371
42415
|
const meshPromises = [];
|
|
@@ -42503,8 +42547,11 @@ class MeshDesc {
|
|
|
42503
42547
|
offsetMesh(mesh, totalOffset);
|
|
42504
42548
|
}
|
|
42505
42549
|
if (!FLAGS.SHOW_CAGE) the_ref_mesh = void 0;
|
|
42506
|
-
if (FLAGS.HIDE_LAYERED_CLOTHING) return;
|
|
42550
|
+
if (FLAGS.HIDE_LAYERED_CLOTHING) return the_ref_mesh;
|
|
42507
42551
|
}
|
|
42552
|
+
return the_ref_mesh;
|
|
42553
|
+
}
|
|
42554
|
+
async wrapTarget(mesh) {
|
|
42508
42555
|
if (this.target && this.targetOrigin && this.hsrDesc) {
|
|
42509
42556
|
const meshMap = /* @__PURE__ */ new Map();
|
|
42510
42557
|
const meshPromises = [];
|
|
@@ -42537,6 +42584,8 @@ class MeshDesc {
|
|
|
42537
42584
|
doHSR(totalUvToHits, targetCage, mesh, true, `${this.target}-${this.mesh}`);
|
|
42538
42585
|
}
|
|
42539
42586
|
}
|
|
42587
|
+
}
|
|
42588
|
+
async wrapTextureTransfer(mesh) {
|
|
42540
42589
|
if (this.wrapTextureTarget && this.wrapTextureTargetOrigin && this.wrapTextureMinBound && this.wrapTextureMaxBound) {
|
|
42541
42590
|
const meshMap = /* @__PURE__ */ new Map();
|
|
42542
42591
|
const meshPromises = [];
|
|
@@ -42566,11 +42615,38 @@ class MeshDesc {
|
|
|
42566
42615
|
}
|
|
42567
42616
|
for (let i = mesh.coreMesh.numverts - 1; i >= 0; i--) {
|
|
42568
42617
|
const vertUV = mesh.coreMesh.getUV(i);
|
|
42569
|
-
if (vertUV[0] <
|
|
42570
|
-
mesh.coreMesh.
|
|
42618
|
+
if (vertUV[0] < 0.05 || vertUV[0] > 0.95 || vertUV[1] < 0.05 || vertUV[1] > 0.95) {
|
|
42619
|
+
mesh.coreMesh.setColor(i, [255, 255, 255, 0]);
|
|
42571
42620
|
}
|
|
42572
42621
|
}
|
|
42573
42622
|
}
|
|
42623
|
+
}
|
|
42624
|
+
async compileMesh() {
|
|
42625
|
+
if (!this.mesh) return;
|
|
42626
|
+
const meshToLoad = this.mesh;
|
|
42627
|
+
const mesh = await API.Asset.GetMesh(meshToLoad, void 0);
|
|
42628
|
+
if (mesh instanceof Response) {
|
|
42629
|
+
warn(true, "Failed to get mesh for compileMesh", mesh);
|
|
42630
|
+
return mesh;
|
|
42631
|
+
}
|
|
42632
|
+
if (!mesh.facs && this.headMesh && mesh.skinning.skinnings.length > 0) {
|
|
42633
|
+
const headMesh = await API.Asset.GetMesh(this.headMesh, void 0, true);
|
|
42634
|
+
if (headMesh instanceof Response) {
|
|
42635
|
+
warn(true, "Failed to get headMesh for compileMesh", headMesh);
|
|
42636
|
+
return headMesh;
|
|
42637
|
+
}
|
|
42638
|
+
if (headMesh.facs) {
|
|
42639
|
+
mesh.facs = headMesh.facs.clone();
|
|
42640
|
+
}
|
|
42641
|
+
}
|
|
42642
|
+
const wrapDeformerResult = await this.wrapDeformer(mesh);
|
|
42643
|
+
if (wrapDeformerResult instanceof Response) return wrapDeformerResult;
|
|
42644
|
+
const the_ref_mesh = await this.wrapLayer(mesh);
|
|
42645
|
+
if (the_ref_mesh instanceof Response) return the_ref_mesh;
|
|
42646
|
+
const wrapTargetResult = await this.wrapTarget(mesh);
|
|
42647
|
+
if (wrapTargetResult instanceof Response) return wrapTargetResult;
|
|
42648
|
+
const wrapTextureTransferResult = await this.wrapTextureTransfer(mesh);
|
|
42649
|
+
if (wrapTextureTransferResult instanceof Response) return wrapTextureTransferResult;
|
|
42574
42650
|
this.fileMesh = mesh;
|
|
42575
42651
|
const geometry = fileMeshToTHREEGeometry(the_ref_mesh || mesh, this.canHaveSkinning, this.forceVertexColor);
|
|
42576
42652
|
let threeMesh = void 0;
|
|
@@ -42610,6 +42686,9 @@ class MeshDesc {
|
|
|
42610
42686
|
break;
|
|
42611
42687
|
}
|
|
42612
42688
|
}
|
|
42689
|
+
if (child.className === "Decal") {
|
|
42690
|
+
this.forceVertexColor = void 0;
|
|
42691
|
+
}
|
|
42613
42692
|
}
|
|
42614
42693
|
fromPart(child) {
|
|
42615
42694
|
this.canHaveSkinning = false;
|
|
@@ -43126,6 +43205,26 @@ function fastMask(mask, image) {
|
|
|
43126
43205
|
ctx.drawImage(image, 0, 0, mask.width, mask.height);
|
|
43127
43206
|
return canvas;
|
|
43128
43207
|
}
|
|
43208
|
+
function imageDataToCanvas(data, width, height) {
|
|
43209
|
+
const offscreenCanvas = new OffscreenCanvas(width, height);
|
|
43210
|
+
const offscreenCtx = offscreenCanvas.getContext("2d");
|
|
43211
|
+
const canvas = document.createElement("canvas");
|
|
43212
|
+
const ctx = canvas.getContext("2d");
|
|
43213
|
+
canvas.width = width;
|
|
43214
|
+
canvas.height = height;
|
|
43215
|
+
if (!ctx || !offscreenCtx) {
|
|
43216
|
+
throw new Error("Failed to get CanvasContext");
|
|
43217
|
+
}
|
|
43218
|
+
const imgData = new ImageData(new Uint8ClampedArray(data.buffer), width, height);
|
|
43219
|
+
offscreenCtx.putImageData(imgData, 0, 0);
|
|
43220
|
+
ctx.translate(0, height);
|
|
43221
|
+
ctx.scale(1, -1);
|
|
43222
|
+
ctx.drawImage(offscreenCanvas, 0, 0);
|
|
43223
|
+
return canvas;
|
|
43224
|
+
}
|
|
43225
|
+
function imageDataToCanvasTexture(data, width, height) {
|
|
43226
|
+
return new CanvasTexture(imageDataToCanvas(data, width, height));
|
|
43227
|
+
}
|
|
43129
43228
|
class ColorLayer {
|
|
43130
43229
|
color;
|
|
43131
43230
|
bodyPart;
|
|
@@ -43476,7 +43575,7 @@ class MaterialDesc {
|
|
|
43476
43575
|
}
|
|
43477
43576
|
let hasTransparency = false;
|
|
43478
43577
|
const rbxRenderer = RBXRenderer.getRenderer();
|
|
43479
|
-
if (!hasColorLayer && rbxRenderer) {
|
|
43578
|
+
if (!hasColorLayer && rbxRenderer || FLAGS.RENDERTARGET_TO_CANVASTEXTURE && rbxRenderer) {
|
|
43480
43579
|
const data = new Uint8Array(width * height * 4);
|
|
43481
43580
|
await rbxRenderer.readRenderTargetPixelsAsync(renderTarget, 0, 0, width, height, data);
|
|
43482
43581
|
for (let i = 3; i < data.length; i += 4) {
|
|
@@ -43485,6 +43584,15 @@ class MaterialDesc {
|
|
|
43485
43584
|
break;
|
|
43486
43585
|
}
|
|
43487
43586
|
}
|
|
43587
|
+
if (FLAGS.RENDERTARGET_TO_CANVASTEXTURE) {
|
|
43588
|
+
const ogTexture = texture;
|
|
43589
|
+
texture = imageDataToCanvasTexture(data, width, height);
|
|
43590
|
+
texture.colorSpace = textureType === "color" ? SRGBColorSpace : NoColorSpace;
|
|
43591
|
+
texture.wrapS = ogTexture.wrapS;
|
|
43592
|
+
texture.wrapT = ogTexture.wrapT;
|
|
43593
|
+
texture.minFilter = ogTexture.minFilter;
|
|
43594
|
+
texture.magFilter = ogTexture.magFilter;
|
|
43595
|
+
}
|
|
43488
43596
|
}
|
|
43489
43597
|
if (!this.transparent) {
|
|
43490
43598
|
hasTransparency = false;
|
|
@@ -43537,7 +43645,7 @@ class MaterialDesc {
|
|
|
43537
43645
|
}
|
|
43538
43646
|
}
|
|
43539
43647
|
let hasTransparency = false;
|
|
43540
|
-
if (this.transparent) {
|
|
43648
|
+
if (this.transparent || FLAGS.RENDERTARGET_TO_CANVASTEXTURE) {
|
|
43541
43649
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
43542
43650
|
const data = imageData.data;
|
|
43543
43651
|
for (let i = 3; i < data.length; i += 4) {
|
|
@@ -43600,7 +43708,7 @@ class MaterialDesc {
|
|
|
43600
43708
|
if (!hasLayerOfType) return;
|
|
43601
43709
|
if ((hasSpecialUVType || this.bodyPart !== void 0) && FLAGS.USE_RENDERTARGET) {
|
|
43602
43710
|
return "full";
|
|
43603
|
-
} else if (this.layers.length > 1 || hasColorLayer && FLAGS.USE_RENDERTARGET) {
|
|
43711
|
+
} else if ((this.layers.length > 1 || hasColorLayer) && FLAGS.USE_RENDERTARGET) {
|
|
43604
43712
|
return "simple";
|
|
43605
43713
|
} else {
|
|
43606
43714
|
return "direct";
|
|
@@ -43657,13 +43765,15 @@ class MaterialDesc {
|
|
|
43657
43765
|
hasTransparency = true;
|
|
43658
43766
|
}
|
|
43659
43767
|
let material = void 0;
|
|
43768
|
+
const textureTemplate = {};
|
|
43769
|
+
if (colorTexture) textureTemplate.map = colorTexture;
|
|
43770
|
+
if (normalTexture) textureTemplate.normalMap = normalTexture;
|
|
43771
|
+
if (roughnessTexture) textureTemplate.roughnessMap = roughnessTexture;
|
|
43772
|
+
if (metalnessTexture) textureTemplate.metalnessMap = metalnessTexture;
|
|
43773
|
+
if (emissiveTexture) textureTemplate.emissiveMap = emissiveTexture;
|
|
43660
43774
|
if (normalTexture || roughnessTexture || metalnessTexture || emissiveTexture) {
|
|
43661
43775
|
material = new MeshStandardMaterial({
|
|
43662
|
-
|
|
43663
|
-
normalMap: normalTexture,
|
|
43664
|
-
roughnessMap: roughnessTexture,
|
|
43665
|
-
metalnessMap: metalnessTexture,
|
|
43666
|
-
emissiveMap: emissiveTexture,
|
|
43776
|
+
...textureTemplate,
|
|
43667
43777
|
emissiveIntensity: hasEmissive ? this.emissiveStrength : 0,
|
|
43668
43778
|
emissive: hasEmissive ? new Color(this.emissiveTint.R, this.emissiveTint.G, this.emissiveTint.B) : new Color(0, 0, 0),
|
|
43669
43779
|
transparent: hasTransparency,
|
|
@@ -43679,7 +43789,7 @@ class MaterialDesc {
|
|
|
43679
43789
|
});
|
|
43680
43790
|
} else {
|
|
43681
43791
|
material = new MeshPhongMaterial({
|
|
43682
|
-
|
|
43792
|
+
...textureTemplate,
|
|
43683
43793
|
specular: new Color(1 / 102, 1 / 102, 1 / 102),
|
|
43684
43794
|
shininess: 9,
|
|
43685
43795
|
transparent: hasTransparency,
|
|
@@ -44779,31 +44889,7 @@ class SkeletonDesc2 {
|
|
|
44779
44889
|
}
|
|
44780
44890
|
class DisposableDesc {
|
|
44781
44891
|
disposeMesh(scene, mesh) {
|
|
44782
|
-
|
|
44783
|
-
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
44784
|
-
for (const material of materials) {
|
|
44785
|
-
for (const key of Object.keys(material)) {
|
|
44786
|
-
const value = material[key];
|
|
44787
|
-
if (value instanceof Texture) {
|
|
44788
|
-
value.dispose();
|
|
44789
|
-
}
|
|
44790
|
-
}
|
|
44791
|
-
if (material instanceof ShaderMaterial) {
|
|
44792
|
-
const uniforms = material.uniforms;
|
|
44793
|
-
for (const key of Object.keys(uniforms)) {
|
|
44794
|
-
const value = uniforms[key].value;
|
|
44795
|
-
if (value instanceof Texture) {
|
|
44796
|
-
value.dispose();
|
|
44797
|
-
}
|
|
44798
|
-
}
|
|
44799
|
-
}
|
|
44800
|
-
material.dispose();
|
|
44801
|
-
}
|
|
44802
|
-
}
|
|
44803
|
-
if (mesh.geometry) {
|
|
44804
|
-
mesh.geometry.dispose();
|
|
44805
|
-
}
|
|
44806
|
-
scene.remove(mesh);
|
|
44892
|
+
disposeMesh(scene, mesh);
|
|
44807
44893
|
}
|
|
44808
44894
|
disposeMeshes(scene, meshes) {
|
|
44809
44895
|
for (const mesh of meshes) {
|
|
@@ -47061,6 +47147,26 @@ class AnimatorWrapper extends InstanceWrapper {
|
|
|
47061
47147
|
return false;
|
|
47062
47148
|
}
|
|
47063
47149
|
}
|
|
47150
|
+
class AttachmentWrapper extends InstanceWrapper {
|
|
47151
|
+
static className = "Attachment";
|
|
47152
|
+
static requiredProperties = [
|
|
47153
|
+
"Name",
|
|
47154
|
+
"CFrame"
|
|
47155
|
+
];
|
|
47156
|
+
setup() {
|
|
47157
|
+
if (!this.instance.HasProperty("Name")) this.instance.addProperty(new Property("Name", DataType.String), this.instance.className);
|
|
47158
|
+
if (!this.instance.HasProperty("CFrame")) this.instance.addProperty(new Property("CFrame", DataType.CFrame), new CFrame());
|
|
47159
|
+
}
|
|
47160
|
+
getWorldCFrame() {
|
|
47161
|
+
if (this.instance.parent) {
|
|
47162
|
+
if (this.instance.parent.className.includes("Part")) {
|
|
47163
|
+
const parentCF = this.instance.parent.PropOrDefault("CFrame", new CFrame());
|
|
47164
|
+
return parentCF.multiply(this.instance.Prop("CFrame"));
|
|
47165
|
+
}
|
|
47166
|
+
}
|
|
47167
|
+
return this.instance.Prop("CFrame");
|
|
47168
|
+
}
|
|
47169
|
+
}
|
|
47064
47170
|
class BodyColorsWrapper extends InstanceWrapper {
|
|
47065
47171
|
static className = "BodyColors";
|
|
47066
47172
|
static requiredProperties = [
|
|
@@ -48610,6 +48716,7 @@ class HumanoidDescriptionWrapper extends InstanceWrapper {
|
|
|
48610
48716
|
toChange.push("dance2");
|
|
48611
48717
|
toChange.push("dance3");
|
|
48612
48718
|
toChange.push("toolnone");
|
|
48719
|
+
if (this.instance.Prop("IdleAnimation") <= 0) toChange.push("pose");
|
|
48613
48720
|
}
|
|
48614
48721
|
miniPromises.push(this._applyAnimations(humanoid, toChange));
|
|
48615
48722
|
}
|
|
@@ -48979,6 +49086,7 @@ function RegisterWrappers() {
|
|
|
48979
49086
|
WeldWrapper.register();
|
|
48980
49087
|
Motor6DWrapper.register();
|
|
48981
49088
|
ManualWeldWrapper.register();
|
|
49089
|
+
AttachmentWrapper.register();
|
|
48982
49090
|
AnimationConstraintWrapper.register();
|
|
48983
49091
|
AnimatorWrapper.register();
|
|
48984
49092
|
FaceControlsWrapper.register();
|
|
@@ -48989,11 +49097,40 @@ function RegisterWrappers() {
|
|
|
48989
49097
|
BodyColorsWrapper.register();
|
|
48990
49098
|
AccessoryWrapper.register();
|
|
48991
49099
|
}
|
|
49100
|
+
function disposeMesh(scene, mesh) {
|
|
49101
|
+
if (mesh.material) {
|
|
49102
|
+
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
49103
|
+
for (const material of materials) {
|
|
49104
|
+
for (const key of Object.keys(material)) {
|
|
49105
|
+
const value = material[key];
|
|
49106
|
+
if (value instanceof Texture) {
|
|
49107
|
+
value.dispose();
|
|
49108
|
+
}
|
|
49109
|
+
}
|
|
49110
|
+
if (material instanceof ShaderMaterial) {
|
|
49111
|
+
const uniforms = material.uniforms;
|
|
49112
|
+
for (const key of Object.keys(uniforms)) {
|
|
49113
|
+
const value = uniforms[key].value;
|
|
49114
|
+
if (value instanceof Texture) {
|
|
49115
|
+
value.dispose();
|
|
49116
|
+
}
|
|
49117
|
+
}
|
|
49118
|
+
}
|
|
49119
|
+
material.dispose();
|
|
49120
|
+
}
|
|
49121
|
+
}
|
|
49122
|
+
if (mesh.geometry) {
|
|
49123
|
+
mesh.geometry.dispose();
|
|
49124
|
+
}
|
|
49125
|
+
scene.remove(mesh);
|
|
49126
|
+
}
|
|
48992
49127
|
class RBXRendererScene {
|
|
48993
49128
|
//important scene components
|
|
48994
49129
|
scene = new Scene();
|
|
48995
49130
|
camera = new PerspectiveCamera(70, 1 / 1, 0.1, 100);
|
|
48996
49131
|
controls;
|
|
49132
|
+
shouldAnimate = true;
|
|
49133
|
+
destroyed = false;
|
|
48997
49134
|
//renderer
|
|
48998
49135
|
effectComposer;
|
|
48999
49136
|
//viewport
|
|
@@ -49032,6 +49169,39 @@ class RBXRendererScene {
|
|
|
49032
49169
|
this.viewport = [0, 0, 0, 0];
|
|
49033
49170
|
this.scissor = [0, 0, 0, 0];
|
|
49034
49171
|
}
|
|
49172
|
+
destroy() {
|
|
49173
|
+
if (this.destroyed) return;
|
|
49174
|
+
this.destroyed = true;
|
|
49175
|
+
for (const instance of this.renderDescs.keys()) {
|
|
49176
|
+
RBXRenderer.removeInstance(instance, this);
|
|
49177
|
+
}
|
|
49178
|
+
RBXRenderer.scenes.splice(RBXRenderer.scenes.indexOf(this), 1);
|
|
49179
|
+
if (this.plane) {
|
|
49180
|
+
disposeMesh(this.scene, this.plane);
|
|
49181
|
+
this.plane = void 0;
|
|
49182
|
+
}
|
|
49183
|
+
if (this.shadowPlane) {
|
|
49184
|
+
disposeMesh(this.scene, this.shadowPlane);
|
|
49185
|
+
this.shadowPlane = void 0;
|
|
49186
|
+
}
|
|
49187
|
+
}
|
|
49188
|
+
async exportGLTF(name = "scene", autoDownload = true) {
|
|
49189
|
+
return new Promise((resolve, reject) => {
|
|
49190
|
+
const exporter = new GLTFExporter();
|
|
49191
|
+
exporter.parse(this.scene, (gltf) => {
|
|
49192
|
+
if (autoDownload) {
|
|
49193
|
+
if (gltf instanceof ArrayBuffer) {
|
|
49194
|
+
saveByteArray([gltf], `${name}.glb`);
|
|
49195
|
+
} else {
|
|
49196
|
+
download(`${name}.gltf`, JSON.stringify(gltf));
|
|
49197
|
+
}
|
|
49198
|
+
}
|
|
49199
|
+
resolve(gltf);
|
|
49200
|
+
}, (error2) => {
|
|
49201
|
+
reject(error2);
|
|
49202
|
+
});
|
|
49203
|
+
});
|
|
49204
|
+
}
|
|
49035
49205
|
}
|
|
49036
49206
|
class RBXRenderer {
|
|
49037
49207
|
static orbitControlsTarget = [0, 3, 0];
|
|
@@ -49425,6 +49595,7 @@ class RBXRenderer {
|
|
|
49425
49595
|
}
|
|
49426
49596
|
static renderScene(renderScene, autoClear = true) {
|
|
49427
49597
|
if (!RBXRenderer.renderer) return;
|
|
49598
|
+
if (!renderScene.shouldAnimate) return;
|
|
49428
49599
|
RBXRenderer.renderer.autoClear = autoClear;
|
|
49429
49600
|
if (!autoClear) {
|
|
49430
49601
|
RBXRenderer.renderer.clearDepth();
|
|
@@ -49545,6 +49716,7 @@ class RBXRenderer {
|
|
|
49545
49716
|
}
|
|
49546
49717
|
/**Adds an instance to the renderer or updates it */
|
|
49547
49718
|
static addInstance(instance, auth, renderScene = RBXRenderer.firstScene) {
|
|
49719
|
+
if (renderScene.destroyed) return;
|
|
49548
49720
|
const isDecal = instance.className === "Decal";
|
|
49549
49721
|
const isBakedDecal = isDecal && !instance.FindFirstChildOfClass("WrapTextureTransfer");
|
|
49550
49722
|
let isFirstDecal = true;
|
|
@@ -49745,14 +49917,6 @@ class HSR {
|
|
|
49745
49917
|
}
|
|
49746
49918
|
}
|
|
49747
49919
|
}
|
|
49748
|
-
function exposeAPI() {
|
|
49749
|
-
globalThis.API = API;
|
|
49750
|
-
globalThis.APICACHE = CACHE;
|
|
49751
|
-
globalThis.Authentication = Authentication;
|
|
49752
|
-
}
|
|
49753
|
-
function exposeMesh() {
|
|
49754
|
-
globalThis.fileMeshToTHREEGeometry = fileMeshToTHREEGeometry;
|
|
49755
|
-
}
|
|
49756
49920
|
function getCorners(cframe, size) {
|
|
49757
49921
|
const halfX = size.X / 2;
|
|
49758
49922
|
const halfY = size.Y / 2;
|
|
@@ -49815,12 +49979,27 @@ function getExtents(cframe, parts) {
|
|
|
49815
49979
|
}
|
|
49816
49980
|
return [lowerExtents, higherExtents];
|
|
49817
49981
|
}
|
|
49982
|
+
function getExtentsCenter(extents) {
|
|
49983
|
+
return extents[1].minus(extents[0]).divide(new Vector32(2, 2, 2)).add(extents[0]);
|
|
49984
|
+
}
|
|
49818
49985
|
function zoomExtents(cameraCFrame, modelCFrame, modelSize, targetFOV, distanceScale) {
|
|
49819
49986
|
const largestSize = Math.max(modelSize.X, modelSize.Y, modelSize.Z);
|
|
49820
49987
|
const fovMultiplier = 70 / targetFOV;
|
|
49821
49988
|
const lookDir = multiply(normalize(minus(cameraCFrame.Position, modelCFrame.Position)), [distanceScale, distanceScale, distanceScale]);
|
|
49822
49989
|
cameraCFrame.Position = add(modelCFrame.Position, multiply(multiply(lookDir, [largestSize, largestSize, largestSize]), [fovMultiplier, fovMultiplier, fovMultiplier]));
|
|
49823
49990
|
}
|
|
49991
|
+
function getCameraOffset(fov2, extentsSize) {
|
|
49992
|
+
const halfSize = extentsSize.magnitude() / 2;
|
|
49993
|
+
const fovDivisor = Math.tan(rad(fov2 / 2));
|
|
49994
|
+
return halfSize / fovDivisor;
|
|
49995
|
+
}
|
|
49996
|
+
function zoomToExtents(cameraCFrame, modelCFrame, modelSize, fov2 = 70) {
|
|
49997
|
+
const cameraOffset = getCameraOffset(fov2, modelSize);
|
|
49998
|
+
const cameraRotation = new CFrame();
|
|
49999
|
+
cameraRotation.Orientation = cameraCFrame.Orientation;
|
|
50000
|
+
const instancePosition = modelCFrame.Position;
|
|
50001
|
+
cameraCFrame.Position = add(instancePosition, multiply(minus([0, 0, 0], cameraRotation.lookVector()), [cameraOffset, cameraOffset, cameraOffset]));
|
|
50002
|
+
}
|
|
49824
50003
|
function getHeadExtents(rig) {
|
|
49825
50004
|
const head = rig.FindFirstChild("Head");
|
|
49826
50005
|
if (!head) return;
|
|
@@ -49840,6 +50019,16 @@ function getHeadExtents(rig) {
|
|
|
49840
50019
|
const extents = getExtents(head.Prop("CFrame"), headParts);
|
|
49841
50020
|
return extents;
|
|
49842
50021
|
}
|
|
50022
|
+
function getRigExtentsWorld(rig) {
|
|
50023
|
+
const rigParts = [];
|
|
50024
|
+
for (const child of rig.GetDescendants()) {
|
|
50025
|
+
if (child.className === "Part" || child.className === "MeshPart") {
|
|
50026
|
+
rigParts.push(child);
|
|
50027
|
+
}
|
|
50028
|
+
}
|
|
50029
|
+
const extents = getExtents(new CFrame(), rigParts);
|
|
50030
|
+
return extents;
|
|
50031
|
+
}
|
|
49843
50032
|
function getCameraCFrameForHeadshotCustomized(rig, fov2, yRot, distance2) {
|
|
49844
50033
|
const head = rig.FindFirstChild("Head");
|
|
49845
50034
|
if (!head) return;
|
|
@@ -49866,6 +50055,34 @@ function getCameraCFrameForHeadshotCustomized(rig, fov2, yRot, distance2) {
|
|
|
49866
50055
|
zoomExtents(cameraCF, headCenterCF, headLocalExtents[1].minus(headLocalExtents[0]), fov2, distance2);
|
|
49867
50056
|
return cameraCF;
|
|
49868
50057
|
}
|
|
50058
|
+
function getCameraCFrameForAvatarNonCustomized(rig) {
|
|
50059
|
+
const thumbnailCamera = rig.FindFirstChildOfClass("Camera");
|
|
50060
|
+
if (thumbnailCamera) return thumbnailCamera.PropOrDefault("CFrame", new CFrame());
|
|
50061
|
+
let rootPart = rig.PropOrDefault("PrimaryPart", void 0);
|
|
50062
|
+
if (!rootPart) rootPart = rig.FindFirstChildOfClass("Part");
|
|
50063
|
+
if (!rootPart) rootPart = rig.FindFirstChildOfClass("MeshPart");
|
|
50064
|
+
if (!rootPart) return;
|
|
50065
|
+
const rootPartCF = rootPart.PropOrDefault("CFrame", new CFrame()).clone();
|
|
50066
|
+
const worldExtents = getRigExtentsWorld(rig);
|
|
50067
|
+
if (!worldExtents) return;
|
|
50068
|
+
const extentsSize = worldExtents[1].minus(worldExtents[0]);
|
|
50069
|
+
rootPartCF.Position = getExtentsCenter(worldExtents).toVec3();
|
|
50070
|
+
let lookVector = rootPartCF.lookVector();
|
|
50071
|
+
if (Math.abs(lookVector[1]) > 0.95) {
|
|
50072
|
+
lookVector = [0, 0, -1];
|
|
50073
|
+
} else {
|
|
50074
|
+
lookVector[1] = 0;
|
|
50075
|
+
lookVector = normalize(lookVector);
|
|
50076
|
+
}
|
|
50077
|
+
let lookCF = CFrame.lookAt([0, 0, 0], lookVector);
|
|
50078
|
+
lookCF = lookCF.multiply(CFrame.fromEulerAngles(25 * Math.PI / 180, 27.5 * Math.PI / 180, 0, "ZXY"));
|
|
50079
|
+
lookVector = lookCF.lookVector();
|
|
50080
|
+
lookCF.Position = add(rootPartCF.Position, multiply([10, 10, 10], lookVector));
|
|
50081
|
+
lookCF = CFrame.lookAt(lookCF.Position, rootPartCF.Position);
|
|
50082
|
+
const cameraCF = lookCF.clone();
|
|
50083
|
+
zoomExtents(cameraCF, rootPartCF, extentsSize, 70, 1);
|
|
50084
|
+
return cameraCF;
|
|
50085
|
+
}
|
|
49869
50086
|
class OutfitRenderer {
|
|
49870
50087
|
auth;
|
|
49871
50088
|
outfit;
|
|
@@ -50054,6 +50271,128 @@ class OutfitRenderer {
|
|
|
50054
50271
|
}
|
|
50055
50272
|
}
|
|
50056
50273
|
}
|
|
50274
|
+
function renderToRenderTarget(width, height, renderScene) {
|
|
50275
|
+
const renderTarget = new WebGLRenderTarget(width, height, {
|
|
50276
|
+
colorSpace: SRGBColorSpace,
|
|
50277
|
+
generateMipmaps: false,
|
|
50278
|
+
minFilter: LinearFilter,
|
|
50279
|
+
magFilter: LinearFilter,
|
|
50280
|
+
type: UnsignedByteType
|
|
50281
|
+
});
|
|
50282
|
+
const rbxRenderer = RBXRenderer.getRenderer();
|
|
50283
|
+
if (!rbxRenderer) return renderTarget;
|
|
50284
|
+
rbxRenderer.setRenderTarget(renderTarget);
|
|
50285
|
+
rbxRenderer.render(renderScene.scene, renderScene.camera);
|
|
50286
|
+
return renderTarget;
|
|
50287
|
+
}
|
|
50288
|
+
async function renderTargetToCanvas(renderTarget) {
|
|
50289
|
+
const rbxRenderer = RBXRenderer.getRenderer();
|
|
50290
|
+
if (!rbxRenderer) return;
|
|
50291
|
+
const width = renderTarget.width;
|
|
50292
|
+
const height = renderTarget.height;
|
|
50293
|
+
const data = new Uint8Array(width * height * 4);
|
|
50294
|
+
await rbxRenderer.readRenderTargetPixelsAsync(renderTarget, 0, 0, width, height, data);
|
|
50295
|
+
return imageDataToCanvas(data, width, height);
|
|
50296
|
+
}
|
|
50297
|
+
async function generateModelThumbnail(auth, renderScene, model, size = [150, 150], type = "png", quality = 1, gltfAutoDownload = false) {
|
|
50298
|
+
return new Promise((resolve) => {
|
|
50299
|
+
const cameraCFrame = getCameraCFrameForAvatarNonCustomized(model);
|
|
50300
|
+
if (cameraCFrame) {
|
|
50301
|
+
RBXRenderer.setCameraCFrame(cameraCFrame, renderScene);
|
|
50302
|
+
}
|
|
50303
|
+
RBXRenderer.addInstance(model, auth, renderScene);
|
|
50304
|
+
let exportTimeout = setTimeout(doExport, FLAGS.THUMBNAIL_TIMEOUT);
|
|
50305
|
+
const onLoadingConnection = API.Events.OnLoadingAssets.Connect((currentlyLoading) => {
|
|
50306
|
+
if (exportTimeout) {
|
|
50307
|
+
clearTimeout(exportTimeout);
|
|
50308
|
+
exportTimeout = void 0;
|
|
50309
|
+
}
|
|
50310
|
+
if (!currentlyLoading) {
|
|
50311
|
+
exportTimeout = setTimeout(doExport, FLAGS.THUMBNAIL_TIMEOUT);
|
|
50312
|
+
}
|
|
50313
|
+
});
|
|
50314
|
+
async function doExport() {
|
|
50315
|
+
onLoadingConnection.Disconnect();
|
|
50316
|
+
if (type === "gltf") {
|
|
50317
|
+
if (!FLAGS.RENDERTARGET_TO_CANVASTEXTURE && FLAGS.USE_RENDERTARGET) {
|
|
50318
|
+
warn(true, "FLAGS.RENDERTARGET_TO_CANVASTEXTURE is false, GLTF export cannot export render target textures, consider setting this flag to true");
|
|
50319
|
+
}
|
|
50320
|
+
resolve(await renderScene.exportGLTF(`result`, gltfAutoDownload));
|
|
50321
|
+
} else {
|
|
50322
|
+
const renderTarget = renderToRenderTarget(...size, renderScene);
|
|
50323
|
+
const canvasTarget = await renderTargetToCanvas(renderTarget);
|
|
50324
|
+
if (canvasTarget) {
|
|
50325
|
+
resolve(canvasTarget.toDataURL(`image/${type}`, quality));
|
|
50326
|
+
} else {
|
|
50327
|
+
resolve(void 0);
|
|
50328
|
+
}
|
|
50329
|
+
}
|
|
50330
|
+
renderScene.destroy();
|
|
50331
|
+
}
|
|
50332
|
+
});
|
|
50333
|
+
}
|
|
50334
|
+
async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "png", quality = 1, gltfAutoDownload = false) {
|
|
50335
|
+
return new Promise((resolve) => {
|
|
50336
|
+
const renderScene = RBXRenderer.addScene();
|
|
50337
|
+
setupThumbnailScene(renderScene);
|
|
50338
|
+
const outfitRenderer = new OutfitRenderer(auth, outfit, renderScene);
|
|
50339
|
+
if (outfit.playerAvatarType === AvatarType.R6) outfitRenderer.deltaTimeMultiplier = 0;
|
|
50340
|
+
outfitRenderer.startAnimating();
|
|
50341
|
+
let exportTimeout = setTimeout(doExport, FLAGS.THUMBNAIL_TIMEOUT);
|
|
50342
|
+
const onLoadingConnection = API.Events.OnLoadingAssets.Connect((currentlyLoading) => {
|
|
50343
|
+
if (exportTimeout) {
|
|
50344
|
+
clearTimeout(exportTimeout);
|
|
50345
|
+
exportTimeout = void 0;
|
|
50346
|
+
}
|
|
50347
|
+
if (!currentlyLoading) {
|
|
50348
|
+
exportTimeout = setTimeout(doExport, FLAGS.THUMBNAIL_TIMEOUT);
|
|
50349
|
+
}
|
|
50350
|
+
});
|
|
50351
|
+
async function doExport() {
|
|
50352
|
+
onLoadingConnection.Disconnect();
|
|
50353
|
+
if (!outfit.containsAssetType("Gear")) {
|
|
50354
|
+
if (outfit.playerAvatarType === AvatarType.R15) {
|
|
50355
|
+
outfitRenderer.setMainAnimation("pose");
|
|
50356
|
+
}
|
|
50357
|
+
} else {
|
|
50358
|
+
outfitRenderer.setMainAnimation("toolnone");
|
|
50359
|
+
}
|
|
50360
|
+
if (outfitRenderer.currentRig) {
|
|
50361
|
+
const thumbnailResult = await generateModelThumbnail(auth, renderScene, outfitRenderer.currentRig, size, type, quality, gltfAutoDownload);
|
|
50362
|
+
resolve(thumbnailResult);
|
|
50363
|
+
outfitRenderer.stopAnimating();
|
|
50364
|
+
if (outfitRenderer.currentRig) outfitRenderer.currentRig.Destroy();
|
|
50365
|
+
} else {
|
|
50366
|
+
resolve(void 0);
|
|
50367
|
+
}
|
|
50368
|
+
}
|
|
50369
|
+
});
|
|
50370
|
+
}
|
|
50371
|
+
function setupThumbnailScene(renderScene) {
|
|
50372
|
+
renderScene.shouldAnimate = false;
|
|
50373
|
+
renderScene.wellLitDirectionalLightIntensity *= 2;
|
|
50374
|
+
renderScene.shadowEnabled = false;
|
|
50375
|
+
RBXRenderer.setupScene("WellLit", 16777215, renderScene);
|
|
50376
|
+
if (renderScene.plane) renderScene.scene.remove(renderScene.plane);
|
|
50377
|
+
if (renderScene.shadowPlane) renderScene.scene.remove(renderScene.shadowPlane);
|
|
50378
|
+
renderScene.scene.background = null;
|
|
50379
|
+
}
|
|
50380
|
+
function exposeAPI() {
|
|
50381
|
+
globalThis.API = API;
|
|
50382
|
+
globalThis.APICACHE = CACHE;
|
|
50383
|
+
globalThis.Authentication = Authentication;
|
|
50384
|
+
}
|
|
50385
|
+
function exposeMesh() {
|
|
50386
|
+
globalThis.fileMeshToTHREEGeometry = fileMeshToTHREEGeometry;
|
|
50387
|
+
}
|
|
50388
|
+
function exposeFLAGS() {
|
|
50389
|
+
globalThis.FLAGS = FLAGS;
|
|
50390
|
+
}
|
|
50391
|
+
function exposeThumbnailGenerator() {
|
|
50392
|
+
globalThis.generateOutfitThumbnail = generateOutfitThumbnail;
|
|
50393
|
+
globalThis.generateModelThumbnail = generateModelThumbnail;
|
|
50394
|
+
globalThis.setupThumbnailScene = setupThumbnailScene;
|
|
50395
|
+
}
|
|
50057
50396
|
export {
|
|
50058
50397
|
API,
|
|
50059
50398
|
AbbreviationToFaceControlProperty,
|
|
@@ -50083,6 +50422,7 @@ export {
|
|
|
50083
50422
|
AssetTypeToAccessoryType,
|
|
50084
50423
|
AssetTypeToMakeupType,
|
|
50085
50424
|
AssetTypes,
|
|
50425
|
+
AttachmentWrapper,
|
|
50086
50426
|
Authentication,
|
|
50087
50427
|
AvatarType,
|
|
50088
50428
|
BodyColor3s,
|
|
@@ -50120,6 +50460,7 @@ export {
|
|
|
50120
50460
|
FileMesh,
|
|
50121
50461
|
FileMeshSkinning,
|
|
50122
50462
|
FileMeshSubset,
|
|
50463
|
+
FindFirstMatchingAttachment,
|
|
50123
50464
|
FullBodyColors,
|
|
50124
50465
|
GetAttachedPart,
|
|
50125
50466
|
HSR,
|
|
@@ -50217,24 +50558,35 @@ export {
|
|
|
50217
50558
|
defaultShirtTemplateAssetIds,
|
|
50218
50559
|
deformReferenceToBaseBodyParts,
|
|
50219
50560
|
deg,
|
|
50561
|
+
disposeMesh,
|
|
50220
50562
|
distance,
|
|
50221
50563
|
divide,
|
|
50222
50564
|
dot,
|
|
50223
50565
|
download,
|
|
50224
50566
|
exposeAPI,
|
|
50567
|
+
exposeFLAGS,
|
|
50225
50568
|
exposeMesh,
|
|
50569
|
+
exposeThumbnailGenerator,
|
|
50226
50570
|
fileMeshToTHREEGeometry,
|
|
50227
50571
|
floor,
|
|
50228
50572
|
gaussian_rbf,
|
|
50573
|
+
generateModelThumbnail,
|
|
50574
|
+
generateOutfitThumbnail,
|
|
50229
50575
|
generateUUIDv4,
|
|
50576
|
+
getCameraCFrameForAvatarNonCustomized,
|
|
50230
50577
|
getCameraCFrameForHeadshotCustomized,
|
|
50578
|
+
getCameraOffset,
|
|
50231
50579
|
getDistIndexArray,
|
|
50232
50580
|
getExtents,
|
|
50581
|
+
getExtentsCenter,
|
|
50233
50582
|
getExtentsForParts,
|
|
50234
50583
|
getHeadExtents,
|
|
50235
50584
|
getOffsetArray,
|
|
50585
|
+
getOriginalAttachmentOrientation,
|
|
50586
|
+
getOriginalAttachmentPosition,
|
|
50236
50587
|
getOriginalSize,
|
|
50237
50588
|
getRandomBetweenInclusive,
|
|
50589
|
+
getRigExtentsWorld,
|
|
50238
50590
|
getUVtoIndexMap,
|
|
50239
50591
|
getUVtoIndicesMap,
|
|
50240
50592
|
getWorkerOnMessage,
|
|
@@ -50278,6 +50630,7 @@ export {
|
|
|
50278
50630
|
rotationMatrixToEulerAngles,
|
|
50279
50631
|
saveByteArray,
|
|
50280
50632
|
scaleMesh,
|
|
50633
|
+
setupThumbnailScene,
|
|
50281
50634
|
snapToNumber,
|
|
50282
50635
|
specialClamp,
|
|
50283
50636
|
transferSkeleton,
|
|
@@ -50287,5 +50640,6 @@ export {
|
|
|
50287
50640
|
versionToNumber,
|
|
50288
50641
|
vertPosToChunkPos,
|
|
50289
50642
|
xmlMagic,
|
|
50290
|
-
zoomExtents
|
|
50643
|
+
zoomExtents,
|
|
50644
|
+
zoomToExtents
|
|
50291
50645
|
};
|