roavatar-renderer 1.5.11 → 1.5.13
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 +16 -2
- package/dist/index.js +108 -38
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -341,6 +341,7 @@ export declare const API: {
|
|
|
341
341
|
*/
|
|
342
342
|
GetRBX: (url: string, headers?: HeadersInit, contentRepresentationPriorityList?: any) => Promise<Response | RBX>;
|
|
343
343
|
GetMesh: (url: string, headers?: HeadersInit, readOnly?: boolean) => Promise<FileMesh | Response>;
|
|
344
|
+
GetAssetTypeId: (assetId: string | number) => Promise<number | Response>;
|
|
344
345
|
IsLayered: (id: number) => Promise<boolean | Response>;
|
|
345
346
|
};
|
|
346
347
|
Catalog: {
|
|
@@ -1439,12 +1440,16 @@ export declare const FLAGS: {
|
|
|
1439
1440
|
AUTO_RESTORE_CONTEXT: boolean;
|
|
1440
1441
|
/**RenderTarget textures are converted to CanvasTextures which can be exported */
|
|
1441
1442
|
RENDERTARGET_TO_CANVASTEXTURE: boolean;
|
|
1442
|
-
/**Amount of time thumbnail generator will wait after no assets are being loaded to resolve, should be a little time at least so particles can render */
|
|
1443
|
+
/**Amount of time thumbnail generator will wait after no assets are being loaded to resolve, should be a little time at least so particles can render OR just set PARTICLES_START_FULL = true */
|
|
1443
1444
|
THUMBNAIL_TIMEOUT: number;
|
|
1444
1445
|
/**Always render attachments even when theyre set to not be visible */
|
|
1445
1446
|
ALWAYS_SHOW_ATTACHMENTS: boolean;
|
|
1446
1447
|
/**Multiplier for delta time used by renderer things (does not affect datamodel side of things but particles and such instead) */
|
|
1447
1448
|
RENDERER_DELTA_TIME_MULTIPLIER: number;
|
|
1449
|
+
/**How many seconds particles will presimulate (mainly so they arent incomplete in thumbnail generations) */
|
|
1450
|
+
PARTICLES_START_FULL: number;
|
|
1451
|
+
/**Framerate of presimulation particles */
|
|
1452
|
+
PARTICLES_START_FULL_FRAMERATE: number;
|
|
1448
1453
|
/**shows ThreeJS SkeletonHelper */
|
|
1449
1454
|
SHOW_SKELETON_HELPER: boolean;
|
|
1450
1455
|
/**if set the skeleton helper will only show if the instance has the name */
|
|
@@ -1565,9 +1570,12 @@ export declare function generateModelThumbnail(auth: Authentication, renderScene
|
|
|
1565
1570
|
* **Example on generating 1000x1000 webp thumbnail for blank outfit**
|
|
1566
1571
|
* ```ts
|
|
1567
1572
|
* const outfit = new Outfit()
|
|
1573
|
+
* FLAGS.THUMBNAIL_TIMEOUT = 1 //makes thumbnail generation faster
|
|
1574
|
+
* FLAGS.PARTICLES_START_FULL = 10 //makes emitters appear as if theyve been there for some time (10 seconds)
|
|
1568
1575
|
* FLAGS.RENDERTARGET_TO_CANVASTEXTURE = true //required for gltf export
|
|
1569
1576
|
* const result = await generateOutfitThumbnail(new Authentication(), outfit, [1000,1000], "webp", 0.99)
|
|
1570
1577
|
* FLAGS.RENDERTARGET_TO_CANVASTEXTURE = false
|
|
1578
|
+
* FLAGS.PARTICLES_START_FULL = 0
|
|
1571
1579
|
* console.log(result)
|
|
1572
1580
|
* ```
|
|
1573
1581
|
*/
|
|
@@ -2718,6 +2726,7 @@ export declare class OutfitRenderer {
|
|
|
2718
2726
|
currentRigType: AvatarType;
|
|
2719
2727
|
doCameraUpdateOnLoad: boolean; /**Makes camera update when new avatar has loaded */
|
|
2720
2728
|
doCameraUpdate: boolean; /**Does camera update every frame */
|
|
2729
|
+
doAddInstance: boolean; /**If outfitRenderer should call RBXRenderer.addInstance() */
|
|
2721
2730
|
currentlyChangingRig: boolean;
|
|
2722
2731
|
currentlyUpdating: boolean;
|
|
2723
2732
|
hasNewUpdate: boolean;
|
|
@@ -2762,6 +2771,10 @@ export declare class OutfitRenderer {
|
|
|
2762
2771
|
* Starts updating the animation of the outfit per frame
|
|
2763
2772
|
*/
|
|
2764
2773
|
startAnimating(): void;
|
|
2774
|
+
/**
|
|
2775
|
+
* Updates the animation once
|
|
2776
|
+
*/
|
|
2777
|
+
animateOnce(deltaTimeOverride?: number): void;
|
|
2765
2778
|
/**
|
|
2766
2779
|
* Stops updating the animation of the outfit per frame
|
|
2767
2780
|
*/
|
|
@@ -2769,8 +2782,9 @@ export declare class OutfitRenderer {
|
|
|
2769
2782
|
/**
|
|
2770
2783
|
* Sets the current animation being played
|
|
2771
2784
|
* @param name The name of the animation, for example "idle", "run" or "emote.1234"
|
|
2785
|
+
* @returns If the animation started playing, it may start playing later if it has been queued despite returning false
|
|
2772
2786
|
*/
|
|
2773
|
-
setMainAnimation(name: string):
|
|
2787
|
+
setMainAnimation(name: string): Promise<boolean>;
|
|
2774
2788
|
/**Calls destroy on the rig and stops animating, the OutfitRenderer should not be interacted with after this */
|
|
2775
2789
|
destroy(): void;
|
|
2776
2790
|
}
|
package/dist/index.js
CHANGED
|
@@ -29864,6 +29864,8 @@ const FLAGS = {
|
|
|
29864
29864
|
THUMBNAIL_TIMEOUT: 500,
|
|
29865
29865
|
ALWAYS_SHOW_ATTACHMENTS: false,
|
|
29866
29866
|
RENDERER_DELTA_TIME_MULTIPLIER: 1,
|
|
29867
|
+
PARTICLES_START_FULL: 0,
|
|
29868
|
+
PARTICLES_START_FULL_FRAMERATE: 20,
|
|
29867
29869
|
//skeleton
|
|
29868
29870
|
SHOW_SKELETON_HELPER: false,
|
|
29869
29871
|
SKELETON_HELPER_INSTANCE_NAME: void 0,
|
|
@@ -33766,6 +33768,27 @@ class Outfit {
|
|
|
33766
33768
|
}
|
|
33767
33769
|
}
|
|
33768
33770
|
await Promise.all(assetPromises);
|
|
33771
|
+
const assetDeliveryPromises = [];
|
|
33772
|
+
for (const asset of assetsToAdd) {
|
|
33773
|
+
const assetId = asset.id;
|
|
33774
|
+
if (assetId && !this.getAssetId(assetId)) {
|
|
33775
|
+
assetDeliveryPromises.push(new Promise((resolve) => {
|
|
33776
|
+
API.Asset.GetAssetTypeId(assetId).then((assetTypeId) => {
|
|
33777
|
+
if (!(assetTypeId instanceof Response)) {
|
|
33778
|
+
if (Number(assetTypeId) === assetTypeId) {
|
|
33779
|
+
this.addAsset(assetId, assetTypeId, `${AssetTypes[assetTypeId] || "Asset"} (${assetId})`);
|
|
33780
|
+
resolve(void 0);
|
|
33781
|
+
} else {
|
|
33782
|
+
resolve(void 0);
|
|
33783
|
+
}
|
|
33784
|
+
} else {
|
|
33785
|
+
resolve(void 0);
|
|
33786
|
+
}
|
|
33787
|
+
});
|
|
33788
|
+
}));
|
|
33789
|
+
}
|
|
33790
|
+
}
|
|
33791
|
+
await Promise.all(assetDeliveryPromises);
|
|
33769
33792
|
for (const assetToAdd of assetsToAdd) {
|
|
33770
33793
|
let asset = void 0;
|
|
33771
33794
|
for (const assetIn of this.assets) {
|
|
@@ -36348,6 +36371,14 @@ const API = {
|
|
|
36348
36371
|
}
|
|
36349
36372
|
}
|
|
36350
36373
|
},
|
|
36374
|
+
GetAssetTypeId: async function(assetId) {
|
|
36375
|
+
const response = await RBLXGet("https://assetdelivery.roblox.com/v2/asset?id=" + assetId);
|
|
36376
|
+
if (response.status !== 200) {
|
|
36377
|
+
return response;
|
|
36378
|
+
}
|
|
36379
|
+
const body = await response.json();
|
|
36380
|
+
return body.assetTypeId;
|
|
36381
|
+
},
|
|
36351
36382
|
IsLayered: async function(id) {
|
|
36352
36383
|
const cached = CACHE.IsLayered.get(id);
|
|
36353
36384
|
if (cached !== void 0) {
|
|
@@ -50278,6 +50309,14 @@ class EmitterGroupDesc extends RenderDesc {
|
|
|
50278
50309
|
this.disposeMeshes(scene, originalResults);
|
|
50279
50310
|
this.disposeRenderLists(renderer);
|
|
50280
50311
|
}
|
|
50312
|
+
if (FLAGS.PARTICLES_START_FULL) {
|
|
50313
|
+
for (const emitterDesc of this.emitterDescs) {
|
|
50314
|
+
for (let i = 0; i < Math.min(emitterDesc.lifetime.Max * FLAGS.PARTICLES_START_FULL_FRAMERATE, FLAGS.PARTICLES_START_FULL * FLAGS.PARTICLES_START_FULL_FRAMERATE); i++) {
|
|
50315
|
+
emitterDesc.tick(1 / FLAGS.PARTICLES_START_FULL_FRAMERATE, this);
|
|
50316
|
+
emitterDesc.updateResult(this.renderScene);
|
|
50317
|
+
}
|
|
50318
|
+
}
|
|
50319
|
+
}
|
|
50281
50320
|
return this.results;
|
|
50282
50321
|
}
|
|
50283
50322
|
updateResults() {
|
|
@@ -51484,6 +51523,8 @@ class OutfitRenderer {
|
|
|
51484
51523
|
/**Makes camera update when new avatar has loaded */
|
|
51485
51524
|
doCameraUpdate = false;
|
|
51486
51525
|
/**Does camera update every frame */
|
|
51526
|
+
doAddInstance = true;
|
|
51527
|
+
/**If outfitRenderer should call RBXRenderer.addInstance() */
|
|
51487
51528
|
currentlyChangingRig = false;
|
|
51488
51529
|
currentlyUpdating = false;
|
|
51489
51530
|
hasNewUpdate = false;
|
|
@@ -51534,7 +51575,7 @@ class OutfitRenderer {
|
|
|
51534
51575
|
dataModel.Destroy();
|
|
51535
51576
|
this.currentRig = newRig;
|
|
51536
51577
|
this.currentlyChangingRig = false;
|
|
51537
|
-
RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
|
|
51578
|
+
if (this.doAddInstance) RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
|
|
51538
51579
|
resolve(newRig);
|
|
51539
51580
|
} else {
|
|
51540
51581
|
this.onError.Fire("rig");
|
|
@@ -51572,7 +51613,7 @@ class OutfitRenderer {
|
|
|
51572
51613
|
}
|
|
51573
51614
|
this.currentlyUpdating = false;
|
|
51574
51615
|
if (this.currentRig) {
|
|
51575
|
-
RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
|
|
51616
|
+
if (this.doAddInstance) RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
|
|
51576
51617
|
if (this.doCameraUpdateOnLoad) {
|
|
51577
51618
|
this.centerCamera();
|
|
51578
51619
|
}
|
|
@@ -51590,9 +51631,11 @@ class OutfitRenderer {
|
|
|
51590
51631
|
}
|
|
51591
51632
|
});
|
|
51592
51633
|
} else {
|
|
51634
|
+
this.onError.Fire("rig");
|
|
51593
51635
|
this.currentlyUpdating = false;
|
|
51594
51636
|
}
|
|
51595
51637
|
} else {
|
|
51638
|
+
this.onError.Fire("rig");
|
|
51596
51639
|
this.currentlyUpdating = false;
|
|
51597
51640
|
}
|
|
51598
51641
|
});
|
|
@@ -51633,21 +51676,27 @@ class OutfitRenderer {
|
|
|
51633
51676
|
if (this.currentRig && this.doCameraUpdate) {
|
|
51634
51677
|
this.centerCamera();
|
|
51635
51678
|
}
|
|
51636
|
-
|
|
51637
|
-
|
|
51638
|
-
|
|
51639
|
-
|
|
51640
|
-
|
|
51641
|
-
|
|
51642
|
-
|
|
51643
|
-
|
|
51644
|
-
|
|
51645
|
-
|
|
51646
|
-
|
|
51647
|
-
|
|
51679
|
+
this.animateOnce();
|
|
51680
|
+
}, 1e3 / this.animationFPS);
|
|
51681
|
+
}
|
|
51682
|
+
/**
|
|
51683
|
+
* Updates the animation once
|
|
51684
|
+
*/
|
|
51685
|
+
animateOnce(deltaTimeOverride) {
|
|
51686
|
+
if (this.currentRig && this.auth) {
|
|
51687
|
+
const humanoid = this.currentRig.FindFirstChildOfClass("Humanoid");
|
|
51688
|
+
if (humanoid) {
|
|
51689
|
+
const animator = humanoid.FindFirstChildOfClass("Animator");
|
|
51690
|
+
if (animator) {
|
|
51691
|
+
const deltaTime = deltaTimeOverride || (Date.now() / 1e3 - this.lastFrameTime) * this.deltaTimeMultiplier;
|
|
51692
|
+
this.lastFrameTime = Date.now() / 1e3;
|
|
51693
|
+
const animatorW = new AnimatorWrapper(animator);
|
|
51694
|
+
animatorW.renderAnimation(deltaTime);
|
|
51695
|
+
this.currentRig.preRender();
|
|
51696
|
+
if (this.doAddInstance) RBXRenderer.addInstance(this.currentRig, this.auth, this.renderScene);
|
|
51648
51697
|
}
|
|
51649
51698
|
}
|
|
51650
|
-
}
|
|
51699
|
+
}
|
|
51651
51700
|
}
|
|
51652
51701
|
/**
|
|
51653
51702
|
* Stops updating the animation of the outfit per frame
|
|
@@ -51661,26 +51710,36 @@ class OutfitRenderer {
|
|
|
51661
51710
|
/**
|
|
51662
51711
|
* Sets the current animation being played
|
|
51663
51712
|
* @param name The name of the animation, for example "idle", "run" or "emote.1234"
|
|
51713
|
+
* @returns If the animation started playing, it may start playing later if it has been queued despite returning false
|
|
51664
51714
|
*/
|
|
51665
51715
|
setMainAnimation(name) {
|
|
51666
|
-
|
|
51667
|
-
|
|
51668
|
-
|
|
51669
|
-
|
|
51670
|
-
|
|
51671
|
-
|
|
51672
|
-
|
|
51673
|
-
|
|
51674
|
-
|
|
51675
|
-
|
|
51676
|
-
animatorW.
|
|
51677
|
-
|
|
51716
|
+
return new Promise((resolve) => {
|
|
51717
|
+
if (this.currentRig) {
|
|
51718
|
+
const humanoid = this.currentRig.FindFirstChildOfClass("Humanoid");
|
|
51719
|
+
if (humanoid) {
|
|
51720
|
+
const animator = humanoid.FindFirstChildOfClass("Animator");
|
|
51721
|
+
if (animator) {
|
|
51722
|
+
const animatorW = new AnimatorWrapper(animator);
|
|
51723
|
+
const successfullyPlayed = animatorW.playAnimation(name);
|
|
51724
|
+
if (!successfullyPlayed && name.startsWith("emote.") && name) {
|
|
51725
|
+
const emoteId = BigInt(name.split(".")[1]);
|
|
51726
|
+
animatorW.loadAvatarAnimation(emoteId, true, true).then(() => {
|
|
51727
|
+
resolve(animatorW.playAnimation(name));
|
|
51728
|
+
});
|
|
51729
|
+
} else {
|
|
51730
|
+
resolve(false);
|
|
51731
|
+
}
|
|
51732
|
+
} else {
|
|
51733
|
+
resolve(false);
|
|
51678
51734
|
}
|
|
51735
|
+
} else {
|
|
51736
|
+
resolve(false);
|
|
51679
51737
|
}
|
|
51738
|
+
} else {
|
|
51739
|
+
this._queuedMainAnimation = name;
|
|
51740
|
+
resolve(false);
|
|
51680
51741
|
}
|
|
51681
|
-
}
|
|
51682
|
-
this._queuedMainAnimation = name;
|
|
51683
|
-
}
|
|
51742
|
+
});
|
|
51684
51743
|
}
|
|
51685
51744
|
/**Calls destroy on the rig and stops animating, the OutfitRenderer should not be interacted with after this */
|
|
51686
51745
|
destroy() {
|
|
@@ -51755,15 +51814,26 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
|
|
|
51755
51814
|
const renderScene = RBXRenderer.addScene();
|
|
51756
51815
|
setupThumbnailScene(renderScene);
|
|
51757
51816
|
const outfitRenderer = new OutfitRenderer(auth, outfit, renderScene);
|
|
51817
|
+
outfitRenderer.doAddInstance = false;
|
|
51758
51818
|
if (outfit.playerAvatarType === AvatarType.R6) outfitRenderer.deltaTimeMultiplier = 0;
|
|
51759
|
-
|
|
51760
|
-
|
|
51761
|
-
if (outfit.
|
|
51762
|
-
|
|
51819
|
+
API.Misc.startCurrentlyLoadingAssets("thumbnail-animation");
|
|
51820
|
+
outfitRenderer.onSuccess.Connect(() => {
|
|
51821
|
+
if (!outfit.containsAssetType("Gear")) {
|
|
51822
|
+
if (outfit.playerAvatarType === AvatarType.R15) {
|
|
51823
|
+
outfitRenderer.setMainAnimation("pose").then(() => {
|
|
51824
|
+
API.Misc.stopCurrentlyLoadingAssets("thumbnail-animation");
|
|
51825
|
+
});
|
|
51826
|
+
} else {
|
|
51827
|
+
outfitRenderer.setMainAnimation("idle").then(() => {
|
|
51828
|
+
API.Misc.stopCurrentlyLoadingAssets("thumbnail-animation");
|
|
51829
|
+
});
|
|
51830
|
+
}
|
|
51831
|
+
} else {
|
|
51832
|
+
outfitRenderer.setMainAnimation("toolnone").then(() => {
|
|
51833
|
+
API.Misc.stopCurrentlyLoadingAssets("thumbnail-animation");
|
|
51834
|
+
});
|
|
51763
51835
|
}
|
|
51764
|
-
}
|
|
51765
|
-
outfitRenderer.setMainAnimation("toolnone");
|
|
51766
|
-
}
|
|
51836
|
+
});
|
|
51767
51837
|
let exportTimeout = !API.Misc.getCurrentlyLoading() ? setTimeout(doExport, FLAGS.THUMBNAIL_TIMEOUT) : void 0;
|
|
51768
51838
|
const onLoadingConnection = API.Events.OnLoadingAssets.Connect((currentlyLoading) => {
|
|
51769
51839
|
if (exportTimeout) {
|
|
@@ -51777,10 +51847,10 @@ async function generateOutfitThumbnail(auth, outfit, size = [150, 150], type = "
|
|
|
51777
51847
|
async function doExport() {
|
|
51778
51848
|
onLoadingConnection.Disconnect();
|
|
51779
51849
|
if (outfitRenderer.currentRig) {
|
|
51850
|
+
outfitRenderer.animateOnce(!outfit.containsAssetType("Gear") && outfit.playerAvatarType === AvatarType.R6 ? 0 : 1);
|
|
51780
51851
|
const thumbnailResult = await generateModelThumbnail(auth, renderScene, outfitRenderer.currentRig, size, type, quality, gltfAutoDownload);
|
|
51781
51852
|
console.log("Generated outfit thumbnail after seconds:", (performance.now() - startTime) / 1e3);
|
|
51782
51853
|
resolve(thumbnailResult);
|
|
51783
|
-
outfitRenderer.stopAnimating();
|
|
51784
51854
|
if (outfitRenderer.currentRig) outfitRenderer.currentRig.Destroy();
|
|
51785
51855
|
} else {
|
|
51786
51856
|
resolve(void 0);
|