feat: Add wearable and emotes model checks#3370
feat: Add wearable and emotes model checks#3370LautaroPetaccio wants to merge 9 commits intomasterfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Pull Request Test Coverage Report for Build 23322235472Details
💛 - 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 |
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. Validation is informational only — it never blocks saving or uploading. Creators can acknowledge warnings and 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 severity (
ERRORorWARNING), 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 error-severity issues are rejected with the concatenated error messages shown in the review table.Item editor (
CenterPanel.tsx):ValidationIssuesPanel.UI Component (
ValidationIssuesPanel)A collapsible panel that lists all validation issues. Errors (red) are shown before warnings (yellow). The header shows a count and can be toggled open/closed. Styled for dark theme to match the builder's UI. When inside a modal, the list can grow up to 60vh; when inline (details step), it's capped at 200px to avoid pushing form fields down.
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 editorState 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
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