Skip to content

Commit

Permalink
Support setting item transforms on model templates
Browse files Browse the repository at this point in the history
  • Loading branch information
ApexModder committed Nov 23, 2024
1 parent c9cc89b commit b54fff3
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@

package net.neoforged.neoforge.common.data.vanilla;

import com.google.common.collect.Maps;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.Map;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.data.models.model.ModelTemplate;
import net.minecraft.data.models.model.TextureSlot;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemDisplayContext;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;

public class ModelTemplateWithCustomData extends ModelTemplate {
@Nullable
Expand All @@ -21,6 +26,7 @@ public class ModelTemplateWithCustomData extends ModelTemplate {
public Boolean ambientOcclusion = null; // BlockModel.DEFAULT_AMBIENT_OCCLUSION
@Nullable
public BlockModel.GuiLight guiLight = null;
public Map<ItemDisplayContext, ItemTransform> transforms = Maps.newHashMap();

public ModelTemplateWithCustomData(ModelTemplate template) {
super(template.model, template.suffix, template.requiredSlots.toArray(TextureSlot[]::new));
Expand All @@ -29,6 +35,7 @@ public ModelTemplateWithCustomData(ModelTemplate template) {
renderType = customData.renderType;
ambientOcclusion = customData.ambientOcclusion;
guiLight = customData.guiLight;
transforms = Maps.newHashMap(customData.transforms);
}
}

Expand All @@ -41,11 +48,17 @@ public JsonObject createBaseTemplate(ResourceLocation modelPath, Map<TextureSlot
}

if (ambientOcclusion != null) {
json.addProperty("ambientocclusion", ambientOcclusion.toString());
json.addProperty("ambientocclusion", ambientOcclusion);
}

if (guiLight != null) {
json.addProperty("gui_light", guiLight.toString());
json.addProperty("gui_light", guiLight.getSerializedName());
}

var transformsJson = toJson(transforms);

if (!transformsJson.isEmpty()) {
json.add("display", transformsJson);
}

return json;
Expand All @@ -55,4 +68,44 @@ public JsonObject createBaseTemplate(ResourceLocation modelPath, Map<TextureSlot
public JsonObject createBaseTemplate(ResourceLocation modelPath, Map<TextureSlot, ResourceLocation> textureMap) {
return createBaseTemplate(modelPath, textureMap, null);
}

public static JsonObject toJson(ItemTransform transform) {
var json = new JsonObject();
var hasRightRotation = !transform.rightRotation.equals(ItemTransform.Deserializer.DEFAULT_ROTATION);

if (!transform.translation.equals(ItemTransform.Deserializer.DEFAULT_TRANSLATION))
json.add("translation", toJson(transform.translation));
if (!transform.rotation.equals(ItemTransform.Deserializer.DEFAULT_ROTATION))
json.add(hasRightRotation ? "left_rotation" : "rotation", toJson(transform.rotation));
if (!transform.scale.equals(ItemTransform.Deserializer.DEFAULT_SCALE))
json.add("scale", toJson(transform.scale));
if (hasRightRotation)
json.add("right_rotation", toJson(transform.rightRotation));

return json;
}

public static JsonObject toJson(Map<ItemDisplayContext, ItemTransform> transforms) {
var json = new JsonObject();

transforms.forEach((context, transform) -> {
if (transform.equals(ItemTransform.NO_TRANSFORM))
return;

var transformJson = toJson(transform);

if (!transformJson.isEmpty())
json.add(context.getSerializedName(), transformJson);
});

return json;
}

public static JsonArray toJson(Vector3f vec) {
var array = new JsonArray();
array.add(vec.x());
array.add(vec.y());
array.add(vec.z());
return array;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import java.util.function.Consumer;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.data.models.model.ModelTemplate;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemDisplayContext;
import net.neoforged.neoforge.common.data.vanilla.ModelTemplateWithCustomData;

public interface IModelTemplateExtension {
Expand All @@ -28,11 +30,15 @@ default ModelTemplate withGuiLight(BlockModel.GuiLight guiLight) {
return withCustomData(customData -> customData.guiLight = guiLight);
}

default ModelTemplate withItemTransform(ItemDisplayContext displayContext, ItemTransform transform) {
return withCustomData(customData -> customData.transforms.put(displayContext, transform));
}

private ModelTemplate self() {
return (ModelTemplate) this;
}

default ModelTemplate withCustomData(Consumer<ModelTemplateWithCustomData> mutator) {
private ModelTemplate withCustomData(Consumer<ModelTemplateWithCustomData> mutator) {
var template = new ModelTemplateWithCustomData(self());
mutator.accept(template);
return template;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
package net.neoforged.neoforge.common.extensions;

import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.data.models.model.TexturedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemDisplayContext;

public interface ITexturedModelExtension {
default TexturedModel withRenderType(String renderType) {
Expand All @@ -26,6 +28,10 @@ default TexturedModel withGuiLight(BlockModel.GuiLight guiLight) {
return new TexturedModel(self().getMapping(), self().getTemplate().withGuiLight(guiLight));
}

default TexturedModel withItemTransform(ItemDisplayContext displayContext, ItemTransform transform) {
return new TexturedModel(self().getMapping(), self().getTemplate().withItemTransform(displayContext, transform));
}

private TexturedModel self() {
return (TexturedModel) this;
}
Expand All @@ -47,6 +53,10 @@ default TexturedModel.Provider withGuiLight(BlockModel.GuiLight guiLight) {
return block -> self().get(block).withGuiLight(guiLight);
}

default TexturedModel.Provider withItemTransform(ItemDisplayContext displayContext, ItemTransform transform) {
return block -> self().get(block).withItemTransform(displayContext, transform);
}

private TexturedModel.Provider self() {
return (TexturedModel.Provider) this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"parent": "minecraft:item/generated",
"ambientocclusion": true,
"display": {
"firstperson_lefthand": {
"rotation": [
0.0,
135.0,
0.0
],
"scale": [
0.4,
0.4,
0.4
],
"translation": [
0.0,
7.0,
4.0
]
},
"firstperson_righthand": {
"rotation": [
0.0,
135.0,
0.0
],
"scale": [
0.4,
0.4,
0.4
],
"translation": [
0.0,
7.0,
4.0
]
},
"fixed": {
"rotation": [
-90.0,
0.0,
0.0
],
"translation": [
0.0,
0.0,
-23.0
]
},
"ground": {
"scale": [
0.25,
0.25,
0.25
],
"translation": [
0.0,
6.0,
4.0
]
},
"gui": {
"rotation": [
30.0,
-135.0,
0.0
],
"scale": [
0.5,
0.5,
0.5
],
"translation": [
0.0,
3.0,
0.0
]
},
"head": {
"translation": [
0.0,
30.0,
4.0
]
},
"thirdperson_lefthand": {
"rotation": [
75.0,
45.0,
0.0
],
"scale": [
0.375,
0.375,
0.375
],
"translation": [
0.0,
3.0,
4.0
]
},
"thirdperson_righthand": {
"rotation": [
75.0,
45.0,
0.0
],
"scale": [
0.375,
0.375,
0.375
],
"translation": [
0.0,
3.0,
4.0
]
}
},
"gui_light": "front",
"render_type": "minecraft:cutout",
"textures": {
"layer0": "minecraft:item/diamond"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@
package net.neoforged.neoforge.debug;

import java.util.function.BiConsumer;
import net.minecraft.client.renderer.block.model.BlockModel;
import net.minecraft.client.renderer.block.model.ItemTransform;
import net.minecraft.core.component.DataComponents;
import net.minecraft.data.models.BlockModelGenerators;
import net.minecraft.data.models.EquipmentModelProvider;
import net.minecraft.data.models.ItemModelGenerators;
import net.minecraft.data.models.ModelProvider;
import net.minecraft.data.models.model.ModelTemplates;
import net.minecraft.data.models.model.TextureMapping;
import net.minecraft.data.models.model.TextureSlot;
import net.minecraft.data.models.model.TexturedModel;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.equipment.EquipmentModel;
import net.minecraft.world.item.equipment.Equippable;
import net.minecraft.world.level.block.Blocks;
Expand All @@ -25,6 +30,7 @@
import net.neoforged.testframework.annotation.ForEachTest;
import net.neoforged.testframework.annotation.TestHolder;
import net.neoforged.testframework.registration.RegistrationHelper;
import org.joml.Vector3f;

@ForEachTest(groups = "vanilla_data_gen")
public interface VanillaDataGenTest {
Expand Down Expand Up @@ -65,6 +71,24 @@ protected void registerModels(BlockModelGenerators blockModels, ItemModelGenerat
// this allows generating your own custom Item model for your BlockItem
// blockModels.skipAutoItemBlock(block.value());
// itemModels.generateFlatItem(blockItem.value(), ModelTemplates.FLAT_HANDHELD_ITEM);

// custom model generation
// output should have all the below custom properties
// parent 'item/generated'
// and have texture slot 'layer0' set to 'item/diamond'
ModelTemplates.FLAT_ITEM
.withItemTransform(ItemDisplayContext.THIRD_PERSON_RIGHT_HAND, new ItemTransform(new Vector3f(75F, 45F, 0F), new Vector3f(0F, 3F, 4F), new Vector3f(.375F)))
.withItemTransform(ItemDisplayContext.THIRD_PERSON_LEFT_HAND, new ItemTransform(new Vector3f(75F, 45F, 0F), new Vector3f(0F, 3F, 4F), new Vector3f(.375F)))
.withItemTransform(ItemDisplayContext.FIRST_PERSON_RIGHT_HAND, new ItemTransform(new Vector3f(0F, 135F, 0F), new Vector3f(0F, 7F, 4F), new Vector3f(.4F)))
.withItemTransform(ItemDisplayContext.FIRST_PERSON_LEFT_HAND, new ItemTransform(new Vector3f(0F, 135F, 0F), new Vector3f(0F, 7F, 4F), new Vector3f(.4F)))
.withItemTransform(ItemDisplayContext.HEAD, new ItemTransform(new Vector3f(0F), new Vector3f(0F, 30F, 4F), new Vector3f(1F)))
.withItemTransform(ItemDisplayContext.GROUND, new ItemTransform(new Vector3f(0F), new Vector3f(0F, 6F, 4F), new Vector3f(.25F)))
.withItemTransform(ItemDisplayContext.FIXED, new ItemTransform(new Vector3f(-90F, 0F, 0F), new Vector3f(0F, 0F, -23F), new Vector3f(1F)))
.withItemTransform(ItemDisplayContext.GUI, new ItemTransform(new Vector3f(30F, -135F, 0F), new Vector3f(0F, 3F, 0F), new Vector3f(.5F)))
.withRenderType("cutout")
.withAmbientOcclusion(true)
.withGuiLight(BlockModel.GuiLight.FRONT)
.create(itemModels.modLocation("custom_model_generation"), TextureMapping.layer0(Items.DIAMOND), itemModels.output, fileHelper);
}
});

Expand Down

0 comments on commit b54fff3

Please sign in to comment.