Initial support for model visibility system. Implemented it for OBJ, B3D and normal vanilla models; fixed NPE accessing parent state in B3DModel. Fixes #2801.

This commit is contained in:
RainWarrior 2016-05-30 01:20:43 +03:00
parent 4008983a5d
commit ce481da1d1
6 changed files with 228 additions and 170 deletions

View File

@ -63,6 +63,7 @@ import net.minecraftforge.client.model.animation.ModelBlockAnimation;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.model.IModelPart;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.Models;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.model.animation.IClip;
import net.minecraftforge.common.property.IExtendedBlockState;
@ -526,6 +527,10 @@ public final class ModelLoader extends ModelBakery
SimpleBakedModel.Builder builder = (new SimpleBakedModel.Builder(model, model.createOverrides())).setTexture(particle);
for(int i = 0; i < model.getElements().size(); i++)
{
if(modelState.apply(Optional.of(Models.getHiddenModelPart(ImmutableList.of(Integer.toString(i))))).isPresent())
{
continue;
}
BlockPart part = model.getElements().get(i);
TRSRTransformation transformation = baseState;
if(newTransforms.get(i) != null)

View File

@ -47,6 +47,7 @@ import net.minecraftforge.client.model.b3d.B3DModel.Vertex;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.model.IModelPart;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.Models;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.model.animation.IClip;
import net.minecraftforge.common.model.animation.IJoint;
@ -209,7 +210,14 @@ public enum B3DLoader implements ICustomModelLoader
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
// TODO make more use of Optional
if(!part.isPresent()) return parent.apply(part);
if(!part.isPresent())
{
if(parent != null)
{
return parent.apply(part);
}
return Optional.absent();
}
if(!(part.get() instanceof NodeJoint))
{
return Optional.absent();
@ -364,6 +372,10 @@ public enum B3DLoader implements ICustomModelLoader
}
}
/**
* @deprecated use AnimationProperty.
*/
@Deprecated
public static enum B3DFrameProperty implements IUnlistedProperty<B3DState>
{
INSTANCE;
@ -679,26 +691,30 @@ public enum B3DLoader implements ICustomModelLoader
if(quads == null)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
generateQuads(builder, node, this.state);
generateQuads(builder, node, this.state, ImmutableList.<String>of());
quads = builder.build();
}
// TODO: caching?
if(this.state != modelState)
{
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
generateQuads(builder, node, modelState);
generateQuads(builder, node, modelState, ImmutableList.<String>of());
return builder.build();
}
return quads;
}
private void generateQuads(ImmutableList.Builder<BakedQuad> builder, Node<?> node, final IModelState state)
private void generateQuads(ImmutableList.Builder<BakedQuad> builder, Node<?> node, final IModelState state, ImmutableList<String> path)
{
ImmutableList.Builder<String> pathBuilder = ImmutableList.builder();
pathBuilder.addAll(path);
pathBuilder.add(node.getName());
ImmutableList<String> newPath = pathBuilder.build();
for(Node<?> child : node.getNodes().values())
{
generateQuads(builder, child, state);
generateQuads(builder, child, state, newPath);
}
if(node.getKind() instanceof Mesh && meshes.contains(node.getName()))
if(node.getKind() instanceof Mesh && meshes.contains(node.getName()) && !state.apply(Optional.of(Models.getHiddenModelPart(newPath))).isPresent())
{
Mesh mesh = (Mesh)node.getKind();
Collection<Face> faces = mesh.bake(new Function<Node<?>, Matrix4f>()

View File

@ -32,16 +32,15 @@ import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelCustomData;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.client.model.IRetexturableModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.*;
import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad;
import net.minecraftforge.common.model.IModelPart;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.Models;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.lang3.tuple.Pair;
@ -1036,6 +1035,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
}
@Deprecated
public static class Group implements IModelPart
{
public static final String DEFAULT_NAME = "OBJModel.Default.Element.Name";
@ -1092,6 +1092,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
}
@Deprecated
public static class OBJState implements IModelState
{
protected Map<String, Boolean> visibilityMap = Maps.newHashMap();
@ -1230,6 +1231,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
}
}
@Deprecated
public enum OBJProperty implements IUnlistedProperty<OBJState>
{
INSTANCE;
@ -1262,7 +1264,7 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
private final OBJModel model;
private IModelState state;
private final VertexFormat format;
private Set<BakedQuad> quads;
private ImmutableList<BakedQuad> quads;
private ImmutableMap<String, TextureAtlasSprite> textures;
private TextureAtlasSprite sprite = ModelLoader.White.INSTANCE;
@ -1277,98 +1279,122 @@ public class OBJModel implements IRetexturableModel, IModelCustomData
public void scheduleRebake()
{
this.quads = null;
}
// FIXME: merge with getQuads
@Override
public List<BakedQuad> getQuads(IBlockState blockState, EnumFacing side, long rand)
{
if(side != null) return ImmutableList.of();
if (side != null) return ImmutableList.of();
if (quads == null)
{
quads = Collections.synchronizedSet(new LinkedHashSet<BakedQuad>());
Set<Face> faces = Collections.synchronizedSet(new LinkedHashSet<Face>());
Optional<TRSRTransformation> transform = Optional.absent();
for (Group g : this.model.getMatLib().getGroups().values())
quads = buildQuads(this.state);
}
if (blockState instanceof IExtendedBlockState)
{
IExtendedBlockState exState = (IExtendedBlockState) blockState;
if (exState.getUnlistedNames().contains(Properties.AnimationProperty))
{
// g.minUVBounds = this.model.getMatLib().minUVBounds;
// g.maxUVBounds = this.model.getMatLib().maxUVBounds;
// FMLLog.info("Group: %s u: [%f, %f] v: [%f, %f]", g.name, g.minUVBounds[0], g.maxUVBounds[0], g.minUVBounds[1], g.maxUVBounds[1]);
if (this.state instanceof OBJState)
IModelState newState = exState.getValue(Properties.AnimationProperty);
if (newState != null)
{
OBJState state = (OBJState) this.state;
if (state.parent != null)
newState = new ModelStateComposition(this.state, newState);
return buildQuads(newState);
}
}
}
return quads;
}
private ImmutableList<BakedQuad> buildQuads(IModelState modelState)
{
List<BakedQuad> quads = Lists.newArrayList();
Collections.synchronizedSet(new LinkedHashSet<BakedQuad>());
Set<Face> faces = Collections.synchronizedSet(new LinkedHashSet<Face>());
Optional<TRSRTransformation> transform = Optional.absent();
for (Group g : this.model.getMatLib().getGroups().values())
{
// g.minUVBounds = this.model.getMatLib().minUVBounds;
// g.maxUVBounds = this.model.getMatLib().maxUVBounds;
// FMLLog.info("Group: %s u: [%f, %f] v: [%f, %f]", g.name, g.minUVBounds[0], g.maxUVBounds[0], g.minUVBounds[1], g.maxUVBounds[1]);
if(modelState.apply(Optional.of(Models.getHiddenModelPart(ImmutableList.of(g.getName())))).isPresent())
{
continue;
}
if (modelState instanceof OBJState)
{
OBJState state = (OBJState) modelState;
if (state.parent != null)
{
transform = state.parent.apply(Optional.<IModelPart>absent());
}
//TODO: can this be replaced by updateStateVisibilityMap(OBJState)?
if (state.getGroupNamesFromMap().contains(Group.ALL))
{
state.visibilityMap.clear();
for (String s : this.model.getMatLib().getGroups().keySet())
{
transform = state.parent.apply(Optional.<IModelPart>absent());
state.visibilityMap.put(s, state.operation.performOperation(true));
}
//TODO: can this be replaced by updateStateVisibilityMap(OBJState)?
if (state.getGroupNamesFromMap().contains(Group.ALL))
}
else if (state.getGroupNamesFromMap().contains(Group.ALL_EXCEPT))
{
List<String> exceptList = state.getGroupNamesFromMap().subList(1, state.getGroupNamesFromMap().size());
state.visibilityMap.clear();
for (String s : this.model.getMatLib().getGroups().keySet())
{
state.visibilityMap.clear();
for (String s : this.model.getMatLib().getGroups().keySet())
if (!exceptList.contains(s))
{
state.visibilityMap.put(s, state.operation.performOperation(true));
}
}
else if (state.getGroupNamesFromMap().contains(Group.ALL_EXCEPT))
{
List<String> exceptList = state.getGroupNamesFromMap().subList(1, state.getGroupNamesFromMap().size());
state.visibilityMap.clear();
for (String s : this.model.getMatLib().getGroups().keySet())
{
if (!exceptList.contains(s))
{
state.visibilityMap.put(s, state.operation.performOperation(true));
}
}
}
else
{
for (String s : state.visibilityMap.keySet())
{
state.visibilityMap.put(s, state.operation.performOperation(state.visibilityMap.get(s)));
}
}
if (state.getGroupsWithVisibility(true).contains(g.getName()))
{
faces.addAll(g.applyTransform(transform));
}
}
else
{
transform = state.apply(Optional.<IModelPart>absent());
for (String s : state.visibilityMap.keySet())
{
state.visibilityMap.put(s, state.operation.performOperation(state.visibilityMap.get(s)));
}
}
if (state.getGroupsWithVisibility(true).contains(g.getName()))
{
faces.addAll(g.applyTransform(transform));
}
}
for (Face f : faces)
else
{
if (this.model.getMatLib().materials.get(f.getMaterialName()).isWhite())
{
for (Vertex v : f.getVertices())
{//update material in each vertex
if (!v.getMaterial().equals(this.model.getMatLib().getMaterial(v.getMaterial().getName())))
{
v.setMaterial(this.model.getMatLib().getMaterial(v.getMaterial().getName()));
}
}
sprite = ModelLoader.White.INSTANCE;
} else sprite = this.textures.get(f.getMaterialName());
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);
builder.setContractUVs(true);
builder.setQuadOrientation(EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z));
builder.setTexture(sprite);
Normal faceNormal = f.getNormal();
putVertexData(builder, f.verts[0], faceNormal, TextureCoordinate.getDefaultUVs()[0], sprite);
putVertexData(builder, f.verts[1], faceNormal, TextureCoordinate.getDefaultUVs()[1], sprite);
putVertexData(builder, f.verts[2], faceNormal, TextureCoordinate.getDefaultUVs()[2], sprite);
putVertexData(builder, f.verts[3], faceNormal, TextureCoordinate.getDefaultUVs()[3], sprite);
quads.add(builder.build());
transform = modelState.apply(Optional.<IModelPart>absent());
faces.addAll(g.applyTransform(transform));
}
}
List<BakedQuad> quadList = Collections.synchronizedList(Lists.newArrayList(quads));
return quadList;
for (Face f : faces)
{
if (this.model.getMatLib().materials.get(f.getMaterialName()).isWhite())
{
for (Vertex v : f.getVertices())
{//update material in each vertex
if (!v.getMaterial().equals(this.model.getMatLib().getMaterial(v.getMaterial().getName())))
{
v.setMaterial(this.model.getMatLib().getMaterial(v.getMaterial().getName()));
}
}
sprite = ModelLoader.White.INSTANCE;
}
else sprite = this.textures.get(f.getMaterialName());
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(format);
builder.setContractUVs(true);
builder.setQuadOrientation(EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z));
builder.setTexture(sprite);
Normal faceNormal = f.getNormal();
putVertexData(builder, f.verts[0], faceNormal, TextureCoordinate.getDefaultUVs()[0], sprite);
putVertexData(builder, f.verts[1], faceNormal, TextureCoordinate.getDefaultUVs()[1], sprite);
putVertexData(builder, f.verts[2], faceNormal, TextureCoordinate.getDefaultUVs()[2], sprite);
putVertexData(builder, f.verts[3], faceNormal, TextureCoordinate.getDefaultUVs()[3], sprite);
quads.add(builder.build());
}
return ImmutableList.copyOf(quads);
}
private final void putVertexData(UnpackedBakedQuad.Builder builder, Vertex v, Normal faceNormal, TextureCoordinate defUV, TextureAtlasSprite sprite)

View File

@ -0,0 +1,18 @@
package net.minecraftforge.common.model;
import com.google.common.collect.ImmutableList;
final class HiddenModelPart implements IModelPart
{
private final ImmutableList<String> path;
HiddenModelPart(ImmutableList<String> path)
{
this.path = path;
}
ImmutableList<String> getPath()
{
return path;
}
}

View File

@ -0,0 +1,24 @@
package net.minecraftforge.common.model;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.UnmodifiableIterator;
public enum Models
{
;
public static IModelPart getHiddenModelPart(ImmutableList<String> path)
{
return new HiddenModelPart(path);
}
public static UnmodifiableIterator<String> getParts(IModelPart part)
{
if(part instanceof HiddenModelPart)
{
return ((HiddenModelPart) part).getPath().iterator();
}
return Iterators.emptyIterator();
}
}

View File

@ -1,7 +1,6 @@
package net.minecraftforge.debug;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.vecmath.AxisAngle4d;
@ -10,6 +9,8 @@ import javax.vecmath.Quat4f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector4f;
import com.google.common.base.Optional;
import com.google.common.collect.UnmodifiableIterator;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
@ -36,16 +37,17 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.b3d.B3DLoader;
import net.minecraftforge.client.model.obj.OBJLoader;
import net.minecraftforge.client.model.obj.OBJModel;
import net.minecraftforge.common.model.IModelPart;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.Models;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
@ -120,7 +122,6 @@ public class ModelLoaderRegistryDebug
public static final CustomModelBlock instance = new CustomModelBlock();
public static final String name = "CustomModelBlock";
private int counter = 1;
public ExtendedBlockState state = new ExtendedBlockState(this, new IProperty[]{FACING}, new IUnlistedProperty[]{B3DLoader.B3DFrameProperty.INSTANCE});
private CustomModelBlock()
{
@ -163,7 +164,7 @@ public class ModelLoaderRegistryDebug
{
//Only return an IExtendedBlockState from this method and createState(), otherwise block placement might break!
B3DLoader.B3DState newState = new B3DLoader.B3DState(null, counter);
return ((IExtendedBlockState) state).withProperty(B3DLoader.B3DFrameProperty.INSTANCE, newState);
return ((IExtendedBlockState) state).withProperty(Properties.AnimationProperty, newState);
}
@Override
@ -183,7 +184,7 @@ public class ModelLoaderRegistryDebug
@Override
public BlockStateContainer createBlockState()
{
return new ExtendedBlockState(this, new IProperty[]{FACING}, new IUnlistedProperty[]{B3DLoader.B3DFrameProperty.INSTANCE});
return new ExtendedBlockState(this, new IProperty[]{FACING}, new IUnlistedProperty[]{Properties.AnimationProperty});
}
public static EnumFacing getFacingFromEntity(World worldIn, BlockPos clickedBlock, EntityLivingBase entityIn)
@ -221,7 +222,6 @@ public class ModelLoaderRegistryDebug
{
public static final OBJTesseractBlock instance = new OBJTesseractBlock();
public static final String name = "OBJTesseractBlock";
private ExtendedBlockState state = new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[]{OBJModel.OBJProperty.INSTANCE});
private OBJTesseractBlock()
{
@ -246,20 +246,11 @@ public class ModelLoaderRegistryDebug
@Override
public boolean isVisuallyOpaque() { return false; }
@Override
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
{
OBJTesseractTileEntity tileEntity = (OBJTesseractTileEntity) world.getTileEntity(pos);
OBJModel.OBJState retState = new OBJModel.OBJState(tileEntity == null ? Lists.newArrayList(OBJModel.Group.ALL) : tileEntity.visible, true);
return ((IExtendedBlockState) this.state.getBaseState()).withProperty(OBJModel.OBJProperty.INSTANCE, retState);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ)
{
if (world.getTileEntity(pos) == null) world.setTileEntity(pos, new OBJTesseractTileEntity());
OBJTesseractTileEntity tileEntity = (OBJTesseractTileEntity) world.getTileEntity(pos);
IModel model = ModelLoaderRegistry.getModelOrMissing(new ResourceLocation(MODID.toLowerCase() + ":" + "block/tesseract.obj"));
if (player.isSneaking())
{
@ -267,19 +258,9 @@ public class ModelLoaderRegistryDebug
}
else
{
if (model != ModelLoaderRegistry.getMissingModel())
{
tileEntity.setMax(((OBJModel) model).getMatLib().getGroups().keySet().size() - 1);
tileEntity.increment();
}
tileEntity.increment();
}
if (world.isRemote)
{
// wtf
//OBJBakedModel objBaked = (OBJBakedModel) Minecraft.getMinecraft().getBlockRendererDispatcher().getModelFromBlockState(state, world, pos);
//objBaked.scheduleRebake(); //not necessarily needed for this specific case, but is available
}
world.markBlockRangeForRenderUpdate(pos, pos);
return false;
}
@ -289,69 +270,85 @@ public class ModelLoaderRegistryDebug
{
return true;
}
@Override
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
{
if (world.getTileEntity(pos) != null && world.getTileEntity(pos) instanceof OBJTesseractTileEntity)
{
OBJTesseractTileEntity te = (OBJTesseractTileEntity) world.getTileEntity(pos);
return ((IExtendedBlockState) state).withProperty(Properties.AnimationProperty, te.state);
}
return state;
}
@Override
public BlockStateContainer createBlockState()
{
return new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[] {Properties.AnimationProperty});
}
}
public static class OBJTesseractTileEntity extends TileEntity
{
private int counter = 1;
private int max = 2;
public List<String> visible = new ArrayList<String>();
public OBJTesseractTileEntity()
private int max = 32;
private final List<String> hidden = new ArrayList<String>();
private final IModelState state = new IModelState()
{
this.visible.add(OBJModel.Group.ALL);
}
private final Optional<TRSRTransformation> value = Optional.of(TRSRTransformation.identity());
@Override
public Optional<TRSRTransformation> apply(Optional<? extends IModelPart> part)
{
if(part.isPresent())
{
// This whole thing is subject to change, but should do for now.
UnmodifiableIterator<String> parts = Models.getParts(part.get());
if(parts.hasNext())
{
String name = parts.next();
// only interested in the root level
if(!parts.hasNext() && hidden.contains(name))
{
return value;
}
}
}
return Optional.absent();
}
};
public void increment()
{
if (this.visible.contains(OBJModel.Group.ALL)) this.visible.remove(OBJModel.Group.ALL);
if (this.counter == max)
{
this.counter = 0;
this.visible.clear();
this.hidden.clear();
}
this.counter++;
this.visible.add(Integer.toString(this.counter));
this.hidden.add(Integer.toString(this.counter));
TextComponentString text = new TextComponentString("" + this.counter);
if (this.worldObj.isRemote) Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(text);
}
public void decrement()
{
if (this.visible.contains(OBJModel.Group.ALL)) this.visible.remove(OBJModel.Group.ALL);
if (this.counter == 1)
{
this.counter = max + 1;
for (int i = 1; i < max; i++) this.visible.add(Integer.toString(i));
for (int i = 1; i < max; i++) this.hidden.add(Integer.toString(i));
}
this.visible.remove(Integer.toString(this.counter));
this.hidden.remove(Integer.toString(this.counter));
this.counter--;
TextComponentString text = new TextComponentString("" + this.counter);
if (this.worldObj.isRemote) Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(text);
}
public void reset()
{
this.counter = 1;
this.max = 2;
this.visible.clear();
this.visible.add(Integer.toString(this.counter));
}
public int getMax()
{
return this.max;
}
public void setMax(int max)
{
this.max = max;
}
public void setToMax()
{
this.counter = this.max;
}
}
/**
@ -431,7 +428,7 @@ public class ModelLoaderRegistryDebug
@Override
public BlockStateContainer createBlockState()
{
return new ExtendedBlockState(this, new IProperty[] {FACING}, new IUnlistedProperty[] {OBJModel.OBJProperty.INSTANCE});
return new BlockStateContainer(this, FACING);
}
@Override
@ -443,15 +440,6 @@ public class ModelLoaderRegistryDebug
@Override
public boolean isVisuallyOpaque() { return false; }
@Override
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
{
EnumFacing facing = (EnumFacing) state.getValue(FACING);
TRSRTransformation transform = new TRSRTransformation(facing);
OBJModel.OBJState retState = new OBJModel.OBJState(Arrays.asList(new String[]{OBJModel.Group.ALL}), true, transform);
return ((IExtendedBlockState) state).withProperty(OBJModel.OBJProperty.INSTANCE, retState);
}
public static EnumFacing getFacingFromEntity(World worldIn, BlockPos clickedBlock, EntityLivingBase entityIn)
{
if (MathHelper.abs((float)entityIn.posX - (float)clickedBlock.getX()) < 2.0F && MathHelper.abs((float)entityIn.posZ - (float)clickedBlock.getZ()) < 2.0F)
@ -586,7 +574,6 @@ public class ModelLoaderRegistryDebug
public static final PropertyDirection FACING = PropertyDirection.create("facing");
public static final OBJDirectionBlock instance = new OBJDirectionBlock();
public static final String name = "OBJDirectionBlock";
public ExtendedBlockState state = new ExtendedBlockState(this, new IProperty[]{FACING}, new IUnlistedProperty[]{OBJModel.OBJProperty.INSTANCE});
private OBJDirectionBlock()
{
@ -624,20 +611,10 @@ public class ModelLoaderRegistryDebug
return ((EnumFacing) state.getValue(FACING)).getIndex();
}
@Override
public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
{
//Only return an IExtendedBlockState from this method and createState(), otherwise block placement will break!
EnumFacing facing = (EnumFacing) state.getValue(FACING);
TRSRTransformation transform = new TRSRTransformation(facing);
OBJModel.OBJState newState = new OBJModel.OBJState(Lists.newArrayList(OBJModel.Group.ALL), true, transform);
return ((IExtendedBlockState) state).withProperty(OBJModel.OBJProperty.INSTANCE, newState);
}
@Override
public BlockStateContainer createBlockState()
{
return new ExtendedBlockState(this, new IProperty[]{FACING}, new IUnlistedProperty[]{OBJModel.OBJProperty.INSTANCE});
return new BlockStateContainer(this, FACING);
}
public static EnumFacing getFacingFromEntity(World worldIn, BlockPos clickedBlock, EntityLivingBase entityIn)
@ -732,7 +709,6 @@ public class ModelLoaderRegistryDebug
{
public static final OBJDynamicEye instance = new OBJDynamicEye();
public static final String name = "OBJDynamicEye";
public ExtendedBlockState state = new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[] {OBJModel.OBJProperty.INSTANCE});
private OBJDynamicEye()
{
super(Material.IRON);
@ -771,9 +747,9 @@ public class ModelLoaderRegistryDebug
if (world.getTileEntity(pos) != null && world.getTileEntity(pos) instanceof OBJDynamicEyeTileEntity)
{
OBJDynamicEyeTileEntity te = (OBJDynamicEyeTileEntity) world.getTileEntity(pos);
if (te.state != null)
if (te.transform != TRSRTransformation.identity())
{
return ((IExtendedBlockState) this.state.getBaseState()).withProperty(OBJModel.OBJProperty.INSTANCE, te.state);
return ((IExtendedBlockState) state).withProperty(Properties.AnimationProperty, te.transform);
}
}
return state;
@ -782,18 +758,13 @@ public class ModelLoaderRegistryDebug
@Override
public BlockStateContainer createBlockState()
{
return new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[] {OBJModel.OBJProperty.INSTANCE});
return new ExtendedBlockState(this, new IProperty[0], new IUnlistedProperty[] {Properties.AnimationProperty});
}
}
public static class OBJDynamicEyeTileEntity extends TileEntity implements ITickable
{
public OBJModel.OBJState state;
public OBJDynamicEyeTileEntity()
{
this.state = new OBJModel.OBJState(Lists.newArrayList(OBJModel.Group.ALL), true);
}
private TRSRTransformation transform = TRSRTransformation.identity();
@Override
public void update()
@ -821,9 +792,7 @@ public class ModelLoaderRegistryDebug
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
matrix.setRotation(rot);
TRSRTransformation transform = new TRSRTransformation(matrix);
transform = TRSRTransformation.blockCenterToCorner(transform);
this.state = new OBJModel.OBJState(Lists.newArrayList(OBJModel.Group.ALL), true, transform);
transform = TRSRTransformation.blockCenterToCorner(new TRSRTransformation(matrix));
this.worldObj.markBlockRangeForRenderUpdate(this.pos, this.pos);
}
}