pick 97420a31d The big reformat of 2020
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AEInternalModelData implements IModelData {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This implementation of IModelData allows us to know precisely which data is part of the
|
||||
* model data. This is relevant for {@link AutoRotatingBakedModel} and {@link AutoRotatingCacheKey}.
|
||||
* This implementation of IModelData allows us to know precisely which data is
|
||||
* part of the model data. This is relevant for {@link AutoRotatingBakedModel}
|
||||
* and {@link AutoRotatingCacheKey}.
|
||||
*/
|
||||
public class AEModelData implements IModelData {
|
||||
|
||||
@@ -36,11 +39,12 @@ public class AEModelData implements IModelData {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
AEModelData that = (AEModelData) o;
|
||||
return up == that.up &&
|
||||
forward == that.forward;
|
||||
return up == that.up && forward == that.forward;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,13 +18,19 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.client.render.FacingToRotation;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.Vector4f;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
@@ -44,298 +50,249 @@ import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
|
||||
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import appeng.client.render.FacingToRotation;
|
||||
|
||||
public class AutoRotatingBakedModel implements IBakedModel {
|
||||
|
||||
public class AutoRotatingBakedModel implements IBakedModel
|
||||
{
|
||||
private final IBakedModel parent;
|
||||
private final LoadingCache<AutoRotatingCacheKey, List<BakedQuad>> quadCache;
|
||||
|
||||
private final IBakedModel parent;
|
||||
private final LoadingCache<AutoRotatingCacheKey, List<BakedQuad>> quadCache;
|
||||
public AutoRotatingBakedModel(IBakedModel parent) {
|
||||
this.parent = parent;
|
||||
// 6 (DUNSWE) * 6 (DUNSWE) * 7 (DUNSWE + null) = 252
|
||||
this.quadCache = CacheBuilder.newBuilder().maximumSize(252)
|
||||
.build(new CacheLoader<AutoRotatingCacheKey, List<BakedQuad>>() {
|
||||
@Override
|
||||
public List<BakedQuad> load(AutoRotatingCacheKey key) {
|
||||
return AutoRotatingBakedModel.this.getRotatedModel(key.getBlockState(), key.getSide(),
|
||||
new Random(0), key.getModelData());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AutoRotatingBakedModel(IBakedModel parent )
|
||||
{
|
||||
this.parent = parent;
|
||||
// 6 (DUNSWE) * 6 (DUNSWE) * 7 (DUNSWE + null) = 252
|
||||
this.quadCache = CacheBuilder.newBuilder().maximumSize( 252 ).build( new CacheLoader<AutoRotatingCacheKey, List<BakedQuad>>()
|
||||
{
|
||||
@Override
|
||||
public List<BakedQuad> load( AutoRotatingCacheKey key )
|
||||
{
|
||||
return AutoRotatingBakedModel.this.getRotatedModel( key.getBlockState(), key.getSide(), new Random(0), key.getModelData() );
|
||||
}
|
||||
} );
|
||||
}
|
||||
private List<BakedQuad> getRotatedModel(BlockState state, Direction side, Random rand, AEModelData modelData) {
|
||||
FacingToRotation f2r = FacingToRotation.get(modelData.getForward(), modelData.getUp());
|
||||
|
||||
private List<BakedQuad> getRotatedModel(BlockState state, Direction side, Random rand, AEModelData modelData)
|
||||
{
|
||||
FacingToRotation f2r = FacingToRotation.get( modelData.getForward(), modelData.getUp() );
|
||||
if (f2r.isRedundant()) {
|
||||
return AutoRotatingBakedModel.this.parent.getQuads(state, side, rand, modelData);
|
||||
}
|
||||
|
||||
if (f2r.isRedundant()) {
|
||||
return AutoRotatingBakedModel.this.parent.getQuads( state, side, rand, modelData );
|
||||
}
|
||||
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads(state, f2r.resultingRotate(side), rand,
|
||||
modelData);
|
||||
List<BakedQuad> rotated = new ArrayList<>(original.size());
|
||||
for (BakedQuad quad : original) {
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
VertexRotator rot = new VertexRotator(f2r, quad.getFace());
|
||||
rot.setParent(builder);
|
||||
quad.pipe(rot);
|
||||
if (quad.getFace() != null) {
|
||||
builder.setQuadOrientation(f2r.rotate(quad.getFace()));
|
||||
} else {
|
||||
builder.setQuadOrientation(null);
|
||||
|
||||
List<BakedQuad> original = AutoRotatingBakedModel.this.parent.getQuads( state, f2r.resultingRotate( side ), rand, modelData );
|
||||
List<BakedQuad> rotated = new ArrayList<>( original.size() );
|
||||
for( BakedQuad quad : original )
|
||||
{
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
VertexRotator rot = new VertexRotator( f2r, quad.getFace() );
|
||||
rot.setParent( builder );
|
||||
quad.pipe( rot );
|
||||
if( quad.getFace() != null )
|
||||
{
|
||||
builder.setQuadOrientation( f2r.rotate( quad.getFace() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.setQuadOrientation( null );
|
||||
}
|
||||
BakedQuad unpackedQuad = builder.build();
|
||||
|
||||
}
|
||||
BakedQuad unpackedQuad = builder.build();
|
||||
// Make a copy of it to resolve the vertex data and throw away the unpacked
|
||||
// stuff
|
||||
// This also fixes a bug in Forge's UnpackedBakedQuad, which unpacks a
|
||||
// byte-based normal like 0,0,-1
|
||||
// to 0,0,-0.99607843. We replace these normals with the proper 0,0,-1 when
|
||||
// rotation, which
|
||||
// causes a bug in the AO lighter, if an unpacked quad pipes this value back to
|
||||
// it.
|
||||
// Packing it back to the vanilla vertex format will fix this inconsistency
|
||||
// because it converts
|
||||
// the normal back to a byte-based format, which then re-applies Forge's own bug
|
||||
// when piping it
|
||||
// to the AO lighter, thus fixing our problem.
|
||||
BakedQuad packedQuad = new BakedQuad(unpackedQuad.getVertexData(), quad.getTintIndex(),
|
||||
unpackedQuad.getFace(), quad.func_187508_a(), quad.shouldApplyDiffuseLighting());
|
||||
rotated.add(packedQuad);
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
// Make a copy of it to resolve the vertex data and throw away the unpacked stuff
|
||||
// This also fixes a bug in Forge's UnpackedBakedQuad, which unpacks a byte-based normal like 0,0,-1
|
||||
// to 0,0,-0.99607843. We replace these normals with the proper 0,0,-1 when rotation, which
|
||||
// causes a bug in the AO lighter, if an unpacked quad pipes this value back to it.
|
||||
// Packing it back to the vanilla vertex format will fix this inconsistency because it converts
|
||||
// the normal back to a byte-based format, which then re-applies Forge's own bug when piping it
|
||||
// to the AO lighter, thus fixing our problem.
|
||||
BakedQuad packedQuad = new BakedQuad( unpackedQuad.getVertexData(), quad.getTintIndex(), unpackedQuad.getFace(), quad.func_187508_a(), quad
|
||||
.shouldApplyDiffuseLighting() );
|
||||
rotated.add( packedQuad );
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return this.parent.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return this.parent.isAmbientOcclusion();
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return this.parent.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return this.parent.isGui3d();
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return parent.func_230044_c_();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return parent.func_230044_c_();
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return this.parent.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return this.parent.isBuiltInRenderer();
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.parent.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.parent.getParticleTexture();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return parent.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return parent.getItemCameraTransforms();
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return parent.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return parent.getOverrides();
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
return getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
}
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
|
||||
@Nonnull IModelData extraData) {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
|
||||
if (!(extraData instanceof AEModelData)) {
|
||||
return this.parent.getQuads(state, side, rand, extraData);
|
||||
}
|
||||
|
||||
if (!(extraData instanceof AEModelData)) {
|
||||
return this.parent.getQuads( state, side, rand, extraData );
|
||||
}
|
||||
AEModelData aeModelData = (AEModelData) extraData;
|
||||
quadCache.invalidateAll(); // FIXME
|
||||
if (aeModelData.isCacheable()) {
|
||||
return quadCache.getUnchecked(new AutoRotatingCacheKey(state, aeModelData, side));
|
||||
} else {
|
||||
return this.getRotatedModel(state, side, rand, aeModelData);
|
||||
}
|
||||
}
|
||||
|
||||
AEModelData aeModelData = (AEModelData) extraData;
|
||||
quadCache.invalidateAll(); // FIXME
|
||||
if (aeModelData.isCacheable()) {
|
||||
return quadCache.getUnchecked(new AutoRotatingCacheKey(state, aeModelData, side));
|
||||
} else {
|
||||
return this.getRotatedModel(state, side, rand, aeModelData);
|
||||
}
|
||||
}
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
|
||||
@Nonnull IModelData tileData) {
|
||||
return this.parent.getModelData(world, pos, state, tileData);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
|
||||
return this.parent.getModelData(world, pos, state, tileData);
|
||||
}
|
||||
public static class VertexRotator extends QuadGatheringTransformer {
|
||||
private final FacingToRotation f2r;
|
||||
private final Direction face;
|
||||
|
||||
public static class VertexRotator extends QuadGatheringTransformer
|
||||
{
|
||||
private final FacingToRotation f2r;
|
||||
private final Direction face;
|
||||
public VertexRotator(FacingToRotation f2r, Direction face) {
|
||||
this.f2r = f2r;
|
||||
this.face = face;
|
||||
}
|
||||
|
||||
public VertexRotator( FacingToRotation f2r, Direction face )
|
||||
{
|
||||
this.f2r = f2r;
|
||||
this.face = face;
|
||||
}
|
||||
@Override
|
||||
public void setParent(IVertexConsumer parent) {
|
||||
super.setParent(parent);
|
||||
if (Objects.equal(this.getVertexFormat(), parent.getVertexFormat())) {
|
||||
return;
|
||||
}
|
||||
this.setVertexFormat(parent.getVertexFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParent( IVertexConsumer parent )
|
||||
{
|
||||
super.setParent( parent );
|
||||
if( Objects.equal( this.getVertexFormat(), parent.getVertexFormat() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.setVertexFormat( parent.getVertexFormat() );
|
||||
}
|
||||
@Override
|
||||
protected void processQuad() {
|
||||
VertexFormat format = this.parent.getVertexFormat();
|
||||
ImmutableList<VertexFormatElement> elements = format.getElements();
|
||||
|
||||
@Override
|
||||
protected void processQuad()
|
||||
{
|
||||
VertexFormat format = this.parent.getVertexFormat();
|
||||
ImmutableList<VertexFormatElement> elements = format.getElements();
|
||||
for (int v = 0; v < 4; v++) {
|
||||
for (int e = 0; e < elements.size(); e++) {
|
||||
VertexFormatElement element = elements.get(e);
|
||||
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
|
||||
this.parent.put(e, this.transform(this.quadData[e][v]));
|
||||
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
|
||||
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
|
||||
} else {
|
||||
this.parent.put(e, this.quadData[e][v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int v = 0; v < 4; v++ )
|
||||
{
|
||||
for( int e = 0; e < elements.size(); e++ )
|
||||
{
|
||||
VertexFormatElement element = elements.get( e );
|
||||
if( element.getUsage() == VertexFormatElement.Usage.POSITION )
|
||||
{
|
||||
this.parent.put( e, this.transform( this.quadData[e][v] ) );
|
||||
}
|
||||
else if( element.getUsage() == VertexFormatElement.Usage.NORMAL )
|
||||
{
|
||||
this.parent.put( e, this.transformNormal( this.quadData[e][v] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent.put( e, this.quadData[e][v] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private float[] transform(float[] fs) {
|
||||
switch (fs.length) {
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
|
||||
vec.setX(vec.getX() - 0.5f);
|
||||
vec.setY(vec.getY() - 0.5f);
|
||||
vec.setZ(vec.getZ() - 0.5f);
|
||||
vec.transform(this.f2r.getMat());
|
||||
vec.setX(vec.getX() + 0.5f);
|
||||
vec.setY(vec.getY() + 0.5f);
|
||||
vec.setZ(vec.getZ() + 0.5f);
|
||||
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
|
||||
case 4:
|
||||
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
|
||||
vecc.setX(vecc.getX() - 0.5f);
|
||||
vecc.setY(vecc.getY() - 0.5f);
|
||||
vecc.setZ(vecc.getZ() - 0.5f);
|
||||
vecc.transform(this.f2r.getMat());
|
||||
vecc.setX(vecc.getX() + 0.5f);
|
||||
vecc.setY(vecc.getY() + 0.5f);
|
||||
vecc.setZ(vecc.getZ() + 0.5f);
|
||||
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
|
||||
|
||||
private float[] transform( float[] fs )
|
||||
{
|
||||
switch( fs.length )
|
||||
{
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 1 );
|
||||
vec.setX(vec.getX() - 0.5f);
|
||||
vec.setY(vec.getY() - 0.5f);
|
||||
vec.setZ(vec.getZ() - 0.5f);
|
||||
vec.transform(this.f2r.getMat());
|
||||
vec.setX(vec.getX() + 0.5f);
|
||||
vec.setY(vec.getY() + 0.5f);
|
||||
vec.setZ(vec.getZ() + 0.5f);
|
||||
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
|
||||
case 4:
|
||||
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
|
||||
vecc.setX(vecc.getX() - 0.5f);
|
||||
vecc.setY(vecc.getY() - 0.5f);
|
||||
vecc.setZ(vecc.getZ() - 0.5f);
|
||||
vecc.transform(this.f2r.getMat());
|
||||
vecc.setX(vecc.getX() + 0.5f);
|
||||
vecc.setY(vecc.getY() + 0.5f);
|
||||
vecc.setZ(vecc.getZ() + 0.5f);
|
||||
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
private float[] transformNormal(float[] fs) {
|
||||
if (this.face == null) {
|
||||
switch (fs.length) {
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 0);
|
||||
vec.transform(this.f2r.getMat());
|
||||
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
|
||||
case 4:
|
||||
Vector4f vec4 = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
|
||||
vec4.transform(this.f2r.getMat());
|
||||
return new float[] { vec4.getX(), vec4.getY(), vec4.getZ(), 0 };
|
||||
|
||||
private float[] transformNormal( float[] fs )
|
||||
{
|
||||
if( this.face == null )
|
||||
{
|
||||
switch( fs.length )
|
||||
{
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 0 );
|
||||
vec.transform( this.f2r.getMat() );
|
||||
return new float[] {
|
||||
vec.getX(),
|
||||
vec.getY(),
|
||||
vec.getZ()
|
||||
};
|
||||
case 4:
|
||||
Vector4f vec4 = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
|
||||
vec4.transform( this.f2r.getMat() );
|
||||
return new float[] {
|
||||
vec4.getX(),
|
||||
vec4.getY(),
|
||||
vec4.getZ(),
|
||||
0
|
||||
};
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
} else {
|
||||
switch (fs.length) {
|
||||
case 3:
|
||||
Vec3i vec = this.f2r.rotate(this.face).getDirectionVec();
|
||||
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
|
||||
case 4:
|
||||
Vector4f veccc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
|
||||
Vec3i vecc = this.f2r.rotate(this.face).getDirectionVec();
|
||||
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), veccc.getW() };
|
||||
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( fs.length )
|
||||
{
|
||||
case 3:
|
||||
Vec3i vec = this.f2r.rotate( this.face ).getDirectionVec();
|
||||
return new float[] {
|
||||
vec.getX(),
|
||||
vec.getY(),
|
||||
vec.getZ()
|
||||
};
|
||||
case 4:
|
||||
Vector4f veccc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
|
||||
Vec3i vecc = this.f2r.rotate( this.face ).getDirectionVec();
|
||||
return new float[] {
|
||||
vecc.getX(),
|
||||
vecc.getY(),
|
||||
vecc.getZ(),
|
||||
veccc.getW()
|
||||
};
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setQuadTint(int tint) {
|
||||
this.parent.setQuadTint(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadTint( int tint )
|
||||
{
|
||||
this.parent.setQuadTint( tint );
|
||||
}
|
||||
@Override
|
||||
public void setQuadOrientation(Direction orientation) {
|
||||
this.parent.setQuadOrientation(f2r.rotate(orientation));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadOrientation( Direction orientation )
|
||||
{
|
||||
this.parent.setQuadOrientation( f2r.rotate(orientation) );
|
||||
}
|
||||
@Override
|
||||
public void setApplyDiffuseLighting(boolean diffuse) {
|
||||
this.parent.setApplyDiffuseLighting(diffuse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplyDiffuseLighting( boolean diffuse )
|
||||
{
|
||||
this.parent.setApplyDiffuseLighting( diffuse );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTexture( TextureAtlasSprite texture )
|
||||
{
|
||||
this.parent.setTexture( texture );
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void setTexture(TextureAtlasSprite texture) {
|
||||
this.parent.setTexture(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,63 +18,54 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.Direction;
|
||||
|
||||
|
||||
/**
|
||||
* Used as the cache key for caching automatically rotated baked models.
|
||||
*/
|
||||
final class AutoRotatingCacheKey
|
||||
{
|
||||
private final BlockState blockState;
|
||||
private final AEModelData modelData;
|
||||
private final Direction side;
|
||||
final class AutoRotatingCacheKey {
|
||||
private final BlockState blockState;
|
||||
private final AEModelData modelData;
|
||||
private final Direction side;
|
||||
|
||||
AutoRotatingCacheKey( BlockState blockState, AEModelData modelData, Direction side )
|
||||
{
|
||||
this.blockState = blockState;
|
||||
this.modelData = modelData;
|
||||
this.side = side;
|
||||
}
|
||||
AutoRotatingCacheKey(BlockState blockState, AEModelData modelData, Direction side) {
|
||||
this.blockState = blockState;
|
||||
this.modelData = modelData;
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public BlockState getBlockState()
|
||||
{
|
||||
return this.blockState;
|
||||
}
|
||||
public BlockState getBlockState() {
|
||||
return this.blockState;
|
||||
}
|
||||
|
||||
public AEModelData getModelData() {
|
||||
return modelData;
|
||||
}
|
||||
public AEModelData getModelData() {
|
||||
return modelData;
|
||||
}
|
||||
|
||||
public Direction getSide()
|
||||
{
|
||||
return this.side;
|
||||
}
|
||||
public Direction getSide() {
|
||||
return this.side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
if( this == o )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( o == null || this.getClass() != o.getClass() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || this.getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoRotatingCacheKey cacheKey = (AutoRotatingCacheKey) o;
|
||||
return this.blockState.equals( cacheKey.blockState ) && this.modelData.equals(cacheKey.modelData) && this.side == cacheKey.side;
|
||||
}
|
||||
AutoRotatingCacheKey cacheKey = (AutoRotatingCacheKey) o;
|
||||
return this.blockState.equals(cacheKey.blockState) && this.modelData.equals(cacheKey.modelData)
|
||||
&& this.side == cacheKey.side;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = this.blockState.hashCode();
|
||||
result = 31 * result + this.modelData.hashCode();
|
||||
result = 31 * result + ( this.side != null ? this.side.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.blockState.hashCode();
|
||||
result = 31 * result + this.modelData.hashCode();
|
||||
result = 31 * result + (this.side != null ? this.side.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
@@ -30,191 +30,160 @@ import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.AELog;
|
||||
|
||||
class BiometricCardBakedModel implements IBakedModel {
|
||||
|
||||
class BiometricCardBakedModel implements IBakedModel
|
||||
{
|
||||
private final IBakedModel baseModel;
|
||||
|
||||
private final IBakedModel baseModel;
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
private final TextureAtlasSprite texture;
|
||||
private final int hash;
|
||||
|
||||
private final int hash;
|
||||
private final Cache<Integer, BiometricCardBakedModel> modelCache;
|
||||
|
||||
private final Cache<Integer, BiometricCardBakedModel> modelCache;
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
BiometricCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture) {
|
||||
this(baseModel, texture, 0, createCache());
|
||||
}
|
||||
|
||||
BiometricCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture )
|
||||
{
|
||||
this( baseModel, texture, 0, createCache() );
|
||||
}
|
||||
private BiometricCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture, int hash,
|
||||
Cache<Integer, BiometricCardBakedModel> modelCache) {
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.hash = hash;
|
||||
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
|
||||
private BiometricCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture, int hash, Cache<Integer, BiometricCardBakedModel> modelCache )
|
||||
{
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.hash = hash;
|
||||
this.generalQuads = ImmutableList.copyOf( this.buildGeneralQuads() );
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
private static Cache<Integer, BiometricCardBakedModel> createCache() {
|
||||
return CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
}
|
||||
|
||||
private static Cache<Integer, BiometricCardBakedModel> createCache()
|
||||
{
|
||||
return CacheBuilder.newBuilder().maximumSize( 100 ).build();
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
|
||||
{
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
|
||||
List<BakedQuad> quads = this.baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE );
|
||||
if (side != null) {
|
||||
return quads;
|
||||
}
|
||||
|
||||
if( side != null )
|
||||
{
|
||||
return quads;
|
||||
}
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
|
||||
result.addAll(quads);
|
||||
result.addAll(this.generalQuads);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>( quads.size() + this.generalQuads.size() );
|
||||
result.addAll( quads );
|
||||
result.addAll( this.generalQuads );
|
||||
return result;
|
||||
}
|
||||
private List<BakedQuad> buildGeneralQuads() {
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
|
||||
private List<BakedQuad> buildGeneralQuads()
|
||||
{
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
builder.setTexture( this.texture );
|
||||
AEColor col = AEColor.values()[Math.abs(3 + this.hash) % AEColor.values().length];
|
||||
if (this.hash == 0) {
|
||||
col = AEColor.BLACK;
|
||||
}
|
||||
|
||||
AEColor col = AEColor.values()[Math.abs( 3 + this.hash ) % AEColor.values().length];
|
||||
if( this.hash == 0 )
|
||||
{
|
||||
col = AEColor.BLACK;
|
||||
}
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 6; y++) {
|
||||
final boolean isLit;
|
||||
|
||||
for( int x = 0; x < 8; x++ )
|
||||
{
|
||||
for( int y = 0; y < 6; y++ )
|
||||
{
|
||||
final boolean isLit;
|
||||
// This makes the border always use the darker color
|
||||
if (x == 0 || y == 0 || x == 7 || y == 5) {
|
||||
isLit = false;
|
||||
} else {
|
||||
isLit = (this.hash & (1 << x)) != 0 || (this.hash & (1 << y)) != 0;
|
||||
}
|
||||
|
||||
// This makes the border always use the darker color
|
||||
if( x == 0 || y == 0 || x == 7 || y == 5 )
|
||||
{
|
||||
isLit = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isLit = ( this.hash & ( 1 << x ) ) != 0 || ( this.hash & ( 1 << y ) ) != 0;
|
||||
}
|
||||
if (isLit) {
|
||||
builder.setColorRGB(col.mediumVariant);
|
||||
} else {
|
||||
final float scale = 0.3f / 255.0f;
|
||||
builder.setColorRGB(((col.blackVariant >> 16) & 0xff) * scale,
|
||||
((col.blackVariant >> 8) & 0xff) * scale, (col.blackVariant & 0xff) * scale);
|
||||
}
|
||||
|
||||
if( isLit )
|
||||
{
|
||||
builder.setColorRGB( col.mediumVariant );
|
||||
}
|
||||
else
|
||||
{
|
||||
final float scale = 0.3f / 255.0f;
|
||||
builder.setColorRGB( ( ( col.blackVariant >> 16 ) & 0xff ) * scale, ( ( col.blackVariant >> 8 ) & 0xff ) * scale, ( col.blackVariant & 0xff ) * scale );
|
||||
}
|
||||
builder.addCube(4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
return builder.getOutput();
|
||||
}
|
||||
|
||||
builder.addCube( 4 + x, 6 + y, 7.5f, 4 + x + 1, 6 + y + 1, 8.5f );
|
||||
}
|
||||
}
|
||||
return builder.getOutput();
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return false;//TODO
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return new ItemOverrideList() {
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, World world,
|
||||
LivingEntity entity) {
|
||||
String username = "";
|
||||
if (stack.getItem() instanceof IBiometricCard) {
|
||||
final GameProfile gp = ((IBiometricCard) stack.getItem()).getProfile(stack);
|
||||
if (gp != null) {
|
||||
if (gp.getId() != null) {
|
||||
username = gp.getId().toString();
|
||||
} else {
|
||||
username = gp.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
final int hash = !username.isEmpty() ? username.hashCode() : 0;
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return new ItemOverrideList()
|
||||
{
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides( IBakedModel originalModel, ItemStack stack, World world, LivingEntity entity )
|
||||
{
|
||||
String username = "";
|
||||
if( stack.getItem() instanceof IBiometricCard )
|
||||
{
|
||||
final GameProfile gp = ( (IBiometricCard) stack.getItem() ).getProfile( stack );
|
||||
if( gp != null )
|
||||
{
|
||||
if( gp.getId() != null )
|
||||
{
|
||||
username = gp.getId().toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
username = gp.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
final int hash = !username.isEmpty() ? username.hashCode() : 0;
|
||||
// Get hash
|
||||
if (hash == 0) {
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
|
||||
// Get hash
|
||||
if( hash == 0 )
|
||||
{
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
try {
|
||||
return BiometricCardBakedModel.this.modelCache.get(hash,
|
||||
() -> new BiometricCardBakedModel(BiometricCardBakedModel.this.baseModel,
|
||||
BiometricCardBakedModel.this.texture, hash,
|
||||
BiometricCardBakedModel.this.modelCache));
|
||||
} catch (ExecutionException e) {
|
||||
AELog.error(e);
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return BiometricCardBakedModel.this.modelCache.get( hash, () -> new BiometricCardBakedModel( BiometricCardBakedModel.this.baseModel, BiometricCardBakedModel.this.texture, hash, BiometricCardBakedModel.this.modelCache ) );
|
||||
}
|
||||
catch( ExecutionException e )
|
||||
{
|
||||
AELog.error( e );
|
||||
return BiometricCardBakedModel.this;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public boolean doesHandlePerspectives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesHandlePerspectives()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
|
||||
{
|
||||
baseModel.handlePerspective( cameraTransformType, mat );
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
|
||||
baseModel.handlePerspective(cameraTransformType, mat);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
@@ -13,37 +13,37 @@ import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Model wrapper for the biometric card item model, which combines a base card layer with a "visual hash" of the player
|
||||
* name
|
||||
* Model wrapper for the biometric card item model, which combines a base card
|
||||
* layer with a "visual hash" of the player name
|
||||
*/
|
||||
public class BiometricCardModel implements IModelGeometry<BiometricCardModel>
|
||||
{
|
||||
public class BiometricCardModel implements IModelGeometry<BiometricCardModel> {
|
||||
|
||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/biometric_card_base" );
|
||||
private static final Material TEXTURE = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/biometric_card_hash" ) );
|
||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID, "item/biometric_card_base");
|
||||
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "item/biometric_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
|
||||
{
|
||||
return Collections.singleton( TEXTURE );
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.singleton(TEXTURE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transformIn, ItemOverrideList overrides, ResourceLocation locationIn )
|
||||
{
|
||||
TextureAtlasSprite texture = spriteGetter.apply( TEXTURE );
|
||||
@Nullable
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transformIn,
|
||||
ItemOverrideList overrides, ResourceLocation locationIn) {
|
||||
TextureAtlasSprite texture = spriteGetter.apply(TEXTURE);
|
||||
|
||||
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, transformIn, spriteGetter );
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, transformIn, spriteGetter);
|
||||
|
||||
return new BiometricCardBakedModel( baseModel, texture );
|
||||
}
|
||||
return new BiometricCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
@@ -20,120 +20,100 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.PerspectiveMapWrapper;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
class ColorApplicatorBakedModel implements IBakedModel {
|
||||
|
||||
class ColorApplicatorBakedModel implements IBakedModel
|
||||
{
|
||||
private final IBakedModel baseModel;
|
||||
|
||||
private final IBakedModel baseModel;
|
||||
private final IModelTransform transforms;
|
||||
|
||||
private final IModelTransform transforms;
|
||||
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
|
||||
|
||||
private final EnumMap<Direction, List<BakedQuad>> quadsBySide;
|
||||
private final List<BakedQuad> generalQuads;
|
||||
|
||||
private final List<BakedQuad> generalQuads;
|
||||
ColorApplicatorBakedModel(IBakedModel baseModel, IModelTransform transforms, TextureAtlasSprite texDark,
|
||||
TextureAtlasSprite texMedium, TextureAtlasSprite texBright) {
|
||||
this.baseModel = baseModel;
|
||||
this.transforms = transforms;
|
||||
|
||||
ColorApplicatorBakedModel( IBakedModel baseModel, IModelTransform transforms, TextureAtlasSprite texDark, TextureAtlasSprite texMedium, TextureAtlasSprite texBright )
|
||||
{
|
||||
this.baseModel = baseModel;
|
||||
this.transforms = transforms;
|
||||
// Put the tint indices in... Since this is an item model, we are ignoring rand
|
||||
this.generalQuads = this.fixQuadTint(null, texDark, texMedium, texBright);
|
||||
this.quadsBySide = new EnumMap<>(Direction.class);
|
||||
for (Direction facing : Direction.values()) {
|
||||
this.quadsBySide.put(facing, this.fixQuadTint(facing, texDark, texMedium, texBright));
|
||||
}
|
||||
}
|
||||
|
||||
// Put the tint indices in... Since this is an item model, we are ignoring rand
|
||||
this.generalQuads = this.fixQuadTint( null, texDark, texMedium, texBright );
|
||||
this.quadsBySide = new EnumMap<>( Direction.class );
|
||||
for( Direction facing : Direction.values() )
|
||||
{
|
||||
this.quadsBySide.put( facing, this.fixQuadTint( facing, texDark, texMedium, texBright ) );
|
||||
}
|
||||
}
|
||||
private List<BakedQuad> fixQuadTint(Direction facing, TextureAtlasSprite texDark, TextureAtlasSprite texMedium,
|
||||
TextureAtlasSprite texBright) {
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(null, facing, new Random(0), EmptyModelData.INSTANCE);
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size());
|
||||
for (BakedQuad quad : quads) {
|
||||
int tint;
|
||||
|
||||
private List<BakedQuad> fixQuadTint( Direction facing, TextureAtlasSprite texDark, TextureAtlasSprite texMedium, TextureAtlasSprite texBright )
|
||||
{
|
||||
List<BakedQuad> quads = this.baseModel.getQuads( null, facing, new Random( 0 ), EmptyModelData.INSTANCE );
|
||||
List<BakedQuad> result = new ArrayList<>( quads.size() );
|
||||
for( BakedQuad quad : quads )
|
||||
{
|
||||
int tint;
|
||||
if (quad.func_187508_a() == texDark) {
|
||||
tint = 1;
|
||||
} else if (quad.func_187508_a() == texMedium) {
|
||||
tint = 2;
|
||||
} else if (quad.func_187508_a() == texBright) {
|
||||
tint = 3;
|
||||
} else {
|
||||
result.add(quad);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( quad.func_187508_a() == texDark )
|
||||
{
|
||||
tint = 1;
|
||||
}
|
||||
else if( quad.func_187508_a() == texMedium )
|
||||
{
|
||||
tint = 2;
|
||||
}
|
||||
else if( quad.func_187508_a() == texBright )
|
||||
{
|
||||
tint = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.add( quad );
|
||||
continue;
|
||||
}
|
||||
BakedQuad newQuad = new BakedQuad(quad.getVertexData(), tint, quad.getFace(), quad.func_187508_a(),
|
||||
quad.shouldApplyDiffuseLighting());
|
||||
result.add(newQuad);
|
||||
}
|
||||
|
||||
BakedQuad newQuad = new BakedQuad( quad.getVertexData(), tint, quad.getFace(), quad.func_187508_a(), quad.shouldApplyDiffuseLighting() );
|
||||
result.add( newQuad );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
if (side == null) {
|
||||
return this.generalQuads;
|
||||
}
|
||||
return this.quadsBySide.get(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
|
||||
{
|
||||
if( side == null )
|
||||
{
|
||||
return this.generalQuads;
|
||||
}
|
||||
return this.quadsBySide.get( side );
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return false;//TODO
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return this.baseModel.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return this.baseModel.getOverrides();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
|
||||
{
|
||||
return PerspectiveMapWrapper.handlePerspective( this, transforms, cameraTransformType, mat );
|
||||
}
|
||||
@Override
|
||||
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
|
||||
return PerspectiveMapWrapper.handlePerspective(this, transforms, cameraTransformType, mat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
@@ -16,37 +16,42 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* A color applicator uses the base model, and extends it with additional layers that are colored according to the
|
||||
* selected color of the applicator.
|
||||
* A color applicator uses the base model, and extends it with additional layers
|
||||
* that are colored according to the selected color of the applicator.
|
||||
*/
|
||||
public class ColorApplicatorModel implements IModelGeometry<ColorApplicatorModel>
|
||||
{
|
||||
public class ColorApplicatorModel implements IModelGeometry<ColorApplicatorModel> {
|
||||
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_colored" );
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID,
|
||||
"item/color_applicator_colored");
|
||||
|
||||
private static final Material TEXTURE_DARK = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_dark" ) );
|
||||
private static final Material TEXTURE_MEDIUM = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_medium" ) );
|
||||
private static final Material TEXTURE_BRIGHT = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/color_applicator_tip_bright" ) );
|
||||
private static final Material TEXTURE_DARK = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_dark"));
|
||||
private static final Material TEXTURE_MEDIUM = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_medium"));
|
||||
private static final Material TEXTURE_BRIGHT = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "item/color_applicator_tip_bright"));
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Arrays.asList( TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK );
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Arrays.asList(TEXTURE_DARK, TEXTURE_MEDIUM, TEXTURE_DARK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
|
||||
TextureAtlasSprite texDark = spriteGetter.apply( TEXTURE_DARK );
|
||||
TextureAtlasSprite texMedium = spriteGetter.apply( TEXTURE_MEDIUM );
|
||||
TextureAtlasSprite texBright = spriteGetter.apply( TEXTURE_BRIGHT );
|
||||
TextureAtlasSprite texDark = spriteGetter.apply(TEXTURE_DARK);
|
||||
TextureAtlasSprite texMedium = spriteGetter.apply(TEXTURE_MEDIUM);
|
||||
TextureAtlasSprite texBright = spriteGetter.apply(TEXTURE_BRIGHT);
|
||||
|
||||
return new ColorApplicatorBakedModel( baseModel, modelTransform, texDark, texMedium, texBright );
|
||||
}
|
||||
return new ColorApplicatorBakedModel(baseModel, modelTransform, texDark, texMedium, texBright);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.api.definitions.IItems;
|
||||
import appeng.block.storage.DriveSlotCellType;
|
||||
import appeng.block.storage.DriveSlotsState;
|
||||
import appeng.client.render.DelegateBakedModel;
|
||||
import appeng.core.Api;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
@@ -34,98 +36,92 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import appeng.api.definitions.IItems;
|
||||
import appeng.block.storage.DriveSlotCellType;
|
||||
import appeng.block.storage.DriveSlotsState;
|
||||
import appeng.client.render.DelegateBakedModel;
|
||||
import appeng.core.Api;
|
||||
|
||||
public class DriveBakedModel extends DelegateBakedModel {
|
||||
private final Map<DriveSlotCellType, IBakedModel> bakedCells;
|
||||
|
||||
public class DriveBakedModel extends DelegateBakedModel
|
||||
{
|
||||
private final Map<DriveSlotCellType, IBakedModel> bakedCells;
|
||||
public DriveBakedModel(IBakedModel bakedBase, Map<DriveSlotCellType, IBakedModel> bakedCells) {
|
||||
super(bakedBase);
|
||||
this.bakedCells = bakedCells;
|
||||
}
|
||||
|
||||
public DriveBakedModel( IBakedModel bakedBase, Map<DriveSlotCellType, IBakedModel> bakedCells )
|
||||
{
|
||||
super(bakedBase);
|
||||
this.bakedCells = bakedCells;
|
||||
}
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand,
|
||||
@Nonnull IModelData extraData) {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull Random rand, @Nonnull IModelData extraData) {
|
||||
List<BakedQuad> result = new ArrayList<>(super.getQuads(state, side, rand, extraData));
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>(super.getQuads(state, side, rand, extraData));
|
||||
if (!(extraData instanceof DriveModelData)) {
|
||||
return result;
|
||||
}
|
||||
DriveModelData driveModelData = (DriveModelData) extraData;
|
||||
|
||||
if (!(extraData instanceof DriveModelData)) {
|
||||
return result;
|
||||
}
|
||||
DriveModelData driveModelData = (DriveModelData) extraData;
|
||||
DriveSlotsState slotsState = driveModelData.getSlotsState();
|
||||
|
||||
DriveSlotsState slotsState = driveModelData.getSlotsState();
|
||||
if (side == null && slotsState != null) {
|
||||
for (int row = 0; row < 5; row++) {
|
||||
for (int col = 0; col < 2; col++) {
|
||||
Matrix4f transform = new Matrix4f();
|
||||
|
||||
if( side == null && slotsState != null )
|
||||
{
|
||||
for( int row = 0; row < 5; row++ )
|
||||
{
|
||||
for( int col = 0; col < 2; col++ )
|
||||
{
|
||||
Matrix4f transform = new Matrix4f();
|
||||
// Position this drive model copy at the correct slot. The transform is based on
|
||||
// the
|
||||
// cell-model being in slot 0,0 at the top left of the drive.
|
||||
float xOffset = -col * 7 / 16.0f;
|
||||
float yOffset = -row * 3 / 16.0f;
|
||||
transform.setTranslation(xOffset, yOffset, 0);
|
||||
|
||||
// Position this drive model copy at the correct slot. The transform is based on the
|
||||
// cell-model being in slot 0,0 at the top left of the drive.
|
||||
float xOffset = -col * 7 / 16.0f;
|
||||
float yOffset = -row * 3 / 16.0f;
|
||||
transform.setTranslation( xOffset, yOffset, 0 );
|
||||
int slot = row * 2 + col;
|
||||
|
||||
int slot = row * 2 + col;
|
||||
// Add the drive chassis
|
||||
Item cell = slotsState.getCell(slot);
|
||||
IBakedModel cellChassisModel = getCellChassisModel(cell);
|
||||
addModel(state, rand, extraData, result, cellChassisModel, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the drive chassis
|
||||
Item cell = slotsState.getCell(slot);
|
||||
IBakedModel cellChassisModel = getCellChassisModel(cell);
|
||||
addModel(state, rand, extraData, result, cellChassisModel, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
// We have faces inside the chassis that are facing east, but should not receive
|
||||
// ambient occlusion from the east-side, but sadly this cannot be fine-tuned on
|
||||
// a
|
||||
// face-by-face basis.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
// We have faces inside the chassis that are facing east, but should not receive
|
||||
// ambient occlusion from the east-side, but sadly this cannot be fine-tuned on a
|
||||
// face-by-face basis.
|
||||
return false;
|
||||
}
|
||||
// Determine which drive chassis to show based on the used cell
|
||||
private IBakedModel getCellChassisModel(Item cell) {
|
||||
IItems items = Api.INSTANCE.definitions().items();
|
||||
if (cell == null) {
|
||||
return bakedCells.get(DriveSlotCellType.EMPTY);
|
||||
} else if (items.fluidCell1k().item() == cell || items.fluidCell4k().item() == cell
|
||||
|| items.fluidCell16k().item() == cell || items.fluidCell64k().item() == cell) {
|
||||
return bakedCells.get(DriveSlotCellType.FLUID);
|
||||
} else {
|
||||
// Fall back to an item model
|
||||
return bakedCells.get(DriveSlotCellType.ITEM);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which drive chassis to show based on the used cell
|
||||
private IBakedModel getCellChassisModel(Item cell) {
|
||||
IItems items = Api.INSTANCE.definitions().items();
|
||||
if (cell == null) {
|
||||
return bakedCells.get(DriveSlotCellType.EMPTY);
|
||||
} else if (items.fluidCell1k().item() == cell
|
||||
|| items.fluidCell4k().item() == cell
|
||||
|| items.fluidCell16k().item() == cell
|
||||
|| items.fluidCell64k().item() == cell) {
|
||||
return bakedCells.get(DriveSlotCellType.FLUID);
|
||||
} else {
|
||||
// Fall back to an item model
|
||||
return bakedCells.get(DriveSlotCellType.ITEM);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addModel(@Nullable BlockState state, @Nonnull Random rand, @Nonnull IModelData extraData, List<BakedQuad> result, IBakedModel bakedCell, Matrix4f transform) {
|
||||
MatrixVertexTransformer transformer = new MatrixVertexTransformer( transform );
|
||||
for( BakedQuad bakedQuad : bakedCell.getQuads( state, null, rand, extraData ) )
|
||||
{
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
transformer.setParent( builder );
|
||||
transformer.setVertexFormat( builder.getVertexFormat() );
|
||||
bakedQuad.pipe( transformer );
|
||||
result.add( builder.build() );
|
||||
}
|
||||
}
|
||||
private static void addModel(@Nullable BlockState state, @Nonnull Random rand, @Nonnull IModelData extraData,
|
||||
List<BakedQuad> result, IBakedModel bakedCell, Matrix4f transform) {
|
||||
MatrixVertexTransformer transformer = new MatrixVertexTransformer(transform);
|
||||
for (BakedQuad bakedQuad : bakedCell.getQuads(state, null, rand, extraData)) {
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
transformer.setParent(builder);
|
||||
transformer.setVertexFormat(builder.getVertexFormat());
|
||||
bakedQuad.pipe(transformer);
|
||||
result.add(builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,56 +18,56 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
import appeng.block.storage.DriveSlotCellType;
|
||||
import appeng.block.storage.DriveSlotState;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import appeng.block.storage.DriveSlotCellType;
|
||||
import appeng.block.storage.DriveSlotState;
|
||||
|
||||
public class DriveModel implements IModelGeometry<DriveModel>
|
||||
{
|
||||
public class DriveModel implements IModelGeometry<DriveModel> {
|
||||
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation( "appliedenergistics2:block/drive/drive_base" );
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation(
|
||||
"appliedenergistics2:block/drive/drive_base");
|
||||
|
||||
private static final Map<DriveSlotCellType, ResourceLocation> MODELS_CELLS = ImmutableMap.of(
|
||||
DriveSlotCellType.EMPTY, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_empty" ),
|
||||
DriveSlotCellType.ITEM, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_items" ),
|
||||
DriveSlotCellType.FLUID, new ResourceLocation( "appliedenergistics2:block/drive/drive_cell_fluids" )
|
||||
);
|
||||
private static final Map<DriveSlotCellType, ResourceLocation> MODELS_CELLS = ImmutableMap.of(
|
||||
DriveSlotCellType.EMPTY, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_empty"),
|
||||
DriveSlotCellType.ITEM, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_items"),
|
||||
DriveSlotCellType.FLUID, new ResourceLocation("appliedenergistics2:block/drive/drive_cell_fluids"));
|
||||
|
||||
public static final Set<ResourceLocation> DEPENDENCIES = ImmutableSet.<ResourceLocation>builder()
|
||||
.addAll(MODELS_CELLS.values())
|
||||
.add(MODEL_BASE)
|
||||
.build();
|
||||
public static final Set<ResourceLocation> DEPENDENCIES = ImmutableSet.<ResourceLocation>builder()
|
||||
.addAll(MODELS_CELLS.values()).add(MODEL_BASE).build();
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
EnumMap<DriveSlotCellType, IBakedModel> cellModels = new EnumMap<>( DriveSlotCellType.class );
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
EnumMap<DriveSlotCellType, IBakedModel> cellModels = new EnumMap<>(DriveSlotCellType.class);
|
||||
|
||||
// Load the base model and the model for each cell state.
|
||||
for( DriveSlotCellType cellType : MODELS_CELLS.keySet() )
|
||||
{
|
||||
IBakedModel cellModel = bakery.getBakedModel( MODELS_CELLS.get( cellType ), modelTransform, spriteGetter );
|
||||
cellModels.put( cellType, cellModel );
|
||||
}
|
||||
// Load the base model and the model for each cell state.
|
||||
for (DriveSlotCellType cellType : MODELS_CELLS.keySet()) {
|
||||
IBakedModel cellModel = bakery.getBakedModel(MODELS_CELLS.get(cellType), modelTransform, spriteGetter);
|
||||
cellModels.put(cellType, cellModel);
|
||||
}
|
||||
|
||||
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
|
||||
return new DriveBakedModel( baseModel, cellModels );
|
||||
}
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
return new DriveBakedModel(baseModel, cellModels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
import appeng.block.storage.DriveSlotsState;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
import appeng.block.storage.DriveSlotsState;
|
||||
|
||||
public class DriveModelData extends AEModelData {
|
||||
|
||||
@@ -29,9 +32,12 @@ public class DriveModelData extends AEModelData {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
if (!super.equals(o))
|
||||
return false;
|
||||
DriveModelData that = (DriveModelData) o;
|
||||
return slotsState.equals(that.slotsState);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
@@ -41,9 +40,6 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import appeng.decorative.solid.BlockQuartzGlass;
|
||||
import appeng.decorative.solid.GlassState;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.ILightReader;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
@@ -52,304 +48,277 @@ import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
import appeng.decorative.solid.BlockQuartzGlass;
|
||||
import appeng.decorative.solid.GlassState;
|
||||
|
||||
class GlassBakedModel implements IDynamicBakedModel
|
||||
{
|
||||
class GlassBakedModel implements IDynamicBakedModel {
|
||||
|
||||
// This unlisted property is used to determine the actual block that should be rendered
|
||||
public static final ModelProperty<GlassState> GLASS_STATE = new ModelProperty<>();
|
||||
// This unlisted property is used to determine the actual block that should be
|
||||
// rendered
|
||||
public static final ModelProperty<GlassState> GLASS_STATE = new ModelProperty<>();
|
||||
|
||||
private static final byte[][][] OFFSETS = generateOffsets();
|
||||
private static final byte[][][] OFFSETS = generateOffsets();
|
||||
|
||||
// Alternating textures based on position
|
||||
static final Material TEXTURE_A = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_a" ));
|
||||
static final Material TEXTURE_B = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_b" ));
|
||||
static final Material TEXTURE_C = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_c" ));
|
||||
static final Material TEXTURE_D = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_d" ));
|
||||
// Alternating textures based on position
|
||||
static final Material TEXTURE_A = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_a"));
|
||||
static final Material TEXTURE_B = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_b"));
|
||||
static final Material TEXTURE_C = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_c"));
|
||||
static final Material TEXTURE_D = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_d"));
|
||||
|
||||
// Frame texture
|
||||
static final Material[] TEXTURES_FRAME = generateTexturesFrame();
|
||||
// Frame texture
|
||||
static final Material[] TEXTURES_FRAME = generateTexturesFrame();
|
||||
|
||||
// Generates the required textures for the frame
|
||||
private static Material[] generateTexturesFrame()
|
||||
{
|
||||
return IntStream.range( 1, 16 )
|
||||
.mapToObj( Integer::toBinaryString )
|
||||
.map( s -> Strings.padStart( s, 4, '0' ) )
|
||||
.map( s -> new ResourceLocation( "appliedenergistics2:block/glass/quartz_glass_frame" + s ) )
|
||||
.map( rl -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, rl) )
|
||||
.toArray( Material[]::new );
|
||||
}
|
||||
// Generates the required textures for the frame
|
||||
private static Material[] generateTexturesFrame() {
|
||||
return IntStream.range(1, 16).mapToObj(Integer::toBinaryString).map(s -> Strings.padStart(s, 4, '0'))
|
||||
.map(s -> new ResourceLocation("appliedenergistics2:block/glass/quartz_glass_frame" + s))
|
||||
.map(rl -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, rl)).toArray(Material[]::new);
|
||||
}
|
||||
|
||||
private final TextureAtlasSprite[] glassTextures;
|
||||
private final TextureAtlasSprite[] glassTextures;
|
||||
|
||||
private final TextureAtlasSprite[] frameTextures;
|
||||
private final TextureAtlasSprite[] frameTextures;
|
||||
|
||||
public GlassBakedModel( Function<Material, TextureAtlasSprite> bakedTextureGetter )
|
||||
{
|
||||
this.glassTextures = new TextureAtlasSprite[] {
|
||||
bakedTextureGetter.apply( TEXTURE_A ),
|
||||
bakedTextureGetter.apply( TEXTURE_B ),
|
||||
bakedTextureGetter.apply( TEXTURE_C ),
|
||||
bakedTextureGetter.apply( TEXTURE_D )
|
||||
};
|
||||
public GlassBakedModel(Function<Material, TextureAtlasSprite> bakedTextureGetter) {
|
||||
this.glassTextures = new TextureAtlasSprite[] { bakedTextureGetter.apply(TEXTURE_A),
|
||||
bakedTextureGetter.apply(TEXTURE_B), bakedTextureGetter.apply(TEXTURE_C),
|
||||
bakedTextureGetter.apply(TEXTURE_D) };
|
||||
|
||||
// The first frame texture would be empty, so we simply leave it set to null here
|
||||
this.frameTextures = new TextureAtlasSprite[16];
|
||||
for( int i = 0; i < TEXTURES_FRAME.length; i++ )
|
||||
{
|
||||
this.frameTextures[1 + i] = bakedTextureGetter.apply( TEXTURES_FRAME[i] );
|
||||
}
|
||||
}
|
||||
// The first frame texture would be empty, so we simply leave it set to null
|
||||
// here
|
||||
this.frameTextures = new TextureAtlasSprite[16];
|
||||
for (int i = 0; i < TEXTURES_FRAME.length; i++) {
|
||||
this.frameTextures[1 + i] = bakedTextureGetter.apply(TEXTURES_FRAME[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData )
|
||||
{
|
||||
if( side == null )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData extraData) {
|
||||
if (side == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final GlassState glassState = extraData.getData( GLASS_STATE );
|
||||
final GlassState glassState = extraData.getData(GLASS_STATE);
|
||||
|
||||
if( glassState == null )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (glassState == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// TODO: This could just use the Random instance we're given...
|
||||
final int cx = Math.abs( glassState.getX() % 10 );
|
||||
final int cy = Math.abs( glassState.getY() % 10 );
|
||||
final int cz = Math.abs( glassState.getZ() % 10 );
|
||||
// TODO: This could just use the Random instance we're given...
|
||||
final int cx = Math.abs(glassState.getX() % 10);
|
||||
final int cy = Math.abs(glassState.getY() % 10);
|
||||
final int cz = Math.abs(glassState.getZ() % 10);
|
||||
|
||||
int u = OFFSETS[cx][cy][cz] % 4;
|
||||
int v = OFFSETS[9 - cx][9 - cy][9 - cz] % 4;
|
||||
int u = OFFSETS[cx][cy][cz] % 4;
|
||||
int v = OFFSETS[9 - cx][9 - cy][9 - cz] % 4;
|
||||
|
||||
int texIdx = Math.abs( ( OFFSETS[cx][cy][cz] + ( glassState.getX() + glassState.getY() + glassState.getZ() ) ) % 4 );
|
||||
int texIdx = Math.abs((OFFSETS[cx][cy][cz] + (glassState.getX() + glassState.getY() + glassState.getZ())) % 4);
|
||||
|
||||
if( texIdx < 2 )
|
||||
{
|
||||
u /= 2;
|
||||
v /= 2;
|
||||
}
|
||||
if (texIdx < 2) {
|
||||
u /= 2;
|
||||
v /= 2;
|
||||
}
|
||||
|
||||
final TextureAtlasSprite glassTexture = this.glassTextures[texIdx];
|
||||
final TextureAtlasSprite glassTexture = this.glassTextures[texIdx];
|
||||
|
||||
// Render the glass side
|
||||
final List<BakedQuad> quads = new ArrayList<>( 5 ); // At most 5
|
||||
// Render the glass side
|
||||
final List<BakedQuad> quads = new ArrayList<>(5); // At most 5
|
||||
|
||||
final List<Vec3d> corners = RenderHelper.getFaceCorners( side );
|
||||
quads.add( this.createQuad( side, corners, glassTexture, u, v ) );
|
||||
final List<Vec3d> corners = RenderHelper.getFaceCorners(side);
|
||||
quads.add(this.createQuad(side, corners, glassTexture, u, v));
|
||||
|
||||
/*
|
||||
* This needs some explanation:
|
||||
* The bit-field contains 4-bits, one for each direction that a frame may be drawn.
|
||||
* Converted to a number, the bit-field is then used as an index into the list of
|
||||
* frame textures, which have been created in such a way that their filenames
|
||||
* indicate, in which directions they contain borders.
|
||||
* i.e. bitmask = 0101 means a border should be drawn up and down (in terms of u,v space).
|
||||
* Converted to a number, this bitmask is 5. So the texture at index 5 is used.
|
||||
* That texture had "0101" in its filename to indicate this.
|
||||
*/
|
||||
final int edgeBitmask = makeBitmask( glassState, side );
|
||||
final TextureAtlasSprite sideSprite = this.frameTextures[edgeBitmask];
|
||||
/*
|
||||
* This needs some explanation: The bit-field contains 4-bits, one for each
|
||||
* direction that a frame may be drawn. Converted to a number, the bit-field is
|
||||
* then used as an index into the list of frame textures, which have been
|
||||
* created in such a way that their filenames indicate, in which directions they
|
||||
* contain borders. i.e. bitmask = 0101 means a border should be drawn up and
|
||||
* down (in terms of u,v space). Converted to a number, this bitmask is 5. So
|
||||
* the texture at index 5 is used. That texture had "0101" in its filename to
|
||||
* indicate this.
|
||||
*/
|
||||
final int edgeBitmask = makeBitmask(glassState, side);
|
||||
final TextureAtlasSprite sideSprite = this.frameTextures[edgeBitmask];
|
||||
|
||||
if( sideSprite != null )
|
||||
{
|
||||
quads.add( this.createQuad( side, corners, sideSprite, 0, 0 ) );
|
||||
}
|
||||
if (sideSprite != null) {
|
||||
quads.add(this.createQuad(side, corners, sideSprite, 0, 0));
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
// TODO: Forge: Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
// TODO: Forge: Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the bitmask that indicates, in which directions (in terms of u,v space) a border should be drawn.
|
||||
*/
|
||||
private static int makeBitmask( GlassState state, Direction side )
|
||||
{
|
||||
switch( side )
|
||||
{
|
||||
case DOWN:
|
||||
return makeBitmask( state, Direction.SOUTH, Direction.EAST, Direction.NORTH, Direction.WEST );
|
||||
case UP:
|
||||
return makeBitmask( state, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST );
|
||||
case NORTH:
|
||||
return makeBitmask( state, Direction.UP, Direction.WEST, Direction.DOWN, Direction.EAST );
|
||||
case SOUTH:
|
||||
return makeBitmask( state, Direction.UP, Direction.EAST, Direction.DOWN, Direction.WEST );
|
||||
case WEST:
|
||||
return makeBitmask( state, Direction.UP, Direction.SOUTH, Direction.DOWN, Direction.NORTH );
|
||||
case EAST:
|
||||
return makeBitmask( state, Direction.UP, Direction.NORTH, Direction.DOWN, Direction.SOUTH );
|
||||
default:
|
||||
throw new IllegalArgumentException( "Unsupported side!" );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates the bitmask that indicates, in which directions (in terms of u,v
|
||||
* space) a border should be drawn.
|
||||
*/
|
||||
private static int makeBitmask(GlassState state, Direction side) {
|
||||
switch (side) {
|
||||
case DOWN:
|
||||
return makeBitmask(state, Direction.SOUTH, Direction.EAST, Direction.NORTH, Direction.WEST);
|
||||
case UP:
|
||||
return makeBitmask(state, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.EAST);
|
||||
case NORTH:
|
||||
return makeBitmask(state, Direction.UP, Direction.WEST, Direction.DOWN, Direction.EAST);
|
||||
case SOUTH:
|
||||
return makeBitmask(state, Direction.UP, Direction.EAST, Direction.DOWN, Direction.WEST);
|
||||
case WEST:
|
||||
return makeBitmask(state, Direction.UP, Direction.SOUTH, Direction.DOWN, Direction.NORTH);
|
||||
case EAST:
|
||||
return makeBitmask(state, Direction.UP, Direction.NORTH, Direction.DOWN, Direction.SOUTH);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported side!");
|
||||
}
|
||||
}
|
||||
|
||||
private static int makeBitmask( GlassState state, Direction up, Direction right, Direction down, Direction left )
|
||||
{
|
||||
private static int makeBitmask(GlassState state, Direction up, Direction right, Direction down, Direction left) {
|
||||
|
||||
int bitmask = 0;
|
||||
int bitmask = 0;
|
||||
|
||||
if( !state.isFlushWith( up ) )
|
||||
{
|
||||
bitmask |= 1;
|
||||
}
|
||||
if( !state.isFlushWith( right ) )
|
||||
{
|
||||
bitmask |= 2;
|
||||
}
|
||||
if( !state.isFlushWith( down ) )
|
||||
{
|
||||
bitmask |= 4;
|
||||
}
|
||||
if( !state.isFlushWith( left ) )
|
||||
{
|
||||
bitmask |= 8;
|
||||
}
|
||||
return bitmask;
|
||||
}
|
||||
if (!state.isFlushWith(up)) {
|
||||
bitmask |= 1;
|
||||
}
|
||||
if (!state.isFlushWith(right)) {
|
||||
bitmask |= 2;
|
||||
}
|
||||
if (!state.isFlushWith(down)) {
|
||||
bitmask |= 4;
|
||||
}
|
||||
if (!state.isFlushWith(left)) {
|
||||
bitmask |= 8;
|
||||
}
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
private BakedQuad createQuad( Direction side, List<Vec3d> corners, TextureAtlasSprite sprite, float uOffset, float vOffset )
|
||||
{
|
||||
return this.createQuad( side, corners.get( 0 ), corners.get( 1 ), corners.get( 2 ), corners.get( 3 ), sprite, uOffset, vOffset );
|
||||
}
|
||||
private BakedQuad createQuad(Direction side, List<Vec3d> corners, TextureAtlasSprite sprite, float uOffset,
|
||||
float vOffset) {
|
||||
return this.createQuad(side, corners.get(0), corners.get(1), corners.get(2), corners.get(3), sprite, uOffset,
|
||||
vOffset);
|
||||
}
|
||||
|
||||
private BakedQuad createQuad( Direction side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, TextureAtlasSprite sprite, float uOffset, float vOffset )
|
||||
{
|
||||
Vec3d normal = new Vec3d( side.getDirectionVec() );
|
||||
private BakedQuad createQuad(Direction side, Vec3d c1, Vec3d c2, Vec3d c3, Vec3d c4, TextureAtlasSprite sprite,
|
||||
float uOffset, float vOffset) {
|
||||
Vec3d normal = new Vec3d(side.getDirectionVec());
|
||||
|
||||
// Apply the u,v shift.
|
||||
// This mirrors the logic from OffsetIcon from 1.7
|
||||
float u1 = MathHelper.clamp( 0 - uOffset, 0, 16 );
|
||||
float u2 = MathHelper.clamp( 16 - uOffset, 0, 16 );
|
||||
float v1 = MathHelper.clamp( 0 - vOffset, 0, 16 );
|
||||
float v2 = MathHelper.clamp( 16 - vOffset, 0, 16 );
|
||||
// Apply the u,v shift.
|
||||
// This mirrors the logic from OffsetIcon from 1.7
|
||||
float u1 = MathHelper.clamp(0 - uOffset, 0, 16);
|
||||
float u2 = MathHelper.clamp(16 - uOffset, 0, 16);
|
||||
float v1 = MathHelper.clamp(0 - vOffset, 0, 16);
|
||||
float v2 = MathHelper.clamp(16 - vOffset, 0, 16);
|
||||
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||
builder.setQuadOrientation(side);
|
||||
this.putVertex( builder, normal, c1.x, c1.y, c1.z, sprite, u1, v1 );
|
||||
this.putVertex( builder, normal, c2.x, c2.y, c2.z, sprite, u1, v2 );
|
||||
this.putVertex( builder, normal, c3.x, c3.y, c3.z, sprite, u2, v2 );
|
||||
this.putVertex( builder, normal, c4.x, c4.y, c4.z, sprite, u2, v1 );
|
||||
return builder.build();
|
||||
}
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||
builder.setQuadOrientation(side);
|
||||
this.putVertex(builder, normal, c1.x, c1.y, c1.z, sprite, u1, v1);
|
||||
this.putVertex(builder, normal, c2.x, c2.y, c2.z, sprite, u1, v2);
|
||||
this.putVertex(builder, normal, c3.x, c3.y, c3.z, sprite, u2, v2);
|
||||
this.putVertex(builder, normal, c4.x, c4.y, c4.z, sprite, u2, v1);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is as complicated as it is, because the order in which we push data into the vertexbuffer actually
|
||||
* has to be precisely the order
|
||||
* in which the vertex elements had been declared in the vertex format.
|
||||
*/
|
||||
private void putVertex( BakedQuadBuilder builder, Vec3d normal, double x, double y, double z, TextureAtlasSprite sprite, float u, float v )
|
||||
{
|
||||
VertexFormat vertexFormat = builder.getVertexFormat();
|
||||
for( int e = 0; e < vertexFormat.getElements().size(); e++ )
|
||||
{
|
||||
VertexFormatElement el = vertexFormat.getElements().get(e);
|
||||
switch( el.getUsage() )
|
||||
{
|
||||
case POSITION:
|
||||
builder.put( e, (float) x, (float) y, (float) z, 1.0f );
|
||||
break;
|
||||
case COLOR:
|
||||
builder.put( e, 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
break;
|
||||
case NORMAL:
|
||||
builder.put( e, (float) normal.x, (float) normal.y, (float) normal.z, 0f );
|
||||
break;
|
||||
case UV:
|
||||
if( el.getIndex() == 0 )
|
||||
{
|
||||
u = sprite.getInterpolatedU( u );
|
||||
v = sprite.getInterpolatedV( v );
|
||||
builder.put( e, u, v, 0f, 1f );
|
||||
break;
|
||||
}
|
||||
// Important: Fall through for getIndex() != 0
|
||||
default:
|
||||
builder.put( e );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This method is as complicated as it is, because the order in which we push
|
||||
* data into the vertexbuffer actually has to be precisely the order in which
|
||||
* the vertex elements had been declared in the vertex format.
|
||||
*/
|
||||
private void putVertex(BakedQuadBuilder builder, Vec3d normal, double x, double y, double z,
|
||||
TextureAtlasSprite sprite, float u, float v) {
|
||||
VertexFormat vertexFormat = builder.getVertexFormat();
|
||||
for (int e = 0; e < vertexFormat.getElements().size(); e++) {
|
||||
VertexFormatElement el = vertexFormat.getElements().get(e);
|
||||
switch (el.getUsage()) {
|
||||
case POSITION:
|
||||
builder.put(e, (float) x, (float) y, (float) z, 1.0f);
|
||||
break;
|
||||
case COLOR:
|
||||
builder.put(e, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
break;
|
||||
case NORMAL:
|
||||
builder.put(e, (float) normal.x, (float) normal.y, (float) normal.z, 0f);
|
||||
break;
|
||||
case UV:
|
||||
if (el.getIndex() == 0) {
|
||||
u = sprite.getInterpolatedU(u);
|
||||
v = sprite.getInterpolatedV(v);
|
||||
builder.put(e, u, v, 0f, 1f);
|
||||
break;
|
||||
}
|
||||
// Important: Fall through for getIndex() != 0
|
||||
default:
|
||||
builder.put(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.frameTextures[this.frameTextures.length - 1];
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.frameTextures[this.frameTextures.length - 1];
|
||||
}
|
||||
|
||||
private static byte[][][] generateOffsets()
|
||||
{
|
||||
final Random r = new Random( 924 );
|
||||
final byte[][][] offset = new byte[10][10][10];
|
||||
private static byte[][][] generateOffsets() {
|
||||
final Random r = new Random(924);
|
||||
final byte[][][] offset = new byte[10][10][10];
|
||||
|
||||
for( int x = 0; x < 10; x++ )
|
||||
{
|
||||
for( int y = 0; y < 10; y++ )
|
||||
{
|
||||
r.nextBytes( offset[x][y] );
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 10; x++) {
|
||||
for (int y = 0; y < 10; y++) {
|
||||
r.nextBytes(offset[x][y]);
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull IModelData tileData) {
|
||||
@Nonnull
|
||||
@Override
|
||||
public IModelData getModelData(@Nonnull ILightReader world, @Nonnull BlockPos pos, @Nonnull BlockState state,
|
||||
@Nonnull IModelData tileData) {
|
||||
|
||||
EnumSet<Direction> flushWith = EnumSet.noneOf( Direction.class );
|
||||
// Test every direction for another glass block
|
||||
for( Direction facing : Direction.values() )
|
||||
{
|
||||
if( isGlassBlock( world, pos, facing ) )
|
||||
{
|
||||
flushWith.add( facing );
|
||||
}
|
||||
}
|
||||
EnumSet<Direction> flushWith = EnumSet.noneOf(Direction.class);
|
||||
// Test every direction for another glass block
|
||||
for (Direction facing : Direction.values()) {
|
||||
if (isGlassBlock(world, pos, facing)) {
|
||||
flushWith.add(facing);
|
||||
}
|
||||
}
|
||||
|
||||
GlassState glassState = new GlassState( pos.getX(), pos.getY(), pos.getZ(), flushWith );
|
||||
return new ModelDataMap.Builder()
|
||||
.withInitial(GLASS_STATE, glassState)
|
||||
.build();
|
||||
GlassState glassState = new GlassState(pos.getX(), pos.getY(), pos.getZ(), flushWith);
|
||||
return new ModelDataMap.Builder().withInitial(GLASS_STATE, glassState).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGlassBlock(IBlockReader world, BlockPos pos, Direction facing )
|
||||
{
|
||||
return world.getBlockState( pos.offset( facing ) ).getBlock() instanceof BlockQuartzGlass;
|
||||
}
|
||||
private static boolean isGlassBlock(IBlockReader world, BlockPos pos, Direction facing) {
|
||||
return world.getBlockState(pos.offset(facing)).getBlock() instanceof BlockQuartzGlass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,41 +18,42 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Model class for the connected texture glass model.
|
||||
*/
|
||||
public class GlassModel implements IModelGeometry<GlassModel>
|
||||
{
|
||||
public class GlassModel implements IModelGeometry<GlassModel> {
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
return new GlassBakedModel( spriteGetter );
|
||||
}
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
return new GlassBakedModel(spriteGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return ImmutableSet.<Material>builder()
|
||||
.add(GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B, GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D)
|
||||
.add(GlassBakedModel.TEXTURES_FRAME)
|
||||
.build();
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return ImmutableSet
|
||||
.<Material>builder().add(GlassBakedModel.TEXTURE_A, GlassBakedModel.TEXTURE_B,
|
||||
GlassBakedModel.TEXTURE_C, GlassBakedModel.TEXTURE_D)
|
||||
.add(GlassBakedModel.TEXTURES_FRAME).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Vector4f;
|
||||
@@ -27,147 +28,107 @@ import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.pipeline.QuadGatheringTransformer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Applies an arbitrary transformation matrix to the vertices of a quad.
|
||||
*/
|
||||
final class MatrixVertexTransformer extends QuadGatheringTransformer
|
||||
{
|
||||
final class MatrixVertexTransformer extends QuadGatheringTransformer {
|
||||
|
||||
private final Matrix4f transform;
|
||||
private final Matrix4f transform;
|
||||
|
||||
public MatrixVertexTransformer( Matrix4f transform )
|
||||
{
|
||||
this.transform = transform;
|
||||
}
|
||||
public MatrixVertexTransformer(Matrix4f transform) {
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processQuad()
|
||||
{
|
||||
VertexFormat format = this.parent.getVertexFormat();
|
||||
List<VertexFormatElement> elements = format.getElements();
|
||||
int count = elements.size();
|
||||
@Override
|
||||
protected void processQuad() {
|
||||
VertexFormat format = this.parent.getVertexFormat();
|
||||
List<VertexFormatElement> elements = format.getElements();
|
||||
int count = elements.size();
|
||||
|
||||
for( int v = 0; v < 4; v++ )
|
||||
{
|
||||
for( int e = 0; e < count; e++ )
|
||||
{
|
||||
VertexFormatElement element = elements.get( e );
|
||||
if( element.getUsage() == VertexFormatElement.Usage.POSITION )
|
||||
{
|
||||
this.parent.put( e, this.transform( this.quadData[e][v], element.getElementCount() ) );
|
||||
}
|
||||
else if( element.getUsage() == VertexFormatElement.Usage.NORMAL )
|
||||
{
|
||||
this.parent.put( e, this.transformNormal( this.quadData[e][v] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent.put( e, this.quadData[e][v] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int v = 0; v < 4; v++) {
|
||||
for (int e = 0; e < count; e++) {
|
||||
VertexFormatElement element = elements.get(e);
|
||||
if (element.getUsage() == VertexFormatElement.Usage.POSITION) {
|
||||
this.parent.put(e, this.transform(this.quadData[e][v], element.getElementCount()));
|
||||
} else if (element.getUsage() == VertexFormatElement.Usage.NORMAL) {
|
||||
this.parent.put(e, this.transformNormal(this.quadData[e][v]));
|
||||
} else {
|
||||
this.parent.put(e, this.quadData[e][v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadTint( int tint )
|
||||
{
|
||||
this.parent.setQuadTint( tint );
|
||||
}
|
||||
@Override
|
||||
public void setQuadTint(int tint) {
|
||||
this.parent.setQuadTint(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadOrientation( Direction orientation )
|
||||
{
|
||||
this.parent.setQuadOrientation( orientation );
|
||||
}
|
||||
@Override
|
||||
public void setQuadOrientation(Direction orientation) {
|
||||
this.parent.setQuadOrientation(orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplyDiffuseLighting( boolean diffuse )
|
||||
{
|
||||
this.parent.setApplyDiffuseLighting( diffuse );
|
||||
}
|
||||
@Override
|
||||
public void setApplyDiffuseLighting(boolean diffuse) {
|
||||
this.parent.setApplyDiffuseLighting(diffuse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTexture( TextureAtlasSprite texture )
|
||||
{
|
||||
this.parent.setTexture( texture );
|
||||
}
|
||||
@Override
|
||||
public void setTexture(TextureAtlasSprite texture) {
|
||||
this.parent.setTexture(texture);
|
||||
}
|
||||
|
||||
private float[] transform( float[] fs, int elemCount )
|
||||
{
|
||||
switch( fs.length )
|
||||
{
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f( fs[0], fs[1], fs[2], 1 );
|
||||
vec.setX(vec.getX() - 0.5f);
|
||||
vec.setY(vec.getY() - 0.5f);
|
||||
vec.setZ(vec.getZ() - 0.5f);
|
||||
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
|
||||
vec.setX(vec.getX() + 0.5f);
|
||||
vec.setY(vec.getY() + 0.5f);
|
||||
vec.setZ(vec.getZ() + 0.5f);
|
||||
return new float[] {
|
||||
vec.getX(),
|
||||
vec.getY(),
|
||||
vec.getZ()
|
||||
};
|
||||
case 4:
|
||||
Vector4f vecc = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
|
||||
// Otherwise all translation is lost
|
||||
if( elemCount == 3 )
|
||||
{
|
||||
vecc.setW(1);
|
||||
}
|
||||
vecc.setX(vecc.getX() - 0.5f);
|
||||
vecc.setY(vecc.getY() - 0.5f);
|
||||
vecc.setZ(vecc.getZ() - 0.5f);
|
||||
vecc.transform(this.transform);
|
||||
vecc.setX(vecc.getX() + 0.5f);
|
||||
vecc.setY(vecc.getY() + 0.5f);
|
||||
vecc.setZ(vecc.getZ() + 0.5f);
|
||||
return new float[] {
|
||||
vecc.getX(),
|
||||
vecc.getY(),
|
||||
vecc.getZ(),
|
||||
vecc.getW()
|
||||
};
|
||||
private float[] transform(float[] fs, int elemCount) {
|
||||
switch (fs.length) {
|
||||
case 3:
|
||||
Vector4f vec = new Vector4f(fs[0], fs[1], fs[2], 1);
|
||||
vec.setX(vec.getX() - 0.5f);
|
||||
vec.setY(vec.getY() - 0.5f);
|
||||
vec.setZ(vec.getZ() - 0.5f);
|
||||
vec.transform(this.transform); // FIXME: Check this, we're using a Vec4, input is Vec3
|
||||
vec.setX(vec.getX() + 0.5f);
|
||||
vec.setY(vec.getY() + 0.5f);
|
||||
vec.setZ(vec.getZ() + 0.5f);
|
||||
return new float[] { vec.getX(), vec.getY(), vec.getZ() };
|
||||
case 4:
|
||||
Vector4f vecc = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
|
||||
// Otherwise all translation is lost
|
||||
if (elemCount == 3) {
|
||||
vecc.setW(1);
|
||||
}
|
||||
vecc.setX(vecc.getX() - 0.5f);
|
||||
vecc.setY(vecc.getY() - 0.5f);
|
||||
vecc.setZ(vecc.getZ() - 0.5f);
|
||||
vecc.transform(this.transform);
|
||||
vecc.setX(vecc.getX() + 0.5f);
|
||||
vecc.setY(vecc.getY() + 0.5f);
|
||||
vecc.setZ(vecc.getZ() + 0.5f);
|
||||
return new float[] { vecc.getX(), vecc.getY(), vecc.getZ(), vecc.getW() };
|
||||
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
|
||||
private float[] transformNormal( float[] fs )
|
||||
{
|
||||
Vector4f normal;
|
||||
private float[] transformNormal(float[] fs) {
|
||||
Vector4f normal;
|
||||
|
||||
switch( fs.length )
|
||||
{
|
||||
case 3:
|
||||
normal = new Vector4f( fs[0], fs[1], fs[2], 0 );
|
||||
normal.transform(this.transform);
|
||||
normal.normalize();
|
||||
return new float[] {
|
||||
normal.getX(),
|
||||
normal.getY(),
|
||||
normal.getZ()
|
||||
};
|
||||
switch (fs.length) {
|
||||
case 3:
|
||||
normal = new Vector4f(fs[0], fs[1], fs[2], 0);
|
||||
normal.transform(this.transform);
|
||||
normal.normalize();
|
||||
return new float[] { normal.getX(), normal.getY(), normal.getZ() };
|
||||
|
||||
case 4:
|
||||
normal = new Vector4f( fs[0], fs[1], fs[2], fs[3] );
|
||||
normal.transform(this.transform);
|
||||
normal.normalize();
|
||||
return new float[] {
|
||||
normal.getX(),
|
||||
normal.getY(),
|
||||
normal.getZ(),
|
||||
normal.getW()
|
||||
};
|
||||
case 4:
|
||||
normal = new Vector4f(fs[0], fs[1], fs[2], fs[3]);
|
||||
normal.transform(this.transform);
|
||||
normal.normalize();
|
||||
return new float[] { normal.getX(), normal.getY(), normal.getZ(), normal.getW() };
|
||||
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
@@ -34,187 +34,159 @@ import appeng.api.util.AEColor;
|
||||
import appeng.client.render.cablebus.CubeBuilder;
|
||||
import appeng.core.AELog;
|
||||
|
||||
class MemoryCardBakedModel implements IBakedModel {
|
||||
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] { AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, };
|
||||
|
||||
class MemoryCardBakedModel implements IBakedModel
|
||||
{
|
||||
private static final AEColor[] DEFAULT_COLOR_CODE = new AEColor[] {
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT, AEColor.TRANSPARENT,
|
||||
};
|
||||
private final IBakedModel baseModel;
|
||||
|
||||
private final IBakedModel baseModel;
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
private final TextureAtlasSprite texture;
|
||||
private final AEColor[] colorCode;
|
||||
|
||||
private final AEColor[] colorCode;
|
||||
private final Cache<CacheKey, MemoryCardBakedModel> modelCache;
|
||||
|
||||
private final Cache<CacheKey, MemoryCardBakedModel> modelCache;
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
|
||||
private final ImmutableList<BakedQuad> generalQuads;
|
||||
MemoryCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture) {
|
||||
this(baseModel, texture, DEFAULT_COLOR_CODE, createCache());
|
||||
}
|
||||
|
||||
MemoryCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture )
|
||||
{
|
||||
this( baseModel, texture, DEFAULT_COLOR_CODE, createCache() );
|
||||
}
|
||||
private MemoryCardBakedModel(IBakedModel baseModel, TextureAtlasSprite texture, AEColor[] hash,
|
||||
Cache<CacheKey, MemoryCardBakedModel> modelCache) {
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.colorCode = hash;
|
||||
this.generalQuads = ImmutableList.copyOf(this.buildGeneralQuads());
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
|
||||
private MemoryCardBakedModel( IBakedModel baseModel, TextureAtlasSprite texture, AEColor[] hash, Cache<CacheKey, MemoryCardBakedModel> modelCache )
|
||||
{
|
||||
this.baseModel = baseModel;
|
||||
this.texture = texture;
|
||||
this.colorCode = hash;
|
||||
this.generalQuads = ImmutableList.copyOf( this.buildGeneralQuads() );
|
||||
this.modelCache = modelCache;
|
||||
}
|
||||
private static Cache<CacheKey, MemoryCardBakedModel> createCache() {
|
||||
return CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
}
|
||||
|
||||
private static Cache<CacheKey, MemoryCardBakedModel> createCache()
|
||||
{
|
||||
return CacheBuilder.newBuilder().maximumSize( 100 ).build();
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand) {
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand )
|
||||
{
|
||||
List<BakedQuad> quads = this.baseModel.getQuads(state, side, rand, EmptyModelData.INSTANCE);
|
||||
|
||||
List<BakedQuad> quads = this.baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE );
|
||||
if (side != null) {
|
||||
return quads;
|
||||
}
|
||||
|
||||
if( side != null )
|
||||
{
|
||||
return quads;
|
||||
}
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size() + this.generalQuads.size());
|
||||
result.addAll(quads);
|
||||
result.addAll(this.generalQuads);
|
||||
return result;
|
||||
}
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>( quads.size() + this.generalQuads.size() );
|
||||
result.addAll( quads );
|
||||
result.addAll( this.generalQuads );
|
||||
return result;
|
||||
}
|
||||
private List<BakedQuad> buildGeneralQuads() {
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
|
||||
private List<BakedQuad> buildGeneralQuads()
|
||||
{
|
||||
CubeBuilder builder = new CubeBuilder();
|
||||
builder.setTexture(this.texture);
|
||||
|
||||
builder.setTexture( this.texture );
|
||||
for (int x = 0; x < 4; x++) {
|
||||
for (int y = 0; y < 2; y++) {
|
||||
final AEColor color = this.colorCode[x + y * 4];
|
||||
|
||||
for( int x = 0; x < 4; x++ )
|
||||
{
|
||||
for( int y = 0; y < 2; y++ )
|
||||
{
|
||||
final AEColor color = this.colorCode[x + y * 4];
|
||||
builder.setColorRGB(color.mediumVariant);
|
||||
builder.addCube(7 + x, 8 + (1 - y), 7.5f, 7 + x + 1, 8 + (1 - y) + 1, 8.5f);
|
||||
}
|
||||
}
|
||||
|
||||
builder.setColorRGB( color.mediumVariant );
|
||||
builder.addCube( 7 + x, 8 + ( 1 - y ), 7.5f, 7 + x + 1, 8 + ( 1 - y ) + 1, 8.5f );
|
||||
}
|
||||
}
|
||||
return builder.getOutput();
|
||||
}
|
||||
|
||||
return builder.getOutput();
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return this.baseModel.isAmbientOcclusion();
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return this.baseModel.isGui3d();
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return false;//TODO
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return this.baseModel.isBuiltInRenderer();
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.baseModel.getParticleTexture();
|
||||
}
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return this.baseModel.getItemCameraTransforms();
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return new ItemOverrideList() {
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, World world,
|
||||
LivingEntity entity) {
|
||||
try {
|
||||
if (stack.getItem() instanceof IMemoryCard) {
|
||||
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
|
||||
final AEColor[] colors = memoryCard.getColorCode(stack);
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return new ItemOverrideList()
|
||||
{
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides( IBakedModel originalModel, ItemStack stack, World world, LivingEntity entity )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( stack.getItem() instanceof IMemoryCard )
|
||||
{
|
||||
final IMemoryCard memoryCard = (IMemoryCard) stack.getItem();
|
||||
final AEColor[] colors = memoryCard.getColorCode( stack );
|
||||
return MemoryCardBakedModel.this.modelCache.get(new CacheKey(colors),
|
||||
() -> new MemoryCardBakedModel(MemoryCardBakedModel.this.baseModel,
|
||||
MemoryCardBakedModel.this.texture, colors,
|
||||
MemoryCardBakedModel.this.modelCache));
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
AELog.error(e);
|
||||
}
|
||||
|
||||
return MemoryCardBakedModel.this.modelCache.get( new CacheKey( colors ),
|
||||
() -> new MemoryCardBakedModel( MemoryCardBakedModel.this.baseModel, MemoryCardBakedModel.this.texture, colors, MemoryCardBakedModel.this.modelCache ) );
|
||||
}
|
||||
}
|
||||
catch( ExecutionException e )
|
||||
{
|
||||
AELog.error( e );
|
||||
}
|
||||
return MemoryCardBakedModel.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return MemoryCardBakedModel.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public IBakedModel handlePerspective(ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat) {
|
||||
baseModel.handlePerspective(cameraTransformType, mat);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel handlePerspective( ItemCameraTransforms.TransformType cameraTransformType, MatrixStack mat )
|
||||
{
|
||||
baseModel.handlePerspective( cameraTransformType, mat );
|
||||
return this;
|
||||
}
|
||||
private static class CacheKey {
|
||||
private final AEColor[] key;
|
||||
|
||||
private static class CacheKey
|
||||
{
|
||||
private final AEColor[] key;
|
||||
CacheKey(AEColor[] key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
CacheKey( AEColor[] key )
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(this.key);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode( this.key );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj )
|
||||
{
|
||||
if( this == obj )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( obj == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( this.getClass() != obj.getClass() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CacheKey other = (CacheKey) obj;
|
||||
return Arrays.equals( this.key, other.key );
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
CacheKey other = (CacheKey) obj;
|
||||
return Arrays.equals(this.key, other.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
@@ -13,36 +13,37 @@ import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.AtlasTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
/**
|
||||
* Model wrapper for the memory card item model, which combines a base card layer with a "visual hash" of the part/tile.
|
||||
* Model wrapper for the memory card item model, which combines a base card
|
||||
* layer with a "visual hash" of the part/tile.
|
||||
*/
|
||||
public class MemoryCardModel implements IModelGeometry<MemoryCardModel>
|
||||
{
|
||||
public class MemoryCardModel implements IModelGeometry<MemoryCardModel> {
|
||||
|
||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/memory_card_base" );
|
||||
private static final Material TEXTURE = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "item/memory_card_hash" ) );
|
||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation(AppEng.MOD_ID, "item/memory_card_base");
|
||||
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "item/memory_card_hash"));
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
|
||||
{
|
||||
return Collections.singleton( TEXTURE );
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.singleton(TEXTURE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
TextureAtlasSprite texture = spriteGetter.apply( TEXTURE );
|
||||
@Nullable
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
TextureAtlasSprite texture = spriteGetter.apply(TEXTURE);
|
||||
|
||||
IBakedModel baseModel = bakery.getBakedModel( MODEL_BASE, modelTransform, spriteGetter );
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
|
||||
return new MemoryCardBakedModel( baseModel, texture );
|
||||
}
|
||||
return new MemoryCardBakedModel(baseModel, texture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -28,69 +27,62 @@ import com.google.common.collect.Lists;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
|
||||
// TODO: Investigate use of CubeBuilder instead
|
||||
final class RenderHelper
|
||||
{
|
||||
final class RenderHelper {
|
||||
|
||||
private static EnumMap<Direction, List<Vec3d>> cornersForFacing = generateCornersForFacings();
|
||||
private static EnumMap<Direction, List<Vec3d>> cornersForFacing = generateCornersForFacings();
|
||||
|
||||
private RenderHelper()
|
||||
{
|
||||
private RenderHelper() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static List<Vec3d> getFaceCorners( Direction side )
|
||||
{
|
||||
return cornersForFacing.get( side );
|
||||
}
|
||||
static List<Vec3d> getFaceCorners(Direction side) {
|
||||
return cornersForFacing.get(side);
|
||||
}
|
||||
|
||||
private static EnumMap<Direction, List<Vec3d>> generateCornersForFacings()
|
||||
{
|
||||
EnumMap<Direction, List<Vec3d>> result = new EnumMap<>( Direction.class );
|
||||
private static EnumMap<Direction, List<Vec3d>> generateCornersForFacings() {
|
||||
EnumMap<Direction, List<Vec3d>> result = new EnumMap<>(Direction.class);
|
||||
|
||||
for( Direction facing : Direction.values() )
|
||||
{
|
||||
List<Vec3d> corners;
|
||||
for (Direction facing : Direction.values()) {
|
||||
List<Vec3d> corners;
|
||||
|
||||
float offset = ( facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE ) ? 0 : 1;
|
||||
float offset = (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ? 0 : 1;
|
||||
|
||||
switch( facing.getAxis() )
|
||||
{
|
||||
default:
|
||||
case X:
|
||||
corners = Lists.newArrayList( new Vec3d( offset, 1, 1 ), new Vec3d( offset, 0, 1 ), new Vec3d( offset, 0, 0 ), new Vec3d( offset, 1, 0 ) );
|
||||
break;
|
||||
case Y:
|
||||
corners = Lists.newArrayList( new Vec3d( 1, offset, 1 ), new Vec3d( 1, offset, 0 ), new Vec3d( 0, offset, 0 ), new Vec3d( 0, offset, 1 ) );
|
||||
break;
|
||||
case Z:
|
||||
corners = Lists.newArrayList( new Vec3d( 0, 1, offset ), new Vec3d( 0, 0, offset ), new Vec3d( 1, 0, offset ), new Vec3d( 1, 1, offset ) );
|
||||
break;
|
||||
}
|
||||
switch (facing.getAxis()) {
|
||||
default:
|
||||
case X:
|
||||
corners = Lists.newArrayList(new Vec3d(offset, 1, 1), new Vec3d(offset, 0, 1),
|
||||
new Vec3d(offset, 0, 0), new Vec3d(offset, 1, 0));
|
||||
break;
|
||||
case Y:
|
||||
corners = Lists.newArrayList(new Vec3d(1, offset, 1), new Vec3d(1, offset, 0),
|
||||
new Vec3d(0, offset, 0), new Vec3d(0, offset, 1));
|
||||
break;
|
||||
case Z:
|
||||
corners = Lists.newArrayList(new Vec3d(0, 1, offset), new Vec3d(0, 0, offset),
|
||||
new Vec3d(1, 0, offset), new Vec3d(1, 1, offset));
|
||||
break;
|
||||
}
|
||||
|
||||
if( facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE )
|
||||
{
|
||||
corners = Lists.reverse( corners );
|
||||
}
|
||||
if (facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) {
|
||||
corners = Lists.reverse(corners);
|
||||
}
|
||||
|
||||
result.put( facing, ImmutableList.copyOf( corners ) );
|
||||
}
|
||||
result.put(facing, ImmutableList.copyOf(corners));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Vec3d adjust( Vec3d vec, Direction.Axis axis, double delta )
|
||||
{
|
||||
switch( axis )
|
||||
{
|
||||
default:
|
||||
case X:
|
||||
return new Vec3d( vec.x + delta, vec.y, vec.z );
|
||||
case Y:
|
||||
return new Vec3d( vec.x, vec.y + delta, vec.z );
|
||||
case Z:
|
||||
return new Vec3d( vec.x, vec.y, vec.z + delta );
|
||||
}
|
||||
}
|
||||
private static Vec3d adjust(Vec3d vec, Direction.Axis axis, double delta) {
|
||||
switch (axis) {
|
||||
default:
|
||||
case X:
|
||||
return new Vec3d(vec.x + delta, vec.y, vec.z);
|
||||
case Y:
|
||||
return new Vec3d(vec.x, vec.y + delta, vec.z);
|
||||
case Z:
|
||||
return new Vec3d(vec.x, vec.y, vec.z + delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -26,8 +25,6 @@ import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import appeng.hooks.CompassManager;
|
||||
import appeng.hooks.CompassResult;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
@@ -44,188 +41,172 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
import appeng.hooks.CompassManager;
|
||||
import appeng.hooks.CompassResult;
|
||||
|
||||
/**
|
||||
* This baked model combines the quads of a compass base and the quads of a compass pointer, which will be rotated
|
||||
* around the Y-axis to get the compass to point in the right direction.
|
||||
* This baked model combines the quads of a compass base and the quads of a
|
||||
* compass pointer, which will be rotated around the Y-axis to get the compass
|
||||
* to point in the right direction.
|
||||
*/
|
||||
public class SkyCompassBakedModel implements IDynamicBakedModel
|
||||
{
|
||||
// Rotation is expressed as radians
|
||||
public static final ModelProperty<Float> ROTATION = new ModelProperty<>();
|
||||
public class SkyCompassBakedModel implements IDynamicBakedModel {
|
||||
// Rotation is expressed as radians
|
||||
public static final ModelProperty<Float> ROTATION = new ModelProperty<>();
|
||||
|
||||
private final IBakedModel base;
|
||||
private final IBakedModel base;
|
||||
|
||||
private final IBakedModel pointer;
|
||||
private final IBakedModel pointer;
|
||||
|
||||
private float fallbackRotation = 0;
|
||||
private float fallbackRotation = 0;
|
||||
|
||||
public SkyCompassBakedModel( IBakedModel base, IBakedModel pointer )
|
||||
{
|
||||
this.base = base;
|
||||
this.pointer = pointer;
|
||||
}
|
||||
public SkyCompassBakedModel(IBakedModel base, IBakedModel pointer) {
|
||||
this.base = base;
|
||||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand, IModelData extraData )
|
||||
{
|
||||
float rotation = 0;
|
||||
// Get rotation from the special block state
|
||||
Float rotationFromData = extraData.getData(ROTATION);
|
||||
if (rotationFromData != null) {
|
||||
rotation = rotationFromData;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is used to render a compass pointing in a specific direction when being held in hand
|
||||
rotation = this.fallbackRotation;
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData extraData) {
|
||||
float rotation = 0;
|
||||
// Get rotation from the special block state
|
||||
Float rotationFromData = extraData.getData(ROTATION);
|
||||
if (rotationFromData != null) {
|
||||
rotation = rotationFromData;
|
||||
} else {
|
||||
// This is used to render a compass pointing in a specific direction when being
|
||||
// held in hand
|
||||
rotation = this.fallbackRotation;
|
||||
}
|
||||
|
||||
// Pre-compute the quad count to avoid list resizes
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
quads.addAll( this.base.getQuads( state, side, rand, extraData ) );
|
||||
// Pre-compute the quad count to avoid list resizes
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
quads.addAll(this.base.getQuads(state, side, rand, extraData));
|
||||
|
||||
// We'll add the pointer as "sideless"
|
||||
if( side == null )
|
||||
{
|
||||
// Set up the rotation around the Y-axis for the pointer
|
||||
Matrix4f matrix = new Matrix4f();
|
||||
matrix.setIdentity();
|
||||
matrix.mul( new Quaternion( 0, rotation, 0, false ) );
|
||||
// We'll add the pointer as "sideless"
|
||||
if (side == null) {
|
||||
// Set up the rotation around the Y-axis for the pointer
|
||||
Matrix4f matrix = new Matrix4f();
|
||||
matrix.setIdentity();
|
||||
matrix.mul(new Quaternion(0, rotation, 0, false));
|
||||
|
||||
MatrixVertexTransformer transformer = new MatrixVertexTransformer( matrix );
|
||||
for( BakedQuad bakedQuad : this.pointer.getQuads( state, side, rand, extraData ) )
|
||||
{
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
MatrixVertexTransformer transformer = new MatrixVertexTransformer(matrix);
|
||||
for (BakedQuad bakedQuad : this.pointer.getQuads(state, side, rand, extraData)) {
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder();
|
||||
|
||||
transformer.setParent( builder );
|
||||
transformer.setVertexFormat( builder.getVertexFormat() );
|
||||
bakedQuad.pipe( transformer );
|
||||
// FIXME: This entire code is no longer truly valid...
|
||||
// FIXME builder.setQuadOrientation( null ); // After rotation, facing a specific side cannot be guaranteed
|
||||
// anymore
|
||||
BakedQuad q = builder.build();
|
||||
quads.add( q );
|
||||
}
|
||||
}
|
||||
transformer.setParent(builder);
|
||||
transformer.setVertexFormat(builder.getVertexFormat());
|
||||
bakedQuad.pipe(transformer);
|
||||
// FIXME: This entire code is no longer truly valid...
|
||||
// FIXME builder.setQuadOrientation( null ); // After rotation, facing a
|
||||
// specific side cannot be guaranteed
|
||||
// anymore
|
||||
BakedQuad q = builder.build();
|
||||
quads.add(q);
|
||||
}
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
return quads;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return this.base.isAmbientOcclusion();
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return this.base.isAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.base.getParticleTexture();
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.base.getParticleTexture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return this.base.getItemCameraTransforms();
|
||||
}
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return this.base.getItemCameraTransforms();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
/*
|
||||
* This handles setting the rotation of the compass when being held in hand. If it's not held in hand, it'll
|
||||
* animate using the
|
||||
* spinning animation.
|
||||
*/
|
||||
return new ItemOverrideList()
|
||||
{
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable LivingEntity entity) {
|
||||
// FIXME: This check prevents compasses being held by OTHERS from getting the rotation, BUT do we actually still need this???
|
||||
if (world != null && entity instanceof ClientPlayerEntity)
|
||||
{
|
||||
PlayerEntity player = (PlayerEntity) entity;
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
/*
|
||||
* This handles setting the rotation of the compass when being held in hand. If
|
||||
* it's not held in hand, it'll animate using the spinning animation.
|
||||
*/
|
||||
return new ItemOverrideList() {
|
||||
@Override
|
||||
public IBakedModel getModelWithOverrides(IBakedModel originalModel, ItemStack stack, @Nullable World world,
|
||||
@Nullable LivingEntity entity) {
|
||||
// FIXME: This check prevents compasses being held by OTHERS from getting the
|
||||
// rotation, BUT do we actually still need this???
|
||||
if (world != null && entity instanceof ClientPlayerEntity) {
|
||||
PlayerEntity player = (PlayerEntity) entity;
|
||||
|
||||
float offRads = (float) ( player.rotationYaw / 180.0f * (float) Math.PI + Math.PI );
|
||||
float offRads = (float) (player.rotationYaw / 180.0f * (float) Math.PI + Math.PI);
|
||||
|
||||
SkyCompassBakedModel.this.fallbackRotation = offRads + getAnimatedRotation( player.getPosition(), true );
|
||||
}
|
||||
else
|
||||
{
|
||||
SkyCompassBakedModel.this.fallbackRotation = getAnimatedRotation( null, false );
|
||||
}
|
||||
SkyCompassBakedModel.this.fallbackRotation = offRads
|
||||
+ getAnimatedRotation(player.getPosition(), true);
|
||||
} else {
|
||||
SkyCompassBakedModel.this.fallbackRotation = getAnimatedRotation(null, false);
|
||||
}
|
||||
|
||||
return originalModel;
|
||||
}
|
||||
};
|
||||
}
|
||||
return originalModel;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective, animated rotation for the compass given the current position of the compass.
|
||||
*/
|
||||
public static float getAnimatedRotation( @Nullable BlockPos pos, boolean prefetch )
|
||||
{
|
||||
/**
|
||||
* Gets the effective, animated rotation for the compass given the current
|
||||
* position of the compass.
|
||||
*/
|
||||
public static float getAnimatedRotation(@Nullable BlockPos pos, boolean prefetch) {
|
||||
|
||||
// Only query for a meteor position if we know our own position
|
||||
if( pos != null )
|
||||
{
|
||||
CompassResult cr = CompassManager.INSTANCE.getCompassDirection( 0, pos.getX(), pos.getY(), pos.getZ() );
|
||||
// Only query for a meteor position if we know our own position
|
||||
if (pos != null) {
|
||||
CompassResult cr = CompassManager.INSTANCE.getCompassDirection(0, pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
// Prefetch meteor positions from the server for adjacent blocks so they are available more quickly when
|
||||
// we're moving
|
||||
if( prefetch )
|
||||
{
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
CompassManager.INSTANCE.getCompassDirection( 0, pos.getX() + i - 1, pos.getY(), pos.getZ() + j - 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
// Prefetch meteor positions from the server for adjacent blocks so they are
|
||||
// available more quickly when
|
||||
// we're moving
|
||||
if (prefetch) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
CompassManager.INSTANCE.getCompassDirection(0, pos.getX() + i - 1, pos.getY(),
|
||||
pos.getZ() + j - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( cr.isValidResult() )
|
||||
{
|
||||
if( cr.isSpin() )
|
||||
{
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// .5 seconds per full rotation
|
||||
timeMillis %= 500;
|
||||
return timeMillis / 500.f * (float) Math.PI * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (float) cr.getRad();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cr.isValidResult()) {
|
||||
if (cr.isSpin()) {
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// .5 seconds per full rotation
|
||||
timeMillis %= 500;
|
||||
return timeMillis / 500.f * (float) Math.PI * 2;
|
||||
} else {
|
||||
return (float) cr.getRad();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// 3 seconds per full rotation
|
||||
timeMillis %= 3000;
|
||||
return timeMillis / 3000.f * (float) Math.PI * 2;
|
||||
}
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
// 3 seconds per full rotation
|
||||
timeMillis %= 3000;
|
||||
return timeMillis / 3000.f * (float) Math.PI * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,44 +18,48 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
/**
|
||||
* The parent model for the compass baked model. Declares the dependencies for the base and pointer submodels mostly.
|
||||
* The parent model for the compass baked model. Declares the dependencies for
|
||||
* the base and pointer submodels mostly.
|
||||
*/
|
||||
public class SkyCompassModel implements IModelGeometry<SkyCompassModel>
|
||||
{
|
||||
public class SkyCompassModel implements IModelGeometry<SkyCompassModel> {
|
||||
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation( "appliedenergistics2:block/sky_compass_base" );
|
||||
private static final ResourceLocation MODEL_BASE = new ResourceLocation(
|
||||
"appliedenergistics2:block/sky_compass_base");
|
||||
|
||||
private static final ResourceLocation MODEL_POINTER = new ResourceLocation( "appliedenergistics2:block/sky_compass_pointer" );
|
||||
private static final ResourceLocation MODEL_POINTER = new ResourceLocation(
|
||||
"appliedenergistics2:block/sky_compass_pointer");
|
||||
|
||||
public static final List<ResourceLocation> DEPENDENCIES = ImmutableList.of( MODEL_BASE, MODEL_POINTER );
|
||||
public static final List<ResourceLocation> DEPENDENCIES = ImmutableList.of(MODEL_BASE, MODEL_POINTER);
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
IBakedModel pointerModel = bakery.getBakedModel(MODEL_POINTER, modelTransform, spriteGetter);
|
||||
return new SkyCompassBakedModel(baseModel, pointerModel);
|
||||
}
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
IBakedModel baseModel = bakery.getBakedModel(MODEL_BASE, modelTransform, spriteGetter);
|
||||
IBakedModel pointerModel = bakery.getBakedModel(MODEL_POINTER, modelTransform, spriteGetter);
|
||||
return new SkyCompassBakedModel(baseModel, pointerModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,21 @@
|
||||
|
||||
package appeng.client.render.model;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
@@ -40,160 +52,146 @@ import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
|
||||
import net.minecraftforge.common.model.TransformationHelper;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
public class UVLModelLoader implements IModelLoader<UVLModelLoader.UVLModelWrapper> {
|
||||
|
||||
public static final UVLModelLoader INSTANCE = new UVLModelLoader();
|
||||
|
||||
public class UVLModelLoader implements IModelLoader<UVLModelLoader.UVLModelWrapper>
|
||||
{
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {
|
||||
}
|
||||
|
||||
public static final UVLModelLoader INSTANCE = new UVLModelLoader();
|
||||
@Override
|
||||
public UVLModelWrapper read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
|
||||
modelContents.remove("loader");
|
||||
BlockModel blockModel = UVLSERIALIZER.fromJson(modelContents, BlockModel.class);
|
||||
return new UVLModelWrapper(blockModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager resourceManager) {
|
||||
}
|
||||
final Gson UVLSERIALIZER = (new GsonBuilder())
|
||||
.registerTypeAdapter(BlockModel.class, new ModelLoaderRegistry.ExpandedBlockModelDeserializer())
|
||||
.registerTypeAdapter(BlockPart.class, new BlockPart.Deserializer())
|
||||
.registerTypeAdapter(BlockPartFace.class, new BlockPartFaceOverrideSerializer())
|
||||
.registerTypeAdapter(BlockFaceUV.class, new BlockFaceUV.Deserializer())
|
||||
.registerTypeAdapter(ItemTransformVec3f.class, new ItemTransformVec3f.Deserializer())
|
||||
.registerTypeAdapter(ItemCameraTransforms.class, new ItemCameraTransforms.Deserializer())
|
||||
.registerTypeAdapter(ItemOverride.class, new ItemOverride.Deserializer())
|
||||
.registerTypeAdapter(TransformationMatrix.class, new TransformationHelper.Deserializer()).create();
|
||||
|
||||
@Override
|
||||
public UVLModelWrapper read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
|
||||
modelContents.remove("loader");
|
||||
BlockModel blockModel = UVLSERIALIZER.fromJson(modelContents, BlockModel.class);
|
||||
return new UVLModelWrapper(blockModel);
|
||||
}
|
||||
private static class BlockPartFaceOverrideSerializer extends BlockPartFace.Deserializer {
|
||||
@Override
|
||||
public BlockPartFace deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_,
|
||||
JsonDeserializationContext p_deserialize_3_) throws JsonParseException {
|
||||
BlockPartFace blockFace = super.deserialize(p_deserialize_1_, p_deserialize_2_, p_deserialize_3_);
|
||||
Pair<Float, Float> uvl = this.parseUVL(p_deserialize_1_.getAsJsonObject());
|
||||
if (uvl != null) {
|
||||
return new BlockPartFaceWithUVL(blockFace.cullFace, blockFace.tintIndex, blockFace.texture,
|
||||
blockFace.blockFaceUV, uvl.getLeft(), uvl.getRight());
|
||||
}
|
||||
return blockFace;
|
||||
}
|
||||
|
||||
final Gson UVLSERIALIZER = (new GsonBuilder())
|
||||
.registerTypeAdapter(BlockModel.class, new ModelLoaderRegistry.ExpandedBlockModelDeserializer())
|
||||
.registerTypeAdapter(BlockPart.class, new BlockPart.Deserializer())
|
||||
.registerTypeAdapter(BlockPartFace.class, new BlockPartFaceOverrideSerializer())
|
||||
.registerTypeAdapter(BlockFaceUV.class, new BlockFaceUV.Deserializer())
|
||||
.registerTypeAdapter(ItemTransformVec3f.class, new ItemTransformVec3f.Deserializer())
|
||||
.registerTypeAdapter(ItemCameraTransforms.class, new ItemCameraTransforms.Deserializer())
|
||||
.registerTypeAdapter(ItemOverride.class, new ItemOverride.Deserializer())
|
||||
.registerTypeAdapter(TransformationMatrix.class, new TransformationHelper.Deserializer())
|
||||
.create();
|
||||
protected Pair<Float, Float> parseUVL(JsonObject object) {
|
||||
if (!object.has("uvlightmap")) {
|
||||
return null;
|
||||
}
|
||||
object = object.get("uvlightmap").getAsJsonObject();
|
||||
return new ImmutablePair<>(JSONUtils.getFloat(object, "sky", 0), JSONUtils.getFloat(object, "block", 0));
|
||||
}
|
||||
}
|
||||
|
||||
private static class BlockPartFaceOverrideSerializer extends BlockPartFace.Deserializer
|
||||
{
|
||||
@Override
|
||||
public BlockPartFace deserialize( JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_ ) throws JsonParseException
|
||||
{
|
||||
BlockPartFace blockFace = super.deserialize(p_deserialize_1_, p_deserialize_2_, p_deserialize_3_);
|
||||
Pair<Float, Float> uvl = this.parseUVL(p_deserialize_1_.getAsJsonObject());
|
||||
if (uvl != null) {
|
||||
return new BlockPartFaceWithUVL(blockFace.cullFace, blockFace.tintIndex, blockFace.texture, blockFace.blockFaceUV, uvl.getLeft(), uvl.getRight());
|
||||
}
|
||||
return blockFace;
|
||||
}
|
||||
private static class BlockPartFaceWithUVL extends BlockPartFace {
|
||||
|
||||
protected Pair<Float, Float> parseUVL( JsonObject object )
|
||||
{
|
||||
if( !object.has( "uvlightmap" ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
object = object.get( "uvlightmap" ).getAsJsonObject();
|
||||
return new ImmutablePair<>( JSONUtils.getFloat( object, "sky", 0 ), JSONUtils.getFloat( object, "block", 0 ) );
|
||||
}
|
||||
}
|
||||
private final float sky;
|
||||
private final float block;
|
||||
|
||||
private static class BlockPartFaceWithUVL extends BlockPartFace {
|
||||
public BlockPartFaceWithUVL(@Nullable Direction cullFaceIn, int tintIndexIn, String textureIn,
|
||||
BlockFaceUV blockFaceUVIn, float sky, float block) {
|
||||
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
|
||||
this.sky = sky;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
private final float sky;
|
||||
private final float block;
|
||||
public float getSky() {
|
||||
return sky;
|
||||
}
|
||||
|
||||
public BlockPartFaceWithUVL(@Nullable Direction cullFaceIn, int tintIndexIn, String textureIn, BlockFaceUV blockFaceUVIn, float sky, float block) {
|
||||
super(cullFaceIn, tintIndexIn, textureIn, blockFaceUVIn);
|
||||
this.sky = sky;
|
||||
this.block = block;
|
||||
}
|
||||
public float getBlock() {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
public float getSky() {
|
||||
return sky;
|
||||
}
|
||||
public static class UVLModelWrapper implements IModelGeometry<UVLModelWrapper> {
|
||||
private final BlockModel parent;
|
||||
|
||||
public float getBlock() {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
public UVLModelWrapper(BlockModel parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public static class UVLModelWrapper implements IModelGeometry<UVLModelWrapper>
|
||||
{
|
||||
private final BlockModel parent;
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
TextureAtlasSprite particle = spriteGetter.apply(owner.resolveTexture("particle"));
|
||||
|
||||
public UVLModelWrapper( BlockModel parent )
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
IModelBuilder<?> builder = IModelBuilder.of(owner, overrides, particle);
|
||||
for (BlockPart blockpart : parent.getElements()) {
|
||||
for (Direction direction : blockpart.mapFaces.keySet()) {
|
||||
BlockPartFace blockpartface = blockpart.mapFaces.get(direction);
|
||||
TextureAtlasSprite textureatlassprite1 = spriteGetter
|
||||
.apply(owner.resolveTexture(blockpartface.texture));
|
||||
BakedQuad quad = BlockModel.makeBakedQuad(blockpart, blockpartface, textureatlassprite1, direction,
|
||||
modelTransform, modelLocation);
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
TextureAtlasSprite particle = spriteGetter.apply(owner.resolveTexture("particle"));
|
||||
if (blockpartface instanceof BlockPartFaceWithUVL) {
|
||||
BlockPartFaceWithUVL uvlFace = (BlockPartFaceWithUVL) blockpartface;
|
||||
quad = applyPreBakedLighting(quad, textureatlassprite1, uvlFace.sky, uvlFace.block);
|
||||
}
|
||||
|
||||
IModelBuilder<?> builder = IModelBuilder.of(owner, overrides, particle);
|
||||
for(BlockPart blockpart : parent.getElements()) {
|
||||
for(Direction direction : blockpart.mapFaces.keySet()) {
|
||||
BlockPartFace blockpartface = blockpart.mapFaces.get(direction);
|
||||
TextureAtlasSprite textureatlassprite1 = spriteGetter.apply(owner.resolveTexture(blockpartface.texture));
|
||||
BakedQuad quad = BlockModel.makeBakedQuad(blockpart, blockpartface, textureatlassprite1, direction, modelTransform, modelLocation);
|
||||
if (blockpartface.cullFace == null) {
|
||||
builder.addGeneralQuad(quad);
|
||||
} else {
|
||||
builder.addFaceQuad(modelTransform.getRotation().rotateTransform(blockpartface.cullFace), quad);
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
if (blockpartface instanceof BlockPartFaceWithUVL) {
|
||||
BlockPartFaceWithUVL uvlFace = (BlockPartFaceWithUVL) blockpartface;
|
||||
quad = applyPreBakedLighting(quad, textureatlassprite1, uvlFace.sky, uvlFace.block);
|
||||
}
|
||||
private BakedQuad applyPreBakedLighting(BakedQuad quad, TextureAtlasSprite sprite, float sky, float block) {
|
||||
// FIXME: just piping through the quads and manipulating uv index 2 directly
|
||||
// seems way easier than this
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||
VertexLighterFlat trans = new VertexLighterFlat(Minecraft.getInstance().getBlockColors()) {
|
||||
|
||||
if (blockpartface.cullFace == null) {
|
||||
builder.addGeneralQuad(quad);
|
||||
} else {
|
||||
builder.addFaceQuad(
|
||||
modelTransform.getRotation().rotateTransform(blockpartface.cullFace),
|
||||
quad);
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
@Override
|
||||
protected void updateLightmap(float[] normal, float[] lightmap, float x, float y, float z) {
|
||||
lightmap[0] = block;
|
||||
lightmap[1] = sky;
|
||||
}
|
||||
|
||||
private BakedQuad applyPreBakedLighting(BakedQuad quad, TextureAtlasSprite sprite, float sky, float block) {
|
||||
// FIXME: just piping through the quads and manipulating uv index 2 directly seems way easier than this
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(sprite);
|
||||
VertexLighterFlat trans = new VertexLighterFlat( Minecraft.getInstance().getBlockColors() )
|
||||
{
|
||||
@Override
|
||||
public void setQuadTint(int tint) {
|
||||
// Tint requires a block state which we don't have at this point
|
||||
}
|
||||
};
|
||||
MatrixStack identity = new MatrixStack();
|
||||
trans.setTransform(identity.getLast());
|
||||
trans.setParent(builder);
|
||||
quad.pipe(trans);
|
||||
builder.setQuadTint(quad.getTintIndex());
|
||||
builder.setQuadOrientation(quad.getFace());
|
||||
builder.setApplyDiffuseLighting(false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateLightmap( float[] normal, float[] lightmap, float x, float y, float z )
|
||||
{
|
||||
lightmap[0] = block;
|
||||
lightmap[1] = sky;
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter,
|
||||
Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
|
||||
return parent.getTextures(modelGetter, missingTextureErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadTint( int tint )
|
||||
{
|
||||
// Tint requires a block state which we don't have at this point
|
||||
}
|
||||
};
|
||||
MatrixStack identity = new MatrixStack();
|
||||
trans.setTransform(identity.getLast());
|
||||
trans.setParent( builder );
|
||||
quad.pipe( trans );
|
||||
builder.setQuadTint( quad.getTintIndex() );
|
||||
builder.setQuadOrientation( quad.getFace() );
|
||||
builder.setApplyDiffuseLighting( false );
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors) {
|
||||
return parent.getTextures(modelGetter, missingTextureErrors);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user