Clunkily fix the item model

This commit is contained in:
quat1024 2023-07-02 04:51:39 -04:00
parent 24c8c97f00
commit b257241b5e
5 changed files with 46 additions and 9 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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<Random> 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<Random> randomSupplier, RenderContext context) {
context.pushTransform(affineTransformer);
context.pushTransform(itemAffineTransformer);
context.pushTransform(preparer.itemTransformer(stack, randomSupplier));
context.meshConsumer().accept(baseMesh);
context.popTransform();

View File

@ -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<Identifier, Supplier<UnbakedModel>> factories = new HashMap<>();
private final Map<ModelIdentifier, Identifier> itemAssignments = new HashMap<>();
private final Map<Identifier, UnbakedModel> 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<UnbakedModel> 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();
}