From b257241b5ec0bfd05d5b77cead5790e37e0cc88a Mon Sep 17 00:00:00 2001 From: quat1024 Date: Sun, 2 Jul 2023 04:51:39 -0400 Subject: [PATCH] Clunkily fix the item model --- README.md | 2 -- .../cottonmc/templates/TemplatesClient.java | 4 ++- .../model/AffineQuadTransformer.java | 4 +++ .../templates/model/SlopeBakedModel.java | 11 +++--- .../model/TemplateModelVariantProvider.java | 34 ++++++++++++++++++- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1ff5b65..19de49b 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ Template blocks can be placed in the world, then right-clicked with a full-size ## Todo -* The conceit used in SlopeBakedModel (update mutable state, then bake the mesh) might be inherently flawed - it's not threadsafe -* Fix the item model lol, broke it with the new system (might need a ModelLoadingRegistry registerVariantProvider as a last resort) * Re-generalize the model system (I removed a layer of indirection while rewriting it, so it's just slopes now) * Upside-down slopes would be nice... * Pass UVs as part of the mesh and retexture them at runtime too diff --git a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java index 6a952c0..ca60a71 100644 --- a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java +++ b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java @@ -41,10 +41,12 @@ public class TemplatesClient implements ClientModInitializer { } }); - ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> provider); + ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> provider); //block models + ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> provider); //item models BlockRenderLayerMap.INSTANCE.putBlock(Templates.SLOPE, RenderLayer.getCutout()); provider.addTemplateModel(Templates.id("slope_special"), SlopeUnbakedModel::new); + provider.assignItemModel(Templates.id("slope_special"), Templates.SLOPE); } } diff --git a/src/main/java/io/github/cottonmc/templates/model/AffineQuadTransformer.java b/src/main/java/io/github/cottonmc/templates/model/AffineQuadTransformer.java index 816e604..56cb952 100644 --- a/src/main/java/io/github/cottonmc/templates/model/AffineQuadTransformer.java +++ b/src/main/java/io/github/cottonmc/templates/model/AffineQuadTransformer.java @@ -3,6 +3,8 @@ package io.github.cottonmc.templates.model; import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; import net.minecraft.util.math.AffineTransformation; +import net.minecraft.util.math.AffineTransformations; +import net.minecraft.util.math.Direction; import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; @@ -12,6 +14,8 @@ public record AffineQuadTransformer(Matrix4f affineMatrix) implements RenderCont this(aff.getMatrix()); } + public static final AffineQuadTransformer EAST = new AffineQuadTransformer(AffineTransformations.DIRECTION_ROTATIONS.get(Direction.EAST)); + @Override public boolean transform(MutableQuadView quad) { Vector3f pos3 = new Vector3f(); diff --git a/src/main/java/io/github/cottonmc/templates/model/SlopeBakedModel.java b/src/main/java/io/github/cottonmc/templates/model/SlopeBakedModel.java index 6ef0e69..961b799 100644 --- a/src/main/java/io/github/cottonmc/templates/model/SlopeBakedModel.java +++ b/src/main/java/io/github/cottonmc/templates/model/SlopeBakedModel.java @@ -1,6 +1,5 @@ package io.github.cottonmc.templates.model; -import net.fabricmc.fabric.api.renderer.v1.RendererAccess; import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; @@ -19,12 +18,14 @@ public final class SlopeBakedModel extends ForwardingBakedModel { this.wrapped = baseModel; this.preparer = new SlopeQuadTransformFactory(tam); - this.affineTransformer = new AffineQuadTransformer(aff); + this.blockAffineTransformer = new AffineQuadTransformer(aff); + this.itemAffineTransformer = AffineQuadTransformer.EAST; //Makes items point the same way as stairs. Kinda clunky this.baseMesh = SlopeBaseMesh.make(); } private final TemplateQuadTransformFactory preparer; - private final RenderContext.QuadTransform affineTransformer; + private final AffineQuadTransformer blockAffineTransformer; + private final AffineQuadTransformer itemAffineTransformer; private final Mesh baseMesh; @Override @@ -34,7 +35,7 @@ public final class SlopeBakedModel extends ForwardingBakedModel { @Override public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { - context.pushTransform(affineTransformer); + context.pushTransform(blockAffineTransformer); context.pushTransform(preparer.blockTransformer(blockView, state, pos, randomSupplier)); context.meshConsumer().accept(baseMesh); context.popTransform(); @@ -43,7 +44,7 @@ public final class SlopeBakedModel extends ForwardingBakedModel { @Override public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { - context.pushTransform(affineTransformer); + context.pushTransform(itemAffineTransformer); context.pushTransform(preparer.itemTransformer(stack, randomSupplier)); context.meshConsumer().accept(baseMesh); context.popTransform(); diff --git a/src/main/java/io/github/cottonmc/templates/model/TemplateModelVariantProvider.java b/src/main/java/io/github/cottonmc/templates/model/TemplateModelVariantProvider.java index 92216f3..6d05675 100644 --- a/src/main/java/io/github/cottonmc/templates/model/TemplateModelVariantProvider.java +++ b/src/main/java/io/github/cottonmc/templates/model/TemplateModelVariantProvider.java @@ -3,7 +3,11 @@ package io.github.cottonmc.templates.model; import net.fabricmc.fabric.api.client.model.ModelProviderContext; import net.fabricmc.fabric.api.client.model.ModelProviderException; import net.fabricmc.fabric.api.client.model.ModelResourceProvider; +import net.fabricmc.fabric.api.client.model.ModelVariantProvider; import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.client.util.ModelIdentifier; +import net.minecraft.item.ItemConvertible; +import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; @@ -11,8 +15,10 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; -public class TemplateModelVariantProvider implements ModelResourceProvider { +public class TemplateModelVariantProvider implements ModelResourceProvider, ModelVariantProvider { private final Map> factories = new HashMap<>(); + private final Map itemAssignments = new HashMap<>(); + private final Map cache = new HashMap<>(); @Override @@ -32,10 +38,36 @@ public class TemplateModelVariantProvider implements ModelResourceProvider { return null; } + //For blocks, you can point the game directly at the custom model in the blockstate json file. + //Item models don't have that layer of indirection; it always wants to load the hardcoded "item:id#inventory" model. + //You *would* be able to create a model json for it and set the "parent" field to the custom model, + //but json models are never allowed to have non-json models as a parent, and template unbaked models are not json models. Ah well. + //So, instead, we use a ModelVariantProvider to clunkily redirect the item:id#inventory model to the blockmodel. + //Not my favorite solution (for one, it precludes setting custom rotations in the item model) but we'll live. + @Override + public @Nullable UnbakedModel loadModelVariant(ModelIdentifier modelId, ModelProviderContext context) throws ModelProviderException { + Identifier customModelId = itemAssignments.get(modelId); + return customModelId == null ? null : loadModelResource(customModelId, context); + } + + // "public api" + public void addTemplateModel(Identifier id, Supplier modelFactory) { factories.put(id, modelFactory); } + public void assignItemModel(Identifier templateModelId, ModelIdentifier... modelIds) { + for(ModelIdentifier modelId : modelIds) itemAssignments.put(modelId, templateModelId); + } + + public void assignItemModel(Identifier templateModelId, Identifier... itemIds) { + for(Identifier itemId : itemIds) itemAssignments.put(new ModelIdentifier(itemId, "inventory"), templateModelId); + } + + public void assignItemModel(Identifier templateModelId, ItemConvertible... itemConvs) { + for(ItemConvertible itemConv : itemConvs) assignItemModel(templateModelId, Registries.ITEM.getId(itemConv.asItem())); + } + public void dumpCache() { cache.clear(); }