Add a model loader that lets mods specify different models for different perspectives.
Allow custom models to reference vanilla item models as child models.
This commit is contained in:
parent
af9bb9641b
commit
5f1a7326c7
4 changed files with 217 additions and 1 deletions
|
@ -56,6 +56,7 @@ public class ModelLoaderRegistry
|
||||||
{
|
{
|
||||||
public static final String WHITE_TEXTURE = "forge:white";
|
public static final String WHITE_TEXTURE = "forge:white";
|
||||||
|
|
||||||
|
private static final ItemModelGenerator ITEM_MODEL_GENERATOR = new ItemModelGenerator();
|
||||||
private static final Map<ResourceLocation, IModelLoader<?>> loaders = Maps.newHashMap();
|
private static final Map<ResourceLocation, IModelLoader<?>> loaders = Maps.newHashMap();
|
||||||
private static volatile boolean registryFrozen = false;
|
private static volatile boolean registryFrozen = false;
|
||||||
|
|
||||||
|
@ -68,6 +69,7 @@ public class ModelLoaderRegistry
|
||||||
registerLoader(new ResourceLocation("forge","composite"), CompositeModel.Loader.INSTANCE);
|
registerLoader(new ResourceLocation("forge","composite"), CompositeModel.Loader.INSTANCE);
|
||||||
registerLoader(new ResourceLocation("forge","multi-layer"), MultiLayerModel.Loader.INSTANCE);
|
registerLoader(new ResourceLocation("forge","multi-layer"), MultiLayerModel.Loader.INSTANCE);
|
||||||
registerLoader(new ResourceLocation("forge","item-layers"), ItemLayerModel.Loader.INSTANCE);
|
registerLoader(new ResourceLocation("forge","item-layers"), ItemLayerModel.Loader.INSTANCE);
|
||||||
|
registerLoader(new ResourceLocation("forge", "separate-perspective"), SeparatePerspectiveModel.Loader.INSTANCE);
|
||||||
|
|
||||||
// TODO: Implement as new model loaders
|
// TODO: Implement as new model loaders
|
||||||
//registerLoader(new ResourceLocation("forge:b3d"), new ModelLoaderAdapter(B3DLoader.INSTANCE));
|
//registerLoader(new ResourceLocation("forge:b3d"), new ModelLoaderAdapter(B3DLoader.INSTANCE));
|
||||||
|
@ -255,7 +257,16 @@ public class ModelLoaderRegistry
|
||||||
if (customModel != null)
|
if (customModel != null)
|
||||||
model = customModel.bake(blockModel.customData, modelBakery, spriteGetter, modelTransform, blockModel.getOverrides(modelBakery, otherModel, spriteGetter), modelLocation);
|
model = customModel.bake(blockModel.customData, modelBakery, spriteGetter, modelTransform, blockModel.getOverrides(modelBakery, otherModel, spriteGetter), modelLocation);
|
||||||
else
|
else
|
||||||
model = blockModel.bakeVanilla(modelBakery, otherModel, spriteGetter, modelTransform, modelLocation, guiLight3d);
|
{
|
||||||
|
// handle vanilla item models here, since vanilla has a shortcut for them
|
||||||
|
if (blockModel.getRootModel() == ModelBakery.MODEL_GENERATED) {
|
||||||
|
model = ITEM_MODEL_GENERATOR.makeItemModel(spriteGetter, blockModel).bakeModel(modelBakery, blockModel, spriteGetter, modelTransform, modelLocation, guiLight3d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model = blockModel.bakeVanilla(modelBakery, otherModel, spriteGetter, modelTransform, modelLocation, guiLight3d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (customModelState != null && !model.doesHandlePerspectives())
|
if (customModelState != null && !model.doesHandlePerspectives())
|
||||||
model = new PerspectiveMapWrapper(model, customModelState);
|
model = new PerspectiveMapWrapper(model, customModelState);
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.renderer.model.*;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.JSONUtils;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class SeparatePerspectiveModel implements IModelGeometry<SeparatePerspectiveModel>
|
||||||
|
{
|
||||||
|
private final BlockModel baseModel;
|
||||||
|
private final ImmutableMap<ItemCameraTransforms.TransformType, BlockModel> perspectives;
|
||||||
|
|
||||||
|
public SeparatePerspectiveModel(BlockModel baseModel, ImmutableMap<ItemCameraTransforms.TransformType, BlockModel> perspectives)
|
||||||
|
{
|
||||||
|
this.baseModel = baseModel;
|
||||||
|
this.perspectives = perspectives;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
|
||||||
|
{
|
||||||
|
return new BakedModel(
|
||||||
|
owner.useSmoothLighting(), owner.isShadedInGui(), owner.isSideLit(),
|
||||||
|
spriteGetter.apply(owner.resolveTexture("particle")), overrides,
|
||||||
|
baseModel.bakeModel(bakery, baseModel, spriteGetter, modelTransform, modelLocation, owner.isSideLit()),
|
||||||
|
ImmutableMap.copyOf(Maps.transformValues(perspectives, value -> {
|
||||||
|
return value.bakeModel(bakery, value, spriteGetter, modelTransform, modelLocation, owner.isSideLit());
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<RenderMaterial> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||||
|
{
|
||||||
|
Set<RenderMaterial> textures = Sets.newHashSet();
|
||||||
|
textures.addAll(baseModel.getTextures(modelGetter, missingTextureErrors));
|
||||||
|
for(BlockModel model : perspectives.values())
|
||||||
|
textures.addAll(model.getTextures(modelGetter, missingTextureErrors));
|
||||||
|
return textures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BakedModel implements IBakedModel
|
||||||
|
{
|
||||||
|
private final boolean isAmbientOcclusion;
|
||||||
|
private final boolean isGui3d;
|
||||||
|
private final boolean isSideLit;
|
||||||
|
private final TextureAtlasSprite particle;
|
||||||
|
private final ItemOverrideList overrides;
|
||||||
|
private final IBakedModel baseModel;
|
||||||
|
private final ImmutableMap<ItemCameraTransforms.TransformType, IBakedModel> perspectives;
|
||||||
|
|
||||||
|
public BakedModel(boolean isAmbientOcclusion, boolean isGui3d, boolean isSideLit, TextureAtlasSprite particle, ItemOverrideList overrides, IBakedModel baseModel, ImmutableMap<ItemCameraTransforms.TransformType, IBakedModel> perspectives)
|
||||||
|
{
|
||||||
|
this.isAmbientOcclusion = isAmbientOcclusion;
|
||||||
|
this.isGui3d = isGui3d;
|
||||||
|
this.isSideLit = isSideLit;
|
||||||
|
this.particle = particle;
|
||||||
|
this.overrides = overrides;
|
||||||
|
this.baseModel = baseModel;
|
||||||
|
this.perspectives = perspectives;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand)
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAmbientOcclusion()
|
||||||
|
{
|
||||||
|
return isAmbientOcclusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGui3d()
|
||||||
|
{
|
||||||
|
return isGui3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean func_230044_c_()
|
||||||
|
{
|
||||||
|
return isSideLit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBuiltInRenderer()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextureAtlasSprite getParticleTexture()
|
||||||
|
{
|
||||||
|
return particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemOverrideList getOverrides()
|
||||||
|
{
|
||||||
|
return overrides;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doesHandlePerspectives()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemCameraTransforms getItemCameraTransforms()
|
||||||
|
{
|
||||||
|
return ItemCameraTransforms.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat)
|
||||||
|
{
|
||||||
|
if (perspectives.containsKey(cameraTransformType))
|
||||||
|
{
|
||||||
|
IBakedModel p = perspectives.get(cameraTransformType);
|
||||||
|
return p.handlePerspective(cameraTransformType, mat);
|
||||||
|
}
|
||||||
|
return baseModel.handlePerspective(cameraTransformType, mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Loader implements IModelLoader<SeparatePerspectiveModel>
|
||||||
|
{
|
||||||
|
public static final Loader INSTANCE = new Loader();
|
||||||
|
|
||||||
|
private static final ImmutableMap<String, ItemCameraTransforms.TransformType> PERSPECTIVES = ImmutableMap.<String, ItemCameraTransforms.TransformType>builder()
|
||||||
|
.put("none", ItemCameraTransforms.TransformType.NONE)
|
||||||
|
.put("third_person_left_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND)
|
||||||
|
.put("third_person_right_hand", ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND)
|
||||||
|
.put("first_person_left_hand", ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND)
|
||||||
|
.put("first_person_right_hand", ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND)
|
||||||
|
.put("head", ItemCameraTransforms.TransformType.HEAD)
|
||||||
|
.put("gui", ItemCameraTransforms.TransformType.GUI)
|
||||||
|
.put("ground", ItemCameraTransforms.TransformType.GROUND)
|
||||||
|
.put("fixed", ItemCameraTransforms.TransformType.FIXED)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResourceManagerReload(IResourceManager resourceManager)
|
||||||
|
{
|
||||||
|
// Not used
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SeparatePerspectiveModel read(JsonDeserializationContext deserializationContext, JsonObject modelContents)
|
||||||
|
{
|
||||||
|
BlockModel baseModel = deserializationContext.deserialize(JSONUtils.getJsonObject(modelContents, "base"), BlockModel.class);
|
||||||
|
|
||||||
|
JsonObject perspectiveData = JSONUtils.getJsonObject(modelContents, "perspectives");
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ItemCameraTransforms.TransformType, BlockModel> perspectives = ImmutableMap.builder();
|
||||||
|
for(Map.Entry<String, ItemCameraTransforms.TransformType> perspective : PERSPECTIVES.entrySet())
|
||||||
|
{
|
||||||
|
if (perspectiveData.has(perspective.getKey()))
|
||||||
|
{
|
||||||
|
BlockModel perspectiveModel = deserializationContext.deserialize(JSONUtils.getJsonObject(perspectiveData, perspective.getKey()), BlockModel.class);
|
||||||
|
perspectives.put(perspective.getValue(), perspectiveModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SeparatePerspectiveModel(baseModel, perspectives.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -123,6 +123,10 @@ public class NewModelLoaderTest
|
||||||
new Item(new Item.Properties().group(ItemGroup.MISC))
|
new Item(new Item.Properties().group(ItemGroup.MISC))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static RegistryObject<Item> separate_perspective = ITEMS.register("separate_perspective", () ->
|
||||||
|
new Item(new Item.Properties().group(ItemGroup.MISC))
|
||||||
|
);
|
||||||
|
|
||||||
public NewModelLoaderTest()
|
public NewModelLoaderTest()
|
||||||
{
|
{
|
||||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"parent":"forge:item/default",
|
||||||
|
"loader":"forge:separate-perspective",
|
||||||
|
"base": {
|
||||||
|
"parent": "minecraft:item/coal"
|
||||||
|
},
|
||||||
|
"perspectives": {
|
||||||
|
"gui": {
|
||||||
|
"parent": "minecraft:item/snowball"
|
||||||
|
},
|
||||||
|
"first_person_left_hand": {
|
||||||
|
"parent": "minecraft:item/bone"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue