From 614be779b8c4331fbcbaacac547bb4a275ccece5 Mon Sep 17 00:00:00 2001 From: quat1024 Date: Tue, 4 Jul 2023 01:00:41 -0400 Subject: [PATCH] Json model retexturing (kinda works) --- .gitignore | 4 + README.md | 4 +- .../github/cottonmc/templates/Templates.java | 16 ++- .../cottonmc/templates/TemplatesClient.java | 12 +- .../templates/block/TemplateSlabBlock.java | 29 ++++ ...ransformer.java => MatrixTransformer.java} | 30 +++- .../model/RetexturedJsonModelBakedModel.java | 135 ++++++++++++++++++ .../RetexturedJsonModelUnbakedModel.java | 43 ++++++ ...del.java => RetexturedMeshBakedModel.java} | 26 +--- ...l.java => RetexturedMeshUnbakedModel.java} | 6 +- .../templates/model/SlopeBaseMesh.java | 2 +- .../assets/minecraft/atlases/blocks.json | 9 ++ .../assets/templates/blockstates/slab.json | 13 ++ .../assets/templates/lang/en_us.json | 3 +- .../assets/templates/models/block/cube.json | 12 ++ .../templates/models/block/slab_bottom.json | 49 +++++++ .../templates/models/block/slab_top.json | 49 +++++++ .../templates/models/block/slope_base.json | 4 +- .../textures/templates_special/down.png | Bin 0 -> 536 bytes .../textures/templates_special/east.png | Bin 0 -> 528 bytes .../textures/templates_special/north.png | Bin 0 -> 547 bytes .../textures/templates_special/south.png | Bin 0 -> 564 bytes .../textures/templates_special/up.png | Bin 0 -> 525 bytes .../textures/templates_special/west.png | Bin 0 -> 545 bytes 24 files changed, 407 insertions(+), 39 deletions(-) create mode 100644 src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java rename src/main/java/io/github/cottonmc/templates/model/{MatrixMeshTransformer.java => MatrixTransformer.java} (54%) create mode 100644 src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelBakedModel.java create mode 100644 src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelUnbakedModel.java rename src/main/java/io/github/cottonmc/templates/model/{TemplateBakedModel.java => RetexturedMeshBakedModel.java} (75%) rename src/main/java/io/github/cottonmc/templates/model/{RetexturedMeshTemplateUnbakedModel.java => RetexturedMeshUnbakedModel.java} (87%) create mode 100644 src/main/resources/assets/minecraft/atlases/blocks.json create mode 100644 src/main/resources/assets/templates/blockstates/slab.json create mode 100644 src/main/resources/assets/templates/models/block/cube.json create mode 100644 src/main/resources/assets/templates/models/block/slab_bottom.json create mode 100644 src/main/resources/assets/templates/models/block/slab_top.json create mode 100644 src/main/resources/assets/templates/textures/templates_special/down.png create mode 100644 src/main/resources/assets/templates/textures/templates_special/east.png create mode 100644 src/main/resources/assets/templates/textures/templates_special/north.png create mode 100644 src/main/resources/assets/templates/textures/templates_special/south.png create mode 100644 src/main/resources/assets/templates/textures/templates_special/up.png create mode 100644 src/main/resources/assets/templates/textures/templates_special/west.png diff --git a/.gitignore b/.gitignore index 4ca0373..51159f8 100755 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ Thumbs.db .DS_Store local.properties .directory + +# krita Moments +*.png~ +*-autosave.kra \ No newline at end of file diff --git a/README.md b/README.md index bf20544..155c5dc 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ You may create your block any way you like, just make sure it has a block entity ## `Mesh`-based models -We will construct a `RetexturedMeshTemplateUnbakedModel`. You need two things - the ID of a parent model, and a `Supplier` to retexture. +We will construct a `RetexturedMeshUnbakedModel`. You need two things - the ID of a parent model, and a `Supplier` to retexture. Fill in the parent model field with the ID of any model. Ideally, this model should have a parent of `block/block`, or at least define *some* non-default rotations (smokey the bear voice *Only You Can Prevent Weirdly Rotated First-Person Models*), set `"gui_light": "front"` (lest the item model look weird), and define a particle texture. @@ -38,7 +38,7 @@ When building the `Mesh`, if you want a face to be dynamically retextured, `.tag (TODO: implement a system for baking unchanging `Sprite`s onto the mesh, potentially by "registering" more tags; the problem is you don't have access to sprite uvs at mesh building time. Or just provide a way to get sprite UVs at mesh building time...?) -That's all you need in order to construct a `RetexturedMeshTemplateUnbakedModel`, so to finish things off: +That's all you need in order to construct a `RetexturedMeshUnbakedModel`, so to finish things off: * Come up with an ID for it * Register it using `TemplatesClient.provider.addTemplateModel` (a thin wrapper around Fabric's `ModelResourceProvider`) diff --git a/src/main/java/io/github/cottonmc/templates/Templates.java b/src/main/java/io/github/cottonmc/templates/Templates.java index 51f51ea..6dcbdd9 100644 --- a/src/main/java/io/github/cottonmc/templates/Templates.java +++ b/src/main/java/io/github/cottonmc/templates/Templates.java @@ -1,6 +1,7 @@ package io.github.cottonmc.templates; import io.github.cottonmc.templates.block.SlopeBlock; +import io.github.cottonmc.templates.block.TemplateSlabBlock; import io.github.cottonmc.templates.block.entity.TemplateEntity; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; @@ -26,20 +27,31 @@ public class Templates implements ModInitializer { FabricBlockEntityTypeBuilder.create(Templates::makeSlopeEntity, SLOPE).build(null) ); + public static final Block SLAB = Registry.register(Registries.BLOCK, id("slab"), new TemplateSlabBlock()); + public static final BlockEntityType SLAB_ENTITY = Registry.register( + Registries.BLOCK_ENTITY_TYPE, id("slab"), + FabricBlockEntityTypeBuilder.create(Templates::makeSlabEntity, SLAB).build(null) + ); + //Overridden in TemplatesClient public static BiConsumer chunkRerenderProxy = (world, pos) -> {}; @Override public void onInitialize() { - Registry.register(Registries.ITEM, id("slope"), (Item) new BlockItem(SLOPE, new Item.Settings())); + Registry.register(Registries.ITEM, id("slope"), new BlockItem(SLOPE, new Item.Settings())); + Registry.register(Registries.ITEM, id("slab"), new BlockItem(SLAB, new Item.Settings())); } public static Identifier id(String path) { return new Identifier(MODID, path); } - //simply for breaking the circular reference in the SLOPE_ENTITY constructor call + //simply for breaking circular references in the registration calls private static TemplateEntity makeSlopeEntity(BlockPos pos, BlockState state) { return new TemplateEntity(SLOPE_ENTITY, pos, state); } + + private static TemplateEntity makeSlabEntity(BlockPos pos, BlockState state) { + return new TemplateEntity(SLAB_ENTITY, pos, state); + } } diff --git a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java index 370f6ef..2c9879d 100644 --- a/src/main/java/io/github/cottonmc/templates/TemplatesClient.java +++ b/src/main/java/io/github/cottonmc/templates/TemplatesClient.java @@ -1,6 +1,7 @@ package io.github.cottonmc.templates; -import io.github.cottonmc.templates.model.RetexturedMeshTemplateUnbakedModel; +import io.github.cottonmc.templates.model.RetexturedJsonModelUnbakedModel; +import io.github.cottonmc.templates.model.RetexturedMeshUnbakedModel; import io.github.cottonmc.templates.model.SlopeBaseMesh; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; @@ -53,9 +54,14 @@ public class TemplatesClient implements ClientModInitializer { ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> provider); //block models ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> provider); //item models - BlockRenderLayerMap.INSTANCE.putBlock(Templates.SLOPE, RenderLayer.getCutout()); + BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), Templates.SLOPE, Templates.SLAB); - provider.addTemplateModel(Templates.id("slope_special"), () -> new RetexturedMeshTemplateUnbakedModel(Templates.id("block/slope_base"), SlopeBaseMesh::make)); + provider.addTemplateModel(Templates.id("slope_special"), () -> new RetexturedMeshUnbakedModel(Templates.id("block/slope_base"), SlopeBaseMesh::make)); provider.assignItemModel(Templates.id("slope_special"), Templates.SLOPE); + + provider.addTemplateModel(Templates.id("cube_special"), () -> new RetexturedJsonModelUnbakedModel(Templates.id("block/cube"))); + provider.addTemplateModel(Templates.id("slab_bottom_special"), () -> new RetexturedJsonModelUnbakedModel(Templates.id("block/slab_bottom"))); + provider.addTemplateModel(Templates.id("slab_top_special"), () -> new RetexturedJsonModelUnbakedModel(Templates.id("block/slab_top"))); + provider.assignItemModel(Templates.id("slab_bottom_special"), Templates.SLAB); } } diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java new file mode 100644 index 0000000..a9f0712 --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateSlabBlock.java @@ -0,0 +1,29 @@ +package io.github.cottonmc.templates.block; + +import io.github.cottonmc.templates.Templates; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.SlabBlock; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; + +public class TemplateSlabBlock extends SlabBlock implements BlockEntityProvider { + public TemplateSlabBlock(Settings settings) { + super(settings); + } + + public TemplateSlabBlock() { + //super(TemplateBlock.configureSettings(Settings.create()) //TODO + super(Settings.create().nonOpaque() + .sounds(BlockSoundGroup.WOOD) + .hardness(0.2f)); //TODO: Material.WOOD + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return Templates.SLAB_ENTITY.instantiate(pos, state); + } +} diff --git a/src/main/java/io/github/cottonmc/templates/model/MatrixMeshTransformer.java b/src/main/java/io/github/cottonmc/templates/model/MatrixTransformer.java similarity index 54% rename from src/main/java/io/github/cottonmc/templates/model/MatrixMeshTransformer.java rename to src/main/java/io/github/cottonmc/templates/model/MatrixTransformer.java index 3b04dda..197ede0 100644 --- a/src/main/java/io/github/cottonmc/templates/model/MatrixMeshTransformer.java +++ b/src/main/java/io/github/cottonmc/templates/model/MatrixTransformer.java @@ -6,20 +6,24 @@ import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; import net.minecraft.util.math.AffineTransformation; +import net.minecraft.util.math.Direction; import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; +import java.util.EnumMap; +import java.util.Map; + /** * Transforms the position of each vertex in a `Mesh`. * The transformation's origin is bumped to (0.5, 0.5, 0.5) just because it's more convenient for me lol. */ -public class MatrixMeshTransformer { - public static Mesh transformAroundCenter(AffineTransformation aff, Mesh oldMesh) { - return transformAroundCenter(aff.getMatrix(), oldMesh); +public class MatrixTransformer { + public static Mesh meshAroundCenter(AffineTransformation aff, Mesh oldMesh) { + return meshAroundCenter(aff.getMatrix(), oldMesh); } - public static Mesh transformAroundCenter(Matrix4f mat, Mesh oldMesh) { + public static Mesh meshAroundCenter(Matrix4f mat, Mesh oldMesh) { Renderer r = TemplatesClient.getFabricRenderer(); MeshBuilder newMesh = r.meshBuilder(); QuadEmitter emitter = newMesh.getEmitter(); @@ -54,4 +58,22 @@ public class MatrixMeshTransformer { return newMesh.build(); } + + //Hard to explain what this is for... + //Basically, the previous incarnation of this mod assembled the north/south/east/west faces all individually. + //This means it was easy to get the orientation of the block correct - to popular the north face of the slope, look at + //the north texture of the theme block. In this version, there is only *one* slope model that is dynamically rotated + //to form the other possible orientations. If I populate the north face of the model using the north face of the theme, + //that model will then be rotated so it's no longer facing the right way. + // + //This seems to work, but I'm kinda surprised I don't need to invert the transformation here, which is a clue that + //I don't really understand all the math, loool + public static Map facePermutation(AffineTransformation aff) { + Map facePermutation = new EnumMap<>(Direction.class); + for(Direction input : Direction.values()) { + Direction output = Direction.transform(aff.getMatrix(), input); + facePermutation.put(input, output); + } + return facePermutation; + } } diff --git a/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelBakedModel.java b/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelBakedModel.java new file mode 100644 index 0000000..a6e9bed --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelBakedModel.java @@ -0,0 +1,135 @@ +package io.github.cottonmc.templates.model; + +import io.github.cottonmc.templates.Templates; +import io.github.cottonmc.templates.TemplatesClient; +import net.fabricmc.fabric.api.renderer.v1.Renderer; +import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial; +import net.fabricmc.fabric.api.renderer.v1.mesh.Mesh; +import net.fabricmc.fabric.api.renderer.v1.mesh.MeshBuilder; +import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter; +import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; +import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel; +import net.fabricmc.fabric.api.renderer.v1.render.RenderContext; +import net.fabricmc.fabric.api.rendering.data.v1.RenderAttachedBlockView; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.BakedQuad; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.BlockRenderView; + +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Supplier; + +public class RetexturedJsonModelBakedModel extends ForwardingBakedModel { + public RetexturedJsonModelBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, Function spriteLookup) { + this.wrapped = baseModel; + this.tam = tam; + + for(int i = 0; i < DIRECTIONS.length; i++) { + SpriteIdentifier id = new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, Templates.id("templates_special/" + DIRECTIONS[i].getName())); + this.specialSprites[i] = Objects.requireNonNull(spriteLookup.apply(id), () -> "Couldn't find sprite " + id + " !"); + } + } + + private record CacheKey(BlockState state, TemplateAppearance appearance) {} + + private final TemplateAppearanceManager tam; + private final ConcurrentHashMap meshCache = new ConcurrentHashMap<>(); + private final Sprite[] specialSprites = new Sprite[DIRECTIONS.length]; + + @Override + public boolean isVanillaAdapter() { + return false; + } + + @Override + public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) { + BlockState template = (((RenderAttachedBlockView) blockView).getBlockEntityRenderAttachment(pos) instanceof BlockState s) ? s : null; + TemplateAppearance ta = template == null || template.isAir() ? tam.getDefaultAppearance() : tam.getAppearance(template); + + CacheKey key = new CacheKey(state, ta); + context.meshConsumer().accept(meshCache.computeIfAbsent(key, this::makeMesh)); + } + + @Override + public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) { + super.emitItemQuads(stack, randomSupplier, context); + } + + protected Mesh makeMesh(CacheKey key) { + Renderer r = TemplatesClient.getFabricRenderer(); + MeshBuilder builder = r.meshBuilder(); + QuadEmitter emitter = builder.getEmitter(); + RenderMaterial mat = key.appearance().getRenderMaterial(); + + Random rand = Random.create(42); + + for(Direction cullFace : DIRECTIONS_AND_NULL) { + for(BakedQuad quad : wrapped.getQuads(key.state, cullFace, rand)) { + emitter.fromVanilla(quad, mat, cullFace); + + QuadUvBounds bounds = QuadUvBounds.read(emitter); + for(int i = 0; i < specialSprites.length; i++) { + if(bounds.displaysSprite(specialSprites[i])) { + bounds.remap(emitter, specialSprites[i], key.appearance().getSprite(DIRECTIONS[i])); + break; + } + } + + emitter.emit(); + } + } + + return builder.build(); + } + + record QuadUvBounds(float minU, float maxU, float minV, float maxV) { + static QuadUvBounds read(QuadView quad) { + float u0 = quad.u(0); float u1 = quad.u(1); float u2 = quad.u(2); float u3 = quad.u(3); + float v0 = quad.v(0); float v1 = quad.v(1); float v2 = quad.v(2); float v3 = quad.v(3); + return new QuadUvBounds( + Math.min(Math.min(u0, u1), Math.min(u2, u3)), + Math.max(Math.max(u0, u1), Math.max(u2, u3)), + Math.min(Math.min(v0, v1), Math.min(v2, v3)), + Math.max(Math.max(v0, v1), Math.max(v2, v3)) + ); + } + + boolean displaysSprite(Sprite sprite) { + return sprite.getMinU() <= minU && sprite.getMaxU() >= maxU && sprite.getMinV() <= minV && sprite.getMaxV() >= maxV; + } + + void remap(MutableQuadView quad, Sprite specialSprite, Sprite newSprite) { + float remappedMinU = rangeRemap(minU, specialSprite.getMinU(), specialSprite.getMaxU(), newSprite.getMinU(), newSprite.getMaxU()); + float remappedMaxU = rangeRemap(maxU, specialSprite.getMinU(), specialSprite.getMaxU(), newSprite.getMinU(), newSprite.getMaxU()); + float remappedMinV = rangeRemap(minV, specialSprite.getMinV(), specialSprite.getMaxV(), newSprite.getMinV(), newSprite.getMaxV()); + float remappedMaxV = rangeRemap(maxV, specialSprite.getMinV(), specialSprite.getMaxV(), newSprite.getMinV(), newSprite.getMaxV()); + + quad.uv(0, MathHelper.approximatelyEquals(quad.u(0), minU) ? remappedMinU : remappedMaxU, MathHelper.approximatelyEquals(quad.v(0), minV) ? remappedMinV : remappedMaxV); + quad.uv(1, MathHelper.approximatelyEquals(quad.u(1), minU) ? remappedMinU : remappedMaxU, MathHelper.approximatelyEquals(quad.v(1), minV) ? remappedMinV : remappedMaxV); + quad.uv(2, MathHelper.approximatelyEquals(quad.u(2), minU) ? remappedMinU : remappedMaxU, MathHelper.approximatelyEquals(quad.v(2), minV) ? remappedMinV : remappedMaxV); + quad.uv(3, MathHelper.approximatelyEquals(quad.u(3), minU) ? remappedMinU : remappedMaxU, MathHelper.approximatelyEquals(quad.v(3), minV) ? remappedMinV : remappedMaxV); + } + + static float rangeRemap(float value, float low1, float high1, float low2, float high2) { + float value2 = MathHelper.clamp(value, low1, high1); + return low2 + (value2 - low1) * (high2 - low2) / (high1 - low1); + } + } + + private static final Direction[] DIRECTIONS = Direction.values(); + private static final Direction[] DIRECTIONS_AND_NULL = new Direction[DIRECTIONS.length + 1]; + static { + System.arraycopy(DIRECTIONS, 0, DIRECTIONS_AND_NULL, 0, DIRECTIONS.length); + } +} diff --git a/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelUnbakedModel.java b/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelUnbakedModel.java new file mode 100644 index 0000000..0d02b31 --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/model/RetexturedJsonModelUnbakedModel.java @@ -0,0 +1,43 @@ +package io.github.cottonmc.templates.model; + +import io.github.cottonmc.templates.TemplatesClient; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.client.render.model.Baker; +import net.minecraft.client.render.model.ModelBakeSettings; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.util.SpriteIdentifier; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; + +public class RetexturedJsonModelUnbakedModel implements UnbakedModel { + public RetexturedJsonModelUnbakedModel(Identifier parent) { + this.parent = parent; + } + + protected final Identifier parent; + + @Override + public Collection getModelDependencies() { + return Collections.singletonList(parent); + } + + @Override + public void setParents(Function function) { + function.apply(parent).setParents(function); + } + + @Nullable + @Override + public BakedModel bake(Baker baker, Function spriteLookup, ModelBakeSettings modelBakeSettings, Identifier identifier) { + return new RetexturedJsonModelBakedModel( + baker.bake(parent, modelBakeSettings), + TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup), + spriteLookup + ); + } +} diff --git a/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshBakedModel.java similarity index 75% rename from src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java rename to src/main/java/io/github/cottonmc/templates/model/RetexturedMeshBakedModel.java index 9d55224..81b645a 100644 --- a/src/main/java/io/github/cottonmc/templates/model/TemplateBakedModel.java +++ b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshBakedModel.java @@ -22,36 +22,20 @@ import net.minecraft.util.math.random.Random; import net.minecraft.world.BlockRenderView; import org.jetbrains.annotations.NotNull; -import java.util.EnumMap; import java.util.Map; import java.util.function.Supplier; -public final class TemplateBakedModel extends ForwardingBakedModel { - public TemplateBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, AffineTransformation aff, Mesh baseMesh) { +public final class RetexturedMeshBakedModel extends ForwardingBakedModel { + public RetexturedMeshBakedModel(BakedModel baseModel, TemplateAppearanceManager tam, AffineTransformation aff, Mesh baseMesh) { this.wrapped = baseModel; - this.tam = tam; - this.baseMesh = MatrixMeshTransformer.transformAroundCenter(aff, baseMesh); - - //Hard to explain what this is for... - //Basically, the previous incarnation of this mod assembled the north/south/east/west faces all individually. - //This means it was easy to get the orientation of the block correct - to popular the north face of the slope, look at - //the north texture of the theme block. In this version, there is only *one* slope model that is dynamically rotated - //to form the other possible orientations. If I populate the north face of the model using the north face of the theme, - //that model will then be rotated so it's no longer facing the right way. - // - //This seems to work, but I'm kinda surprised I don't need to invert the transformation here, which is a clue that - //I don't really understand all the math, loool - for(Direction input : Direction.values()) { - Direction output = Direction.transform(aff.getMatrix(), input); - facePermutation.put(input, output); - } + this.baseMesh = MatrixTransformer.meshAroundCenter(aff, baseMesh); + this.facePermutation = MatrixTransformer.facePermutation(aff); } private final TemplateAppearanceManager tam; private final Mesh baseMesh; - - private final Map facePermutation = new EnumMap<>(Direction.class); + private final Map facePermutation; @Override public boolean isVanillaAdapter() { diff --git a/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshUnbakedModel.java similarity index 87% rename from src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java rename to src/main/java/io/github/cottonmc/templates/model/RetexturedMeshUnbakedModel.java index cc7bfd5..8f4fa93 100644 --- a/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshTemplateUnbakedModel.java +++ b/src/main/java/io/github/cottonmc/templates/model/RetexturedMeshUnbakedModel.java @@ -16,8 +16,8 @@ import java.util.function.Function; import java.util.function.Supplier; @SuppressWarnings("ClassCanBeRecord") -public class RetexturedMeshTemplateUnbakedModel implements UnbakedModel { - public RetexturedMeshTemplateUnbakedModel(Identifier parent, Supplier baseMeshFactory) { +public class RetexturedMeshUnbakedModel implements UnbakedModel { + public RetexturedMeshUnbakedModel(Identifier parent, Supplier baseMeshFactory) { this.parent = parent; this.baseMeshFactory = baseMeshFactory; } @@ -37,7 +37,7 @@ public class RetexturedMeshTemplateUnbakedModel implements UnbakedModel { @Override public BakedModel bake(Baker baker, Function spriteLookup, ModelBakeSettings modelBakeSettings, Identifier identifier) { - return new TemplateBakedModel( + return new RetexturedMeshBakedModel( baker.bake(parent, modelBakeSettings), TemplatesClient.provider.getOrCreateTemplateApperanceManager(spriteLookup), modelBakeSettings.getRotation(), diff --git a/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java b/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java index 3e60fc9..fd37faf 100644 --- a/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java +++ b/src/main/java/io/github/cottonmc/templates/model/SlopeBaseMesh.java @@ -9,7 +9,7 @@ import net.minecraft.util.math.Direction; public class SlopeBaseMesh { /** - * @see TemplateBakedModel.RetexturingTransformer for why these values were chosen + * @see RetexturedMeshBakedModel.RetexturingTransformer for why these values were chosen */ public static final int TAG_SLOPE = Direction.UP.ordinal() + 1; public static final int TAG_LEFT = Direction.EAST.ordinal() + 1; diff --git a/src/main/resources/assets/minecraft/atlases/blocks.json b/src/main/resources/assets/minecraft/atlases/blocks.json new file mode 100644 index 0000000..84cad5f --- /dev/null +++ b/src/main/resources/assets/minecraft/atlases/blocks.json @@ -0,0 +1,9 @@ +{ + "sources": [ + { + "type": "directory", + "source": "templates_special", + "prefix": "templates_special/" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/blockstates/slab.json b/src/main/resources/assets/templates/blockstates/slab.json new file mode 100644 index 0000000..4823b1f --- /dev/null +++ b/src/main/resources/assets/templates/blockstates/slab.json @@ -0,0 +1,13 @@ +{ + "variants": { + "type=bottom": { + "model": "templates:slab_bottom_special" + }, + "type=double": { + "model": "templates:cube_special" + }, + "type=top": { + "model": "templates:slab_top_special" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/lang/en_us.json b/src/main/resources/assets/templates/lang/en_us.json index 580793f..ae32e51 100644 --- a/src/main/resources/assets/templates/lang/en_us.json +++ b/src/main/resources/assets/templates/lang/en_us.json @@ -1,3 +1,4 @@ { - "block.templates.slope": "Slope Template" + "block.templates.slope": "Slope Template", + "block.templates.slab": "Slab Template" } \ No newline at end of file diff --git a/src/main/resources/assets/templates/models/block/cube.json b/src/main/resources/assets/templates/models/block/cube.json new file mode 100644 index 0000000..ae7024a --- /dev/null +++ b/src/main/resources/assets/templates/models/block/cube.json @@ -0,0 +1,12 @@ +{ + "parent": "minecraft:block/cube", + "textures": { + "down": "templates:templates_special/down", + "up": "templates:templates_special/up", + "north": "templates:templates_special/north", + "south": "templates:templates_special/south", + "west": "templates:templates_special/west", + "east": "templates:templates_special/east", + "particle": "minecraft:block/scaffolding_top" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/models/block/slab_bottom.json b/src/main/resources/assets/templates/models/block/slab_bottom.json new file mode 100644 index 0000000..453fb66 --- /dev/null +++ b/src/main/resources/assets/templates/models/block/slab_bottom.json @@ -0,0 +1,49 @@ +{ + "parent": "minecraft:block/block", + "textures": { + "down": "templates:templates_special/down", + "up": "templates:templates_special/up", + "north": "templates:templates_special/north", + "south": "templates:templates_special/south", + "west": "templates:templates_special/west", + "east": "templates:templates_special/east", + "particle": "minecraft:block/scaffolding_top" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 8, 16], + "faces": { + "down": { + "uv": [0, 0, 16, 16], + "texture": "#down", + "cullface": "down" + }, + "up": { + "uv": [0, 0, 16, 16], + "texture": "#up" + }, + "north": { + "uv": [0, 8, 16, 16], + "texture": "#north", + "cullface": "north" + }, + "south": { + "uv": [0, 8, 16, 16], + "texture": "#south", + "cullface": "south" + }, + "west": { + "uv": [0, 8, 16, 16], + "texture": "#west", + "cullface": "west" + }, + "east": { + "uv": [0, 8, 16, 16], + "texture": "#east", + "cullface": "east" + } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/models/block/slab_top.json b/src/main/resources/assets/templates/models/block/slab_top.json new file mode 100644 index 0000000..0bea2d9 --- /dev/null +++ b/src/main/resources/assets/templates/models/block/slab_top.json @@ -0,0 +1,49 @@ +{ + "parent": "minecraft:block/block", + "textures": { + "down": "templates:templates_special/down", + "up": "templates:templates_special/up", + "north": "templates:templates_special/north", + "south": "templates:templates_special/south", + "west": "templates:templates_special/west", + "east": "templates:templates_special/east", + "particle": "minecraft:block/scaffolding_top" + }, + "elements": [ + { + "from": [0, 8, 0], + "to": [16, 16, 16], + "faces": { + "down": { + "uv": [0, 0, 16, 16], + "texture": "#down" + }, + "up": { + "uv": [0, 0, 16, 16], + "texture": "#up", + "cullface": "up" + }, + "north": { + "uv": [0, 0, 16, 8], + "texture": "#north", + "cullface": "north" + }, + "south": { + "uv": [0, 0, 16, 8], + "texture": "#south", + "cullface": "south" + }, + "west": { + "uv": [0, 0, 16, 8], + "texture": "#west", + "cullface": "west" + }, + "east": { + "uv": [0, 0, 16, 8], + "texture": "#east", + "cullface": "east" + } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/templates/models/block/slope_base.json b/src/main/resources/assets/templates/models/block/slope_base.json index 63cbaf3..7936f14 100644 --- a/src/main/resources/assets/templates/models/block/slope_base.json +++ b/src/main/resources/assets/templates/models/block/slope_base.json @@ -1,8 +1,8 @@ { - "parent": "block/block", + "parent": "minecraft:block/block", "gui_light": "front", "textures": { - "particle": "block/scaffolding_top" + "particle": "minecraft:block/scaffolding_top" }, "display": { "firstperson_righthand": { diff --git a/src/main/resources/assets/templates/textures/templates_special/down.png b/src/main/resources/assets/templates/textures/templates_special/down.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b05aac1fec41b8c002051503ebdc8be55c89cc GIT binary patch literal 536 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 literal 0 HcmV?d00001