Skip to content

Commit

Permalink
Add support for running IModel.retexture() on models from blockstates (
Browse files Browse the repository at this point in the history
  • Loading branch information
KnightMiner authored and LexManos committed Aug 9, 2017
1 parent d14a872 commit 82d735e
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 3 deletions.
62 changes: 59 additions & 3 deletions src/main/java/net/minecraftforge/client/model/ModelLoader.java
Expand Up @@ -701,14 +701,17 @@ public IModel uvlock(boolean value)
private static final class WeightedRandomModel implements IModel
{
private final List<Variant> variants;
private final List<ResourceLocation> locations = new ArrayList<>();
private final Set<ResourceLocation> textures = Sets.newHashSet();
private final List<IModel> models = new ArrayList<>();
private final List<ResourceLocation> locations;
private final Set<ResourceLocation> textures;
private final List<IModel> models;
private final IModelState defaultState;

public WeightedRandomModel(ResourceLocation parent, VariantList variants) throws Exception
{
this.variants = variants.getVariantList();
this.locations = new ArrayList<>();
this.textures = Sets.newHashSet();
this.models = new ArrayList<>();
ImmutableList.Builder<Pair<IModel, IModelState>> builder = ImmutableList.builder();
for (Variant v : this.variants)
{
Expand Down Expand Up @@ -754,6 +757,15 @@ public WeightedRandomModel(ResourceLocation parent, VariantList variants) throws
defaultState = new MultiModelState(builder.build());
}

private WeightedRandomModel(List<Variant> variants, List<ResourceLocation> locations, Set<ResourceLocation> textures, List<IModel> models, IModelState defaultState)
{
this.variants = variants;
this.locations = locations;
this.textures = textures;
this.models = models;
this.defaultState = defaultState;
}

@Override
public Collection<ResourceLocation> getDependencies()
{
Expand Down Expand Up @@ -792,6 +804,28 @@ public IModelState getDefaultState()
{
return defaultState;
}

@Override
public WeightedRandomModel retexture(ImmutableMap<String, String> textures)
{
if (textures.isEmpty())
return this;

// rebuild the texture list taking into account new textures
Set<ResourceLocation> modelTextures = Sets.newHashSet();
// also recreate the MultiModelState so IModelState data is properly applied to the retextured model
ImmutableList.Builder<Pair<IModel, IModelState>> builder = ImmutableList.builder();
List<IModel> retexturedModels = Lists.newArrayList();
for(int i = 0; i < this.variants.size(); i++)
{
IModel retextured = this.models.get(i).retexture(textures);
modelTextures.addAll(retextured.getTextures());
retexturedModels.add(retextured);
builder.add(Pair.of(retextured, this.variants.get(i).getState()));
}

return new WeightedRandomModel(this.variants, this.locations, modelTextures, retexturedModels, new MultiModelState(builder.build()));
}
}

protected IModel getMissingModel()
Expand Down Expand Up @@ -1243,6 +1277,13 @@ public MultipartModel(ResourceLocation location, Multipart multipart) throws Exc
partModels = builder.build();
}

private MultipartModel(ResourceLocation location, Multipart multipart, ImmutableMap<Selector, IModel> partModels)
{
this.location = location;
this.multipart = multipart;
this.partModels = partModels;
}

// FIXME: represent selectors as dependencies?
// FIXME
@Override
Expand All @@ -1258,5 +1299,20 @@ public IBakedModel bake(IModelState state, VertexFormat format, Function<Resourc
IBakedModel bakedModel = builder.makeMultipartModel();
return bakedModel;
}

@Override
public IModel retexture(ImmutableMap<String, String> textures)
{
if (textures.isEmpty())
return this;

ImmutableMap.Builder<Selector, IModel> builder = ImmutableMap.builder();
for (Entry<Selector, IModel> partModel : this.partModels.entrySet())
{
builder.put(partModel.getKey(), partModel.getValue().retexture(textures));
}

return new MultipartModel(location, multipart, builder.build());
}
}
}
@@ -0,0 +1,61 @@
package net.minecraftforge.debug;

import java.util.function.Function;

import com.google.common.collect.ImmutableMap;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;

@Mod(modid = BlockstateRetextureTest.MODID, name = "BlockstateRetextureTest", version = BlockstateRetextureTest.VERSION, acceptableRemoteVersions = "*")
public class BlockstateRetextureTest
{
public static final String MODID = "forge_blockstate_retexture_test";
public static final String VERSION = "1.0";
static final boolean ENABLED = false;

private static ResourceLocation fenceName = new ResourceLocation("minecraft", "fence");
private static ModelResourceLocation fenceLocation = new ModelResourceLocation(fenceName, "east=true,north=false,south=false,west=true");
private static ResourceLocation stoneName = new ResourceLocation("minecraft", "stone");
private static ModelResourceLocation stoneLocation = new ModelResourceLocation(stoneName, "normal");

private static Function<ResourceLocation, TextureAtlasSprite> textureGetter = location ->
{
assert location != null;
return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString());
};

@Mod.EventBusSubscriber(modid = MODID, value = Side.CLIENT)
public static class ClientEvents
{
@SubscribeEvent
public static void onModelBakeEvent(ModelBakeEvent event)
{
if (!ENABLED)
{
return;
}

IModel fence = ModelLoaderRegistry.getModelOrLogError(fenceLocation, "Error loading fence model");
IModel stone = ModelLoaderRegistry.getModelOrLogError(stoneLocation, "Error loading planks model");
IModel retexturedFence = fence.retexture(ImmutableMap.of("texture", "blocks/log_oak"));
IModel retexturedStone = stone.retexture(ImmutableMap.of("all", "blocks/diamond_block"));

IBakedModel fenceResult = retexturedFence.bake(fence.getDefaultState(), DefaultVertexFormats.BLOCK, textureGetter);
IBakedModel stoneResult = retexturedStone.bake(stone.getDefaultState(), DefaultVertexFormats.BLOCK, textureGetter);

event.getModelRegistry().putObject(fenceLocation, fenceResult);
event.getModelRegistry().putObject(stoneLocation, stoneResult);
}
}
}

0 comments on commit 82d735e

Please sign in to comment.