From 4449cd95ff2eb33d1d5dcd8c645e86da1749728f Mon Sep 17 00:00:00 2001 From: Eclipse Date: Sun, 6 Jul 2025 15:51:11 +0000 Subject: [PATCH] Use geometry renderer to render 3D GUI icons, some TODOs --- .../mapping/BedrockItemMapper.java | 39 +++++++++++++------ .../mapping/animation/AnimationMapper.java | 3 +- .../mapping/geometry/GeometryRenderer.java | 4 ++ .../packgenerator/pack/BedrockItem.java | 2 +- .../packgenerator/pack/BedrockPack.java | 6 ++- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/geysermc/packgenerator/mapping/BedrockItemMapper.java b/src/main/java/org/geysermc/packgenerator/mapping/BedrockItemMapper.java index 47e02f7..6a48d68 100644 --- a/src/main/java/org/geysermc/packgenerator/mapping/BedrockItemMapper.java +++ b/src/main/java/org/geysermc/packgenerator/mapping/BedrockItemMapper.java @@ -2,7 +2,6 @@ package org.geysermc.packgenerator.mapping; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.model.SimpleUnbakedGeometry; import net.minecraft.client.renderer.item.BlockModelWrapper; import net.minecraft.client.renderer.item.ConditionalItemModel; import net.minecraft.client.renderer.item.ItemModel; @@ -20,11 +19,13 @@ import net.minecraft.client.renderer.item.properties.select.TrimMaterialProperty import net.minecraft.client.resources.model.Material; import net.minecraft.client.resources.model.ResolvedModel; import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ProblemReporter; import net.minecraft.world.item.CrossbowItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; import net.minecraft.world.item.equipment.trim.TrimMaterial; import net.minecraft.world.level.Level; import org.geysermc.packgenerator.accessor.BlockModelWrapperLocationAccessor; @@ -35,6 +36,7 @@ import org.geysermc.packgenerator.mapping.animation.BedrockAnimationContext; import org.geysermc.packgenerator.mapping.attachable.AttachableMapper; import org.geysermc.packgenerator.mapping.geometry.BedrockGeometryContext; import org.geysermc.packgenerator.mapping.geometry.GeometryMapper; +import org.geysermc.packgenerator.mapping.geometry.GeometryRenderer; import org.geysermc.packgenerator.mapping.geyser.GeyserMappings; import org.geysermc.packgenerator.mapping.geyser.GeyserSingleDefinition; import org.geysermc.packgenerator.mapping.geyser.predicate.GeyserConditionPredicate; @@ -43,8 +45,9 @@ import org.geysermc.packgenerator.mapping.geyser.predicate.GeyserPredicate; import org.geysermc.packgenerator.mixin.ConditionalItemModelAccessor; import org.geysermc.packgenerator.mixin.SelectItemModelAccessor; import org.geysermc.packgenerator.pack.BedrockItem; -import org.geysermc.packgenerator.pack.geometry.BedrockGeometry; +import org.geysermc.packgenerator.pack.BedrockTextures; +import java.nio.file.Path; import java.util.List; import java.util.Optional; import java.util.function.Consumer; @@ -57,19 +60,19 @@ public class BedrockItemMapper { .toList(); public static void tryMapStack(ItemStack stack, ResourceLocation model, ProblemReporter reporter, - GeyserMappings mappings, BedrockItemConsumer itemConsumer, Consumer additionalTextureConsumer) { + GeyserMappings mappings, Path packPath, BedrockItemConsumer itemConsumer, Consumer additionalTextureConsumer) { String displayName = stack.getHoverName().getString(); int protectionValue = 0; // TODO check the attributes mapItem(model, displayName, protectionValue, stack.getComponentsPatch(), reporter, - mapping -> mappings.map(stack.getItemHolder(), mapping), itemConsumer, additionalTextureConsumer); + mapping -> mappings.map(stack.getItemHolder(), mapping), packPath, itemConsumer, additionalTextureConsumer); } public static void mapItem(ResourceLocation modelLocation, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter, - Consumer mappingConsumer, BedrockItemConsumer itemConsumer, Consumer additionalTextureConsumer) { + Consumer mappingConsumer, Path packPath, BedrockItemConsumer itemConsumer, Consumer additionalTextureConsumer) { ItemModel model = Minecraft.getInstance().getModelManager().getItemModel(modelLocation); MappingContext context = new MappingContext(List.of(), modelLocation, displayName, protectionValue, componentPatch, - reporter.forChild(() -> "client item definition " + modelLocation + " "), mappingConsumer, itemConsumer, additionalTextureConsumer); + reporter.forChild(() -> "client item definition " + modelLocation + " "), mappingConsumer, itemConsumer, packPath, additionalTextureConsumer); mapItem(model, context); } @@ -157,15 +160,17 @@ public class BedrockItemMapper { } private record MappingContext(List predicateStack, ResourceLocation model, String displayName, int protectionValue, DataComponentPatch componentPatch, ProblemReporter reporter, - Consumer mappingConsumer, BedrockItemConsumer itemConsumer, Consumer additionalTextureConsumer) { + Consumer mappingConsumer, BedrockItemConsumer itemConsumer, Path packPath, + Consumer additionalTextureConsumer) { public MappingContext with(GeyserPredicate predicate, String childName) { return new MappingContext(Stream.concat(predicateStack.stream(), Stream.of(predicate)).toList(), model, displayName, protectionValue, componentPatch, - reporter.forChild(() -> childName), mappingConsumer, itemConsumer, additionalTextureConsumer); + reporter.forChild(() -> childName), mappingConsumer, itemConsumer, packPath, additionalTextureConsumer); } public MappingContext child(String childName) { - return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName), mappingConsumer, itemConsumer, additionalTextureConsumer); + return new MappingContext(predicateStack, model, displayName, protectionValue, componentPatch, reporter.forChild(() -> childName), + mappingConsumer, itemConsumer, packPath, additionalTextureConsumer); } public void create(ResourceLocation bedrockIdentifier, ResourceLocation texture, boolean displayHandheld, @@ -182,10 +187,22 @@ public class BedrockItemMapper { // TODO Should probably get a better way to get geometry texture String safeIdentifier = definition.textureName(); String bone = "bone"; - Optional bedrockGeometry = customModel.map(model -> GeometryMapper.mapGeometry(safeIdentifier, bone, model, texture)); + ResourceLocation geometryTexture = texture; + Optional bedrockGeometry = customModel.map(model -> GeometryMapper.mapGeometry(safeIdentifier, bone, model, geometryTexture)); Optional bedrockAnimation = customModel.map(model -> AnimationMapper.mapAnimation(safeIdentifier, bone, model.getTopTransforms())); - itemConsumer.accept(new BedrockItem(bedrockIdentifier, definition.textureName(), texture, + boolean exportTexture = true; + if (customModel.isPresent()) { + ItemStack fakeItem = new ItemStack(Items.FLINT); + fakeItem.set(DataComponents.ITEM_MODEL, model); + + texture = texture.withPath(path -> path + "_icon"); + GeometryRenderer.render(fakeItem, packPath.resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png")); + exportTexture = false; + additionalTextureConsumer.accept(geometryTexture); + } + + itemConsumer.accept(new BedrockItem(bedrockIdentifier, definition.textureName(), texture, exportTexture, AttachableMapper.mapItem(componentPatch, bedrockIdentifier, bedrockGeometry, bedrockAnimation, additionalTextureConsumer), bedrockGeometry.map(BedrockGeometryContext::geometry), bedrockAnimation.map(BedrockAnimationContext::animation))); } diff --git a/src/main/java/org/geysermc/packgenerator/mapping/animation/AnimationMapper.java b/src/main/java/org/geysermc/packgenerator/mapping/animation/AnimationMapper.java index 1c14d8c..ab9df14 100644 --- a/src/main/java/org/geysermc/packgenerator/mapping/animation/AnimationMapper.java +++ b/src/main/java/org/geysermc/packgenerator/mapping/animation/AnimationMapper.java @@ -6,6 +6,7 @@ import org.geysermc.packgenerator.pack.animation.BedrockAnimation; import org.joml.Vector3f; import org.joml.Vector3fc; +// TODO these offset values are completely wrong, I think public class AnimationMapper { // These aren't perfect... but I spent over 1.5 hours trying to get these. It's good enough for me. private static final Vector3fc FIRST_PERSON_POSITION_OFFSET = new Vector3f(-7.0F, 22.5F, -7.0F); @@ -21,7 +22,7 @@ public class AnimationMapper { Vector3f firstPersonRotation = FIRST_PERSON_ROTATION_OFFSET.add(firstPerson.rotation(), new Vector3f()); Vector3f firstPersonScale = new Vector3f(firstPerson.scale()); - ItemTransform thirdPerson = transforms.thirdPersonLeftHand(); + ItemTransform thirdPerson = transforms.thirdPersonRightHand(); Vector3f thirdPersonPosition = THIRD_PERSON_POSITION_OFFSET.add(thirdPerson.translation(), new Vector3f()); Vector3f thirdPersonRotation = THIRD_PERSON_ROTATION_OFFSET.add(-thirdPerson.rotation().x(), thirdPerson.rotation().y(), thirdPerson.rotation().z(), new Vector3f()); Vector3f thirdPersonScale = new Vector3f(thirdPerson.scale()); diff --git a/src/main/java/org/geysermc/packgenerator/mapping/geometry/GeometryRenderer.java b/src/main/java/org/geysermc/packgenerator/mapping/geometry/GeometryRenderer.java index 087ff89..3cf598a 100644 --- a/src/main/java/org/geysermc/packgenerator/mapping/geometry/GeometryRenderer.java +++ b/src/main/java/org/geysermc/packgenerator/mapping/geometry/GeometryRenderer.java @@ -14,6 +14,7 @@ import net.minecraft.client.gui.render.state.pip.OversizedItemRenderState; import net.minecraft.client.renderer.item.TrackingItemStackRenderState; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; +import org.geysermc.packgenerator.CodecUtil; import org.geysermc.packgenerator.mixin.PictureInPictureRendererAccessor; import org.geysermc.packgenerator.render.PictureInPictureCopyRenderer; import org.joml.Matrix3x2fStack; @@ -22,6 +23,8 @@ import java.io.IOException; import java.nio.file.Path; import java.util.Objects; +// TODO maybe just use this even for normal 2D items, not sure, could be useful for composite models and stuff +// TODO output in a size bedrock likes public class GeometryRenderer { public static void render(ItemStack stack, Path path) { @@ -62,6 +65,7 @@ public class GeometryRenderer { } } + CodecUtil.ensureDirectoryExists(path.getParent()); nativeImage.writeToFile(path); } catch (IOException var19) { // TODO diff --git a/src/main/java/org/geysermc/packgenerator/pack/BedrockItem.java b/src/main/java/org/geysermc/packgenerator/pack/BedrockItem.java index 7bf6c41..112b2b4 100644 --- a/src/main/java/org/geysermc/packgenerator/pack/BedrockItem.java +++ b/src/main/java/org/geysermc/packgenerator/pack/BedrockItem.java @@ -10,7 +10,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -public record BedrockItem(ResourceLocation identifier, String textureName, ResourceLocation texture, Optional attachable, +public record BedrockItem(ResourceLocation identifier, String textureName, ResourceLocation texture, boolean exportTexture, Optional attachable, Optional geometry, Optional animation) { public void save(Path attachableDirectory, Path geometryDirectory, Path animationDirectory) throws IOException { diff --git a/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java b/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java index 84399b8..5bf76d6 100644 --- a/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java +++ b/src/main/java/org/geysermc/packgenerator/pack/BedrockPack.java @@ -101,9 +101,11 @@ public class BedrockPack { } }; - BedrockItemMapper.tryMapStack(stack, model, mapReporter, mappings, bedrockItem -> { + BedrockItemMapper.tryMapStack(stack, model, mapReporter, mappings, packPath, bedrockItem -> { itemTextures.withItemTexture(bedrockItem); - texturesToExport.add(bedrockItem.texture()); + if (bedrockItem.exportTexture()) { + texturesToExport.add(bedrockItem.texture()); + } bedrockItems.add(bedrockItem); }, texturesToExport::add); return Optional.of(problems.get());