feat: Add wearable and emotes model checks#3370
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Pull Request Test Coverage Report for Build 23449301748Details
💛 - Coveralls |
| "title": "Your file has validation issues", | ||
| "has_errors": "Your file has validation errors that must be fixed before uploading.", | ||
| "triangle_count_exceeded": "Triangle count ({count}) exceeds the limit of {limit} for {category} wearables.", | ||
| "triangle_count_warning": "Triangle count ({count}) may exceed the limit for some wearable categories. The standard limit is 1,500 triangles.", |
There was a problem hiding this comment.
es and zh translations are en translations 😛
src/lib/glbValidation/types.ts
Outdated
| @@ -0,0 +1,39 @@ | |||
| /** Severity level for a GLB validation issue. */ | |||
There was a problem hiding this comment.
the AI went extra verbose here. I think we can trim most of the comments since they are pretty self-explanatory already
…m:decentraland/builder into feat/add-wearable-and-emotes-model-checks
|
Wearable Tris Combiner: If the wearable hide other wearables the creator is allowed to combine the tris per slot. For example: if you want to do a jumpsuit you could create it using the upper body category hiding lower body; in that case you could have 1.5K2= 3K triangles.* In the case of the helmet, if you hide all the head wearables (head, earrings, eyewear, tiara, hat, facial_hair, hair and top_head you can reach the 4k tris, 2 materials and 2 textures) Does it have this into account @LautaroPetaccio ? docs |
…m:decentraland/builder into feat/add-wearable-and-emotes-model-checks
When creators upload wearables or emotes, there is no feedback about whether their GLB files comply with Decentraland's technical requirements. Issues like exceeding triangle limits, oversized textures, or incorrect armature naming are only discovered after submission — during the curation review process. This causes a slow feedback loop: creators submit, wait for review, get rejected, fix, and re-submit.
This PR adds client-side validation that checks the uploaded GLB against the documented spec at upload time and in the item editor, giving creators immediate, actionable feedback. All validation issues are reported as warnings — they never block saving or uploading. Creators see the issues but can always proceed.
How
Validation Engine (
src/lib/glbValidation/)A new module that takes a parsed Three.js GLTF object and runs a battery of checks, returning a flat list of issues. Each issue has a
WARNINGseverity, a machine-readable code, and a translation key with parameters for the UI message.The module is split into:
types.tsValidationIssue,ValidationResult,ValidationSeverityconstants.tsgetEffectiveTriangleLimit()for the Tris Combiner rulewearableValidators.tsemoteValidators.tsindex.tsvalidateWearableGLTF(),validateEmoteGLTF(),revalidateWearableForCategory(),checkTriangleCount()Validators receive the Three.js module as a parameter (via dynamic
import('three')) so they can useinstanceofchecks forMesh,Bone,Camera, etc. This avoids a static dependency on Three.js.Triangle Count Validation & Tris Combiner
Triangle limits depend on the wearable's category and which slots it hides. The Tris Combiner rule allows creators to combine triangle budgets when hiding other slots (e.g., a jumpsuit using upper_body and hiding lower_body gets 1500 + 1500 = 3000 triangles).
Because of this dependency, triangle validation behaves differently at each stage:
The
getEffectiveTriangleLimit(category, hides)function inconstants.tscomputes the combined limit: base category budget + sum of each hidden slot's budget.Integration into the Upload Flow
Single item upload (
ImportStep.tsx):processModel()now callsloadAndValidateModel()fromgetModelData.ts, which loads the GLTF once, determines the item type (emote vs wearable), and runs the validation suite — all in a single WebGL context.ModelData→AcceptedFileProps→ reducer state → context, and displayed in the details step viaValidationIssuesPanel.checkTriangleCount()runs against the already-computedmetrics.triangles(no GLTF reload) and merges the result into the displayed issues.Multi-item upload (
CreateAndEditMultipleItemsModal.tsx):loadAndValidateModel()runs on the model with the category and hides from the wearable config. Files with warnings are accepted; the warnings are shown in the review table.Item editor (
CenterPanel.tsx):ValidationIssuesPanel(non-collapsible in this context).UI Component (
ValidationIssuesPanel)A panel that lists all validation issues, styled for dark theme using CSS modules (
ValidationIssuesPanel.module.css). Warnings are shown in yellow with exclamation icons. The header shows a count.The component accepts a
collapsibleprop (defaults totrue):200pxmax-height to avoid pushing form fields down. Useswidth: 100%to fill its container.60vhmax-height. No toggle arrow or click behavior.The component directory includes an
index.tsbarrel export. Used in three places:WearableDetails— shown above the form when creating/editing a wearableEmoteDetails— shown above the form when creating/editing an emoteCenterPanelvalidation modal — shown when clicking the status indicator in the item editor (withcollapsible={false})State Management
validationIssuesadded toStateDataandAcceptedFilePropsin the CreateSingleItemModal typesSET_VALIDATION_ISSUESaction added to the reducervalidationIssuesexposed through the modal's React contextCreateSingleItemModal, auseMemomerges import-time issues with the category-dependent triangle check, updating whenever the category changesTranslations
All translation keys added under
create_single_item_modal.error.glb_validation.*,validation_issues_panel.*, anditem_editor.center_panel.validation_*inen.json,es.json, andzh.json. Spanish and Chinese translations use real localized text.Validation Rules
All rules report
WARNINGseverity — none block saving or uploading.Wearable Validations
TRIANGLE_COUNT_EXCEEDEDTRIANGLE_COUNT_EXCEEDEDDIMENSIONS_EXCEEDEDAvatarSkin_MATMATERIALS_EXCEEDEDAvatarSkin_MATTEXTURES_EXCEEDEDTEXTURE_RESOLUTION_EXCEEDEDBONE_INFLUENCES_EXCEEDED_endor_neutralsuffixed bonesLEAF_BONES_FOUNDCAMERAS_FOUNDLIGHTS_FOUNDANIMATIONS_IN_WEARABLE_mouth,_eyebrows,_eyesoutside facial categoriesFORBIDDEN_MATERIAL_NAMETriangle limits per category (base, before Tris Combiner):
Tris Combiner examples:
Emote Validations
EMOTE_FRAME_RATEEMOTE_MAX_FRAMESEMOTE_MAX_CLIPSEMOTE_MISSING_KEYFRAMESEMOTE_DISPLACEMENTArmature,Armature_Prop, orArmature_OtherARMATURE_NAMING_Avataror_PropANIMATION_NAMING.mp3and.oggallowedAUDIO_FORMATEmote Prop Validations (when props are detected)
PROP_TRIANGLE_COUNTPROP_MATERIALSPROP_TEXTURESPROP_ARMATURE_BONESScreenshots
The screenshots are illustrative, as the styles of the errors were changed to be better under the dark theme