fn export_variant_mapping()

in native/src/work_asset/export.rs [71:159]


    fn export_variant_mapping(&self, root: &mut Root, variant_ix_lookup: &HashMap<usize, Tag>) -> Result<Metadata> {
        let mut image_sizer = ImageSizes::new(&self);

        // for each mesh...
        for (m_ix, mesh) in root.meshes.iter_mut().enumerate() {
            // and for each of that mesh's primitives...
            for (p_ix, primitive) in mesh.primitives.iter_mut().enumerate() {
                // retrieve the mapping of tag->material_key
                let variant_mapping = self.variant_mapping(m_ix, p_ix);

                // prepare to build the mapping of tag->material_ix
                let mut tag_to_ix = HashMap::new();

                // loop over the (tag, key) entries in that mapping...
                for (tag, material_key) in variant_mapping.iter() {
                    // map the material key to a glTF material index...
                    if let Some(material_ix) = self.material_ix(material_key) {
                        if *tag == self.default_tag {
                            // there may be a mapping for the default tag, but if so the primitive
                            // must have a default material too, and they must match, and we do
                            // not keep or count it – it's treated elsewhere further down
                            if let Some(default_material_ix) = primitive.material {
                                if default_material_ix.value() == material_ix {
                                    continue;
                                }
                                return Err(format!(
                                    "Huh? Default material {} != variant map entry {} of default tag {}.",
                                    default_material_ix,
                                    material_ix, self.default_tag
                            ));
                            }
                            return Err(format!(
                                "Huh? No default material, but variant map entry {} of default tag {} ",
                                material_ix, self.default_tag
                            ));
                        }

                        // place it into the tag->material_ix mapping
                        tag_to_ix.insert(tag.to_owned(), material_ix);

                        // and update metadata
                        image_sizer.accumulate_material(material_ix, true);
                        image_sizer.accumulate_tagged_material(material_ix, tag);
                    } else {
                        return Err(format!("Huh? Non-existent meld key: {}", material_key));
                    }
                }

                // now handle the primitive's default material, if any
                if let Some(default_material_ix) = primitive.material {
                    let default_material_ix = default_material_ix.value();
                    let is_variational = !tag_to_ix.is_empty();

                    image_sizer.accumulate_material(default_material_ix, is_variational);
                    image_sizer.accumulate_tagged_material(default_material_ix, &self.default_tag);

                    if is_variational {
                        // only map the default tag if there's other tags already in the mapping
                        tag_to_ix.insert(self.default_tag.clone(), default_material_ix);
                    }
                };

                extension::write_variant_map(primitive, &tag_to_ix, &variant_ix_lookup)?;
            }
        }

        // ask metadata sizer to count up all the totals
        let (total_image_size, variational_image_size, per_tag_image_size) = image_sizer.count()?;
        // use it to create an authoritative set of all variational tags
        let tags: HashSet<Tag> = per_tag_image_size.keys().cloned().collect();

        // use it also to create the Tag->AssetSize mapping
        let per_tag_sizes: HashMap<Tag, AssetSizes> = tags
            .iter()
            .map(|tag| (tag.to_owned(), AssetSizes::new(per_tag_image_size[tag])))
            .collect();

        // finally construct & return the Metadata structure
        Ok(Metadata {
            tags,
            total_sizes: AssetSizes {
                texture_bytes: total_image_size,
            },
            variational_sizes: AssetSizes {
                texture_bytes: variational_image_size,
            },
            per_tag_sizes,
        })
    }