pick 97420a31d The big reformat of 2020
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
@@ -28,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -48,324 +48,301 @@ import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
|
||||
public class CableBusBakedModel implements IBakedModel {
|
||||
|
||||
public class CableBusBakedModel implements IBakedModel
|
||||
{
|
||||
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
|
||||
|
||||
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
|
||||
private final CableBuilder cableBuilder;
|
||||
|
||||
private final CableBuilder cableBuilder;
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
|
||||
private final FacadeBuilder facadeBuilder;
|
||||
private final Map<ResourceLocation, IBakedModel> partModels;
|
||||
|
||||
private final Map<ResourceLocation, IBakedModel> partModels;
|
||||
private final TextureAtlasSprite particleTexture;
|
||||
|
||||
private final TextureAtlasSprite particleTexture;
|
||||
CableBusBakedModel(CableBuilder cableBuilder, FacadeBuilder facadeBuilder,
|
||||
Map<ResourceLocation, IBakedModel> partModels, TextureAtlasSprite particleTexture) {
|
||||
this.cableBuilder = cableBuilder;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
this.partModels = partModels;
|
||||
this.particleTexture = particleTexture;
|
||||
}
|
||||
|
||||
CableBusBakedModel( CableBuilder cableBuilder, FacadeBuilder facadeBuilder, Map<ResourceLocation, IBakedModel> partModels, TextureAtlasSprite particleTexture )
|
||||
{
|
||||
this.cableBuilder = cableBuilder;
|
||||
this.facadeBuilder = facadeBuilder;
|
||||
this.partModels = partModels;
|
||||
this.particleTexture = particleTexture;
|
||||
}
|
||||
@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 );
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, Random rand,
|
||||
IModelData data) {
|
||||
CableBusRenderState renderState = data.getData(CableBusRenderState.PROPERTY);
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( @Nullable BlockState state, @Nullable Direction side, Random rand, IModelData data )
|
||||
{
|
||||
CableBusRenderState renderState = data.getData( CableBusRenderState.PROPERTY );
|
||||
if (renderState == null || side != null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if( renderState == null || side != null )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
RenderType layer = MinecraftForgeClient.getRenderLayer();
|
||||
|
||||
RenderType layer = MinecraftForgeClient.getRenderLayer();
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
List<BakedQuad> quads = new ArrayList<>();
|
||||
// The core parts of the cable will only be rendered in the CUTOUT layer.
|
||||
// Facades will add them selves to what ever the block would be rendered with,
|
||||
// except when transparent facades are enabled, they are forced to TRANSPARENT.
|
||||
if (layer == RenderType.getCutout()) {
|
||||
|
||||
// The core parts of the cable will only be rendered in the CUTOUT layer.
|
||||
// Facades will add them selves to what ever the block would be rendered with,
|
||||
// except when transparent facades are enabled, they are forced to TRANSPARENT.
|
||||
if( layer == RenderType.getCutout() )
|
||||
{
|
||||
// First, handle the cable at the center of the cable bus
|
||||
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent(renderState, k -> {
|
||||
final List<BakedQuad> model = new ArrayList<>();
|
||||
this.addCableQuads(renderState, model);
|
||||
return model;
|
||||
});
|
||||
quads.addAll(cableModel);
|
||||
|
||||
// First, handle the cable at the center of the cable bus
|
||||
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent( renderState, k -> {
|
||||
final List<BakedQuad> model = new ArrayList<>();
|
||||
this.addCableQuads( renderState, model );
|
||||
return model;
|
||||
} );
|
||||
quads.addAll( cableModel );
|
||||
// Then handle attachments
|
||||
for (Direction facing : Direction.values()) {
|
||||
final IPartModel partModel = renderState.getAttachments().get(facing);
|
||||
if (partModel == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Then handle attachments
|
||||
for( Direction facing : Direction.values() )
|
||||
{
|
||||
final IPartModel partModel = renderState.getAttachments().get( facing );
|
||||
if( partModel == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
IModelData partModelData = renderState.getPartModelData().get(facing);
|
||||
if (partModelData == null) {
|
||||
partModelData = EmptyModelData.INSTANCE;
|
||||
}
|
||||
|
||||
IModelData partModelData = renderState.getPartModelData().get(facing);
|
||||
if (partModelData == null) {
|
||||
partModelData = EmptyModelData.INSTANCE;
|
||||
}
|
||||
for (ResourceLocation model : partModel.getModels()) {
|
||||
IBakedModel bakedModel = this.partModels.get(model);
|
||||
|
||||
for( ResourceLocation model : partModel.getModels() )
|
||||
{
|
||||
IBakedModel bakedModel = this.partModels.get( model );
|
||||
if (bakedModel == null) {
|
||||
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
|
||||
}
|
||||
|
||||
if( bakedModel == null )
|
||||
{
|
||||
throw new IllegalStateException( "Trying to use an unregistered part model: " + model );
|
||||
}
|
||||
List<BakedQuad> partQuads = bakedModel.getQuads(state, null, rand, partModelData);
|
||||
|
||||
List<BakedQuad> partQuads = bakedModel.getQuads(state, null, rand, partModelData);
|
||||
// Rotate quads accordingly
|
||||
QuadRotator rotator = new QuadRotator();
|
||||
partQuads = rotator.rotateQuads(partQuads, facing, Direction.UP);
|
||||
|
||||
// Rotate quads accordingly
|
||||
QuadRotator rotator = new QuadRotator();
|
||||
partQuads = rotator.rotateQuads( partQuads, facing, Direction.UP );
|
||||
quads.addAll(partQuads);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.facadeBuilder.buildFacadeQuads(layer, renderState, rand, quads, this.partModels::get);
|
||||
|
||||
quads.addAll( partQuads );
|
||||
}
|
||||
}
|
||||
}
|
||||
this.facadeBuilder.buildFacadeQuads( layer, renderState, rand, quads, this.partModels::get );
|
||||
return quads;
|
||||
}
|
||||
|
||||
return quads;
|
||||
}
|
||||
// Determines whether a cable is connected to exactly two sides that are
|
||||
// opposite each other
|
||||
private static boolean isStraightLine(AECableType cableType, EnumMap<Direction, AECableType> sides) {
|
||||
final Iterator<Entry<Direction, AECableType>> it = sides.entrySet().iterator();
|
||||
if (!it.hasNext()) {
|
||||
return false; // No connections
|
||||
}
|
||||
|
||||
// Determines whether a cable is connected to exactly two sides that are opposite each other
|
||||
private static boolean isStraightLine( AECableType cableType, EnumMap<Direction, AECableType> sides )
|
||||
{
|
||||
final Iterator<Entry<Direction, AECableType>> it = sides.entrySet().iterator();
|
||||
if( !it.hasNext() )
|
||||
{
|
||||
return false; // No connections
|
||||
}
|
||||
final Entry<Direction, AECableType> nextConnection = it.next();
|
||||
final Direction firstSide = nextConnection.getKey();
|
||||
final AECableType firstType = nextConnection.getValue();
|
||||
|
||||
final Entry<Direction, AECableType> nextConnection = it.next();
|
||||
final Direction firstSide = nextConnection.getKey();
|
||||
final AECableType firstType = nextConnection.getValue();
|
||||
if (!it.hasNext()) {
|
||||
return false; // Only a single connection
|
||||
}
|
||||
if (firstSide.getOpposite() != it.next().getKey()) {
|
||||
return false; // Connected to two sides that are not opposite each other
|
||||
}
|
||||
if (it.hasNext()) {
|
||||
return false; // Must not have any other connection points
|
||||
}
|
||||
|
||||
if( !it.hasNext() )
|
||||
{
|
||||
return false; // Only a single connection
|
||||
}
|
||||
if( firstSide.getOpposite() != it.next().getKey() )
|
||||
{
|
||||
return false; // Connected to two sides that are not opposite each other
|
||||
}
|
||||
if( it.hasNext() )
|
||||
{
|
||||
return false; // Must not have any other connection points
|
||||
}
|
||||
final AECableType secondType = sides.get(firstSide.getOpposite());
|
||||
|
||||
final AECableType secondType = sides.get( firstSide.getOpposite() );
|
||||
return firstType == secondType && cableType == firstType && cableType == secondType;
|
||||
}
|
||||
|
||||
return firstType == secondType && cableType == firstType && cableType == secondType;
|
||||
}
|
||||
private void addCableQuads(CableBusRenderState renderState, List<BakedQuad> quadsOut) {
|
||||
AECableType cableType = renderState.getCableType();
|
||||
if (cableType == AECableType.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void addCableQuads( CableBusRenderState renderState, List<BakedQuad> quadsOut )
|
||||
{
|
||||
AECableType cableType = renderState.getCableType();
|
||||
if( cableType == AECableType.NONE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
AEColor cableColor = renderState.getCableColor();
|
||||
EnumMap<Direction, AECableType> connectionTypes = renderState.getConnectionTypes();
|
||||
|
||||
AEColor cableColor = renderState.getCableColor();
|
||||
EnumMap<Direction, AECableType> connectionTypes = renderState.getConnectionTypes();
|
||||
// If the connection is straight, no busses are attached, and no covered core
|
||||
// has been forced (in case of glass
|
||||
// cables), then render the cable as a simplified straight line.
|
||||
boolean noAttachments = !renderState.getAttachments().values().stream()
|
||||
.anyMatch(IPartModel::requireCableConnection);
|
||||
if (noAttachments && isStraightLine(cableType, connectionTypes)) {
|
||||
Direction facing = connectionTypes.keySet().iterator().next();
|
||||
|
||||
// If the connection is straight, no busses are attached, and no covered core has been forced (in case of glass
|
||||
// cables), then render the cable as a simplified straight line.
|
||||
boolean noAttachments = !renderState.getAttachments().values().stream().anyMatch( IPartModel::requireCableConnection );
|
||||
if( noAttachments && isStraightLine( cableType, connectionTypes ) )
|
||||
{
|
||||
Direction facing = connectionTypes.keySet().iterator().next();
|
||||
switch (cableType) {
|
||||
case GLASS:
|
||||
this.cableBuilder.addStraightGlassConnection(facing, cableColor, quadsOut);
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addStraightCoveredConnection(facing, cableColor, quadsOut);
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addStraightSmartConnection(facing, cableColor,
|
||||
renderState.getChannelsOnSide().get(facing), quadsOut);
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
this.cableBuilder.addStraightDenseCoveredConnection(facing, cableColor, quadsOut);
|
||||
break;
|
||||
case DENSE_SMART:
|
||||
this.cableBuilder.addStraightDenseSmartConnection(facing, cableColor,
|
||||
renderState.getChannelsOnSide().get(facing), quadsOut);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch( cableType )
|
||||
{
|
||||
case GLASS:
|
||||
this.cableBuilder.addStraightGlassConnection( facing, cableColor, quadsOut );
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addStraightCoveredConnection( facing, cableColor, quadsOut );
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addStraightSmartConnection( facing, cableColor, renderState.getChannelsOnSide().get( facing ), quadsOut );
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
this.cableBuilder.addStraightDenseCoveredConnection( facing, cableColor, quadsOut );
|
||||
break;
|
||||
case DENSE_SMART:
|
||||
this.cableBuilder.addStraightDenseSmartConnection( facing, cableColor, renderState.getChannelsOnSide().get( facing ), quadsOut );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return; // Don't render the other form of connection
|
||||
}
|
||||
|
||||
return; // Don't render the other form of connection
|
||||
}
|
||||
this.cableBuilder.addCableCore(renderState.getCoreType(), cableColor, quadsOut);
|
||||
|
||||
this.cableBuilder.addCableCore( renderState.getCoreType(), cableColor, quadsOut );
|
||||
// Render all internal connections to attachments
|
||||
EnumMap<Direction, Integer> attachmentConnections = renderState.getAttachmentConnections();
|
||||
for (Direction facing : attachmentConnections.keySet()) {
|
||||
int distance = attachmentConnections.get(facing);
|
||||
int channels = renderState.getChannelsOnSide().get(facing);
|
||||
|
||||
// Render all internal connections to attachments
|
||||
EnumMap<Direction, Integer> attachmentConnections = renderState.getAttachmentConnections();
|
||||
for( Direction facing : attachmentConnections.keySet() )
|
||||
{
|
||||
int distance = attachmentConnections.get( facing );
|
||||
int channels = renderState.getChannelsOnSide().get( facing );
|
||||
switch (cableType) {
|
||||
case GLASS:
|
||||
this.cableBuilder.addConstrainedGlassConnection(facing, cableColor, distance, quadsOut);
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addConstrainedCoveredConnection(facing, cableColor, distance, quadsOut);
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addConstrainedSmartConnection(facing, cableColor, distance, channels, quadsOut);
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
case DENSE_SMART:
|
||||
// Dense cables do not render connections to parts since none can be attached
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch( cableType )
|
||||
{
|
||||
case GLASS:
|
||||
this.cableBuilder.addConstrainedGlassConnection( facing, cableColor, distance, quadsOut );
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addConstrainedCoveredConnection( facing, cableColor, distance, quadsOut );
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addConstrainedSmartConnection( facing, cableColor, distance, channels, quadsOut );
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
case DENSE_SMART:
|
||||
// Dense cables do not render connections to parts since none can be attached
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Render all outgoing connections using the appropriate type
|
||||
for (final Entry<Direction, AECableType> connection : connectionTypes.entrySet()) {
|
||||
final Direction facing = connection.getKey();
|
||||
final AECableType connectionType = connection.getValue();
|
||||
final boolean cableBusAdjacent = renderState.getCableBusAdjacent().contains(facing);
|
||||
final int channels = renderState.getChannelsOnSide().get(facing);
|
||||
|
||||
// Render all outgoing connections using the appropriate type
|
||||
for( final Entry<Direction, AECableType> connection : connectionTypes.entrySet() )
|
||||
{
|
||||
final Direction facing = connection.getKey();
|
||||
final AECableType connectionType = connection.getValue();
|
||||
final boolean cableBusAdjacent = renderState.getCableBusAdjacent().contains( facing );
|
||||
final int channels = renderState.getChannelsOnSide().get( facing );
|
||||
switch (cableType) {
|
||||
case GLASS:
|
||||
this.cableBuilder.addGlassConnection(facing, cableColor, connectionType, cableBusAdjacent,
|
||||
quadsOut);
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent,
|
||||
quadsOut);
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addSmartConnection(facing, cableColor, connectionType, cableBusAdjacent, channels,
|
||||
quadsOut);
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
this.cableBuilder.addDenseCoveredConnection(facing, cableColor, connectionType, cableBusAdjacent,
|
||||
quadsOut);
|
||||
break;
|
||||
case DENSE_SMART:
|
||||
this.cableBuilder.addDenseSmartConnection(facing, cableColor, connectionType, cableBusAdjacent,
|
||||
channels, quadsOut);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( cableType )
|
||||
{
|
||||
case GLASS:
|
||||
this.cableBuilder.addGlassConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
|
||||
break;
|
||||
case COVERED:
|
||||
this.cableBuilder.addCoveredConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
|
||||
break;
|
||||
case SMART:
|
||||
this.cableBuilder.addSmartConnection( facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut );
|
||||
break;
|
||||
case DENSE_COVERED:
|
||||
this.cableBuilder.addDenseCoveredConnection( facing, cableColor, connectionType, cableBusAdjacent, quadsOut );
|
||||
break;
|
||||
case DENSE_SMART:
|
||||
this.cableBuilder.addDenseSmartConnection( facing, cableColor, connectionType, cableBusAdjacent, channels, quadsOut );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a list of texture sprites appropriate for particles (digging, etc.)
|
||||
* given the render state for a cable bus.
|
||||
*/
|
||||
public List<TextureAtlasSprite> getParticleTextures(CableBusRenderState renderState) {
|
||||
CableCoreType coreType = CableCoreType.fromCableType(renderState.getCableType());
|
||||
AEColor cableColor = renderState.getCableColor();
|
||||
|
||||
/**
|
||||
* Gets a list of texture sprites appropriate for particles (digging, etc.) given the render state for a cable bus.
|
||||
*/
|
||||
public List<TextureAtlasSprite> getParticleTextures( CableBusRenderState renderState )
|
||||
{
|
||||
CableCoreType coreType = CableCoreType.fromCableType( renderState.getCableType() );
|
||||
AEColor cableColor = renderState.getCableColor();
|
||||
List<TextureAtlasSprite> result = new ArrayList<>();
|
||||
|
||||
List<TextureAtlasSprite> result = new ArrayList<>();
|
||||
if (coreType != null) {
|
||||
result.add(this.cableBuilder.getCoreTexture(coreType, cableColor));
|
||||
}
|
||||
|
||||
if( coreType != null )
|
||||
{
|
||||
result.add( this.cableBuilder.getCoreTexture( coreType, cableColor ) );
|
||||
}
|
||||
// If no core is present, just use the first part that comes into play
|
||||
for (Direction side : renderState.getAttachments().keySet()) {
|
||||
IPartModel partModel = renderState.getAttachments().get(side);
|
||||
|
||||
// If no core is present, just use the first part that comes into play
|
||||
for( Direction side : renderState.getAttachments().keySet() )
|
||||
{
|
||||
IPartModel partModel = renderState.getAttachments().get( side );
|
||||
for (ResourceLocation model : partModel.getModels()) {
|
||||
IBakedModel bakedModel = this.partModels.get(model);
|
||||
|
||||
for( ResourceLocation model : partModel.getModels() )
|
||||
{
|
||||
IBakedModel bakedModel = this.partModels.get( model );
|
||||
if (bakedModel == null) {
|
||||
throw new IllegalStateException("Trying to use an unregistered part model: " + model);
|
||||
}
|
||||
|
||||
if( bakedModel == null )
|
||||
{
|
||||
throw new IllegalStateException( "Trying to use an unregistered part model: " + model );
|
||||
}
|
||||
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
|
||||
|
||||
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
|
||||
// If a part sub-model has no particle texture (indicated by it being the
|
||||
// missing texture),
|
||||
// don't add it, so we don't get ugly missing texture break particles.
|
||||
if (!isMissingTexture(particleTexture)) {
|
||||
result.add(particleTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a part sub-model has no particle texture (indicated by it being the missing texture),
|
||||
// don't add it, so we don't get ugly missing texture break particles.
|
||||
if( !isMissingTexture(particleTexture) )
|
||||
{
|
||||
result.add( particleTexture );
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
private boolean isMissingTexture(TextureAtlasSprite particleTexture) {
|
||||
return particleTexture instanceof MissingTextureSprite;
|
||||
}
|
||||
|
||||
private boolean isMissingTexture(TextureAtlasSprite particleTexture) {
|
||||
return particleTexture instanceof MissingTextureSprite;
|
||||
}
|
||||
@Override
|
||||
public boolean isAmbientOcclusion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbientOcclusion()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isGui3d() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_230044_c_()
|
||||
{
|
||||
return false;//TODO
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.particleTexture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.particleTexture;
|
||||
}
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms() {
|
||||
return ItemCameraTransforms.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCameraTransforms getItemCameraTransforms()
|
||||
{
|
||||
return ItemCameraTransforms.DEFAULT;
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
CABLE_MODEL_CACHE.clear();
|
||||
}
|
||||
public static void clearCache() {
|
||||
CABLE_MODEL_CACHE.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ public class CableBusBreakingParticle extends SpriteTexturedParticle {
|
||||
private final float field_217571_C;
|
||||
private final float field_217572_F;
|
||||
|
||||
public CableBusBreakingParticle(World world, double x, double y, double z, double speedX, double speedY, double speedZ, TextureAtlasSprite sprite) {
|
||||
public CableBusBreakingParticle(World world, double x, double y, double z, double speedX, double speedY,
|
||||
double speedZ, TextureAtlasSprite sprite) {
|
||||
super(world, x, y, z, speedX, speedY, speedZ);
|
||||
this.setSprite(sprite);
|
||||
this.particleGravity = 1.0F;
|
||||
|
||||
@@ -18,73 +18,72 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import appeng.core.AELog;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
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 appeng.api.util.AEColor;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import net.minecraftforge.client.model.IModelConfiguration;
|
||||
import net.minecraftforge.client.model.geometry.IModelGeometry;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.features.registries.PartModels;
|
||||
|
||||
/**
|
||||
* The built-in model for the cable bus block.
|
||||
*/
|
||||
public class CableBusModel implements IModelGeometry<CableBusModel>
|
||||
{
|
||||
public class CableBusModel implements IModelGeometry<CableBusModel> {
|
||||
|
||||
private final PartModels partModels;
|
||||
private final PartModels partModels;
|
||||
|
||||
public CableBusModel( PartModels partModels )
|
||||
{
|
||||
this.partModels = partModels;
|
||||
}
|
||||
public CableBusModel(PartModels partModels) {
|
||||
this.partModels = partModels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
Map<ResourceLocation, IBakedModel> partModels = this.loadPartModels( bakery, spriteGetter, modelTransform );
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
Map<ResourceLocation, IBakedModel> partModels = this.loadPartModels(bakery, spriteGetter, modelTransform);
|
||||
|
||||
CableBuilder cableBuilder = new CableBuilder( spriteGetter );
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder();
|
||||
CableBuilder cableBuilder = new CableBuilder(spriteGetter);
|
||||
FacadeBuilder facadeBuilder = new FacadeBuilder();
|
||||
|
||||
// This should normally not be used, but we *have* to provide a particle texture or otherwise damage models will
|
||||
// crash
|
||||
TextureAtlasSprite particleTexture = cableBuilder.getCoreTexture( CableCoreType.GLASS, AEColor.TRANSPARENT );
|
||||
// This should normally not be used, but we *have* to provide a particle texture
|
||||
// or otherwise damage models will
|
||||
// crash
|
||||
TextureAtlasSprite particleTexture = cableBuilder.getCoreTexture(CableCoreType.GLASS, AEColor.TRANSPARENT);
|
||||
|
||||
return new CableBusBakedModel( cableBuilder, facadeBuilder, partModels, particleTexture );
|
||||
}
|
||||
return new CableBusBakedModel(cableBuilder, facadeBuilder, partModels, particleTexture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.unmodifiableList( CableBuilder.getTextures() );
|
||||
}
|
||||
@Override
|
||||
public Collection<Material> getTextures(IModelConfiguration owner,
|
||||
Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
|
||||
return Collections.unmodifiableList(CableBuilder.getTextures());
|
||||
}
|
||||
|
||||
private Map<ResourceLocation, IBakedModel> loadPartModels( ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetterIn, IModelTransform transformIn )
|
||||
{
|
||||
ImmutableMap.Builder<ResourceLocation, IBakedModel> result = ImmutableMap.builder();
|
||||
private Map<ResourceLocation, IBakedModel> loadPartModels(ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetterIn, IModelTransform transformIn) {
|
||||
ImmutableMap.Builder<ResourceLocation, IBakedModel> result = ImmutableMap.builder();
|
||||
|
||||
for( ResourceLocation location : this.partModels.getModels() )
|
||||
{
|
||||
IBakedModel bakedModel = bakery.getBakedModel(location, transformIn, spriteGetterIn);
|
||||
if (bakedModel == null) {
|
||||
AELog.warn("Failed to bake part model {}", location);
|
||||
} else {
|
||||
result.put(location, bakedModel);
|
||||
}
|
||||
}
|
||||
for (ResourceLocation location : this.partModels.getModels()) {
|
||||
IBakedModel bakedModel = bakery.getBakedModel(location, transformIn, spriteGetterIn);
|
||||
if (bakedModel == null) {
|
||||
AELog.warn("Failed to bake part model {}", location);
|
||||
} else {
|
||||
result.put(location, bakedModel);
|
||||
}
|
||||
}
|
||||
|
||||
return result.build();
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.core.features.registries.PartModels;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraftforge.client.model.IModelLoader;
|
||||
|
||||
import appeng.core.features.registries.PartModels;
|
||||
|
||||
public class CableBusModelLoader implements IModelLoader<CableBusModel> {
|
||||
|
||||
private final PartModels partModels;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
@@ -37,199 +36,181 @@ import appeng.api.parts.IPartModel;
|
||||
import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
|
||||
|
||||
/**
|
||||
* This class captures the entire rendering state needed for a cable bus and transports it to the rendering thread
|
||||
* for processing.
|
||||
* This class captures the entire rendering state needed for a cable bus and
|
||||
* transports it to the rendering thread for processing.
|
||||
*/
|
||||
public class CableBusRenderState
|
||||
{
|
||||
public class CableBusRenderState {
|
||||
|
||||
public static final ModelProperty<CableBusRenderState> PROPERTY = new ModelProperty<>();
|
||||
public static final ModelProperty<CableBusRenderState> PROPERTY = new ModelProperty<>();
|
||||
|
||||
// The cable type used for rendering the outgoing connections to other blocks and attached parts
|
||||
private AECableType cableType = AECableType.NONE;
|
||||
// The cable type used for rendering the outgoing connections to other blocks
|
||||
// and attached parts
|
||||
private AECableType cableType = AECableType.NONE;
|
||||
|
||||
// The type to use for rendering the core of the cable.
|
||||
private CableCoreType coreType;
|
||||
// The type to use for rendering the core of the cable.
|
||||
private CableCoreType coreType;
|
||||
|
||||
private AEColor cableColor = AEColor.TRANSPARENT;
|
||||
private AEColor cableColor = AEColor.TRANSPARENT;
|
||||
|
||||
// Describes the outgoing connections of this cable bus to other blocks, and how they should be rendered
|
||||
private EnumMap<Direction, AECableType> connectionTypes = new EnumMap<>( Direction.class );
|
||||
// Describes the outgoing connections of this cable bus to other blocks, and how
|
||||
// they should be rendered
|
||||
private EnumMap<Direction, AECableType> connectionTypes = new EnumMap<>(Direction.class);
|
||||
|
||||
// Indicate on which sides signified by connectionTypes above, there is another cable bus. If a side is connected,
|
||||
// but it is absent from this
|
||||
// set, then it means that there is a Grid host, but not a cable bus on that side (i.e. an interface, a controller,
|
||||
// etc.)
|
||||
private EnumSet<Direction> cableBusAdjacent = EnumSet.noneOf( Direction.class );
|
||||
// Indicate on which sides signified by connectionTypes above, there is another
|
||||
// cable bus. If a side is connected,
|
||||
// but it is absent from this
|
||||
// set, then it means that there is a Grid host, but not a cable bus on that
|
||||
// side (i.e. an interface, a controller,
|
||||
// etc.)
|
||||
private EnumSet<Direction> cableBusAdjacent = EnumSet.noneOf(Direction.class);
|
||||
|
||||
// Specifies the number of channels used for the connection to a given side. Only contains entries if
|
||||
// connections contains a corresponding entry.
|
||||
private EnumMap<Direction, Integer> channelsOnSide = new EnumMap<>( Direction.class );
|
||||
// Specifies the number of channels used for the connection to a given side.
|
||||
// Only contains entries if
|
||||
// connections contains a corresponding entry.
|
||||
private EnumMap<Direction, Integer> channelsOnSide = new EnumMap<>(Direction.class);
|
||||
|
||||
private EnumMap<Direction, IPartModel> attachments = new EnumMap<>( Direction.class );
|
||||
private EnumMap<Direction, IPartModel> attachments = new EnumMap<>(Direction.class);
|
||||
|
||||
// For each attachment, this contains the distance from the edge until which a cable connection should be drawn
|
||||
private EnumMap<Direction, Integer> attachmentConnections = new EnumMap<>( Direction.class );
|
||||
// For each attachment, this contains the distance from the edge until which a
|
||||
// cable connection should be drawn
|
||||
private EnumMap<Direction, Integer> attachmentConnections = new EnumMap<>(Direction.class);
|
||||
|
||||
// Contains the facade to use for each side that has a facade attached
|
||||
private EnumMap<Direction, FacadeRenderState> facades = new EnumMap<>( Direction.class );
|
||||
// Contains the facade to use for each side that has a facade attached
|
||||
private EnumMap<Direction, FacadeRenderState> facades = new EnumMap<>(Direction.class);
|
||||
|
||||
// Used for Facades.
|
||||
private WeakReference<ILightReader> world;
|
||||
private BlockPos pos;
|
||||
// Used for Facades.
|
||||
private WeakReference<ILightReader> world;
|
||||
private BlockPos pos;
|
||||
|
||||
// Contains the bounding boxes of all parts on the cable bus to allow facades to cut out holes for the parts. This
|
||||
// list is only populated if there are
|
||||
// facades on this cable bus
|
||||
private List<AxisAlignedBB> boundingBoxes = new ArrayList<>();
|
||||
// Contains the bounding boxes of all parts on the cable bus to allow facades to
|
||||
// cut out holes for the parts. This
|
||||
// list is only populated if there are
|
||||
// facades on this cable bus
|
||||
private List<AxisAlignedBB> boundingBoxes = new ArrayList<>();
|
||||
|
||||
// Additional model data passed to the part models
|
||||
private EnumMap<Direction, IModelData> partModelData = new EnumMap<>( Direction.class );
|
||||
// Additional model data passed to the part models
|
||||
private EnumMap<Direction, IModelData> partModelData = new EnumMap<>(Direction.class);
|
||||
|
||||
public CableCoreType getCoreType()
|
||||
{
|
||||
return this.coreType;
|
||||
}
|
||||
public CableCoreType getCoreType() {
|
||||
return this.coreType;
|
||||
}
|
||||
|
||||
public void setCoreType( CableCoreType coreType )
|
||||
{
|
||||
this.coreType = coreType;
|
||||
}
|
||||
public void setCoreType(CableCoreType coreType) {
|
||||
this.coreType = coreType;
|
||||
}
|
||||
|
||||
public AECableType getCableType()
|
||||
{
|
||||
return this.cableType;
|
||||
}
|
||||
public AECableType getCableType() {
|
||||
return this.cableType;
|
||||
}
|
||||
|
||||
public void setCableType( AECableType cableType )
|
||||
{
|
||||
this.cableType = cableType;
|
||||
}
|
||||
public void setCableType(AECableType cableType) {
|
||||
this.cableType = cableType;
|
||||
}
|
||||
|
||||
public AEColor getCableColor()
|
||||
{
|
||||
return this.cableColor;
|
||||
}
|
||||
public AEColor getCableColor() {
|
||||
return this.cableColor;
|
||||
}
|
||||
|
||||
public void setCableColor( AEColor cableColor )
|
||||
{
|
||||
this.cableColor = cableColor;
|
||||
}
|
||||
public void setCableColor(AEColor cableColor) {
|
||||
this.cableColor = cableColor;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, Integer> getChannelsOnSide()
|
||||
{
|
||||
return this.channelsOnSide;
|
||||
}
|
||||
public EnumMap<Direction, Integer> getChannelsOnSide() {
|
||||
return this.channelsOnSide;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, AECableType> getConnectionTypes()
|
||||
{
|
||||
return this.connectionTypes;
|
||||
}
|
||||
public EnumMap<Direction, AECableType> getConnectionTypes() {
|
||||
return this.connectionTypes;
|
||||
}
|
||||
|
||||
public void setConnectionTypes( EnumMap<Direction, AECableType> connectionTypes )
|
||||
{
|
||||
this.connectionTypes = connectionTypes;
|
||||
}
|
||||
public void setConnectionTypes(EnumMap<Direction, AECableType> connectionTypes) {
|
||||
this.connectionTypes = connectionTypes;
|
||||
}
|
||||
|
||||
public void setChannelsOnSide( EnumMap<Direction, Integer> channelsOnSide )
|
||||
{
|
||||
this.channelsOnSide = channelsOnSide;
|
||||
}
|
||||
public void setChannelsOnSide(EnumMap<Direction, Integer> channelsOnSide) {
|
||||
this.channelsOnSide = channelsOnSide;
|
||||
}
|
||||
|
||||
public EnumSet<Direction> getCableBusAdjacent()
|
||||
{
|
||||
return this.cableBusAdjacent;
|
||||
}
|
||||
public EnumSet<Direction> getCableBusAdjacent() {
|
||||
return this.cableBusAdjacent;
|
||||
}
|
||||
|
||||
public void setCableBusAdjacent( EnumSet<Direction> cableBusAdjacent )
|
||||
{
|
||||
this.cableBusAdjacent = cableBusAdjacent;
|
||||
}
|
||||
public void setCableBusAdjacent(EnumSet<Direction> cableBusAdjacent) {
|
||||
this.cableBusAdjacent = cableBusAdjacent;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, IPartModel> getAttachments()
|
||||
{
|
||||
return this.attachments;
|
||||
}
|
||||
public EnumMap<Direction, IPartModel> getAttachments() {
|
||||
return this.attachments;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, Integer> getAttachmentConnections()
|
||||
{
|
||||
return this.attachmentConnections;
|
||||
}
|
||||
public EnumMap<Direction, Integer> getAttachmentConnections() {
|
||||
return this.attachmentConnections;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, FacadeRenderState> getFacades()
|
||||
{
|
||||
return this.facades;
|
||||
}
|
||||
public EnumMap<Direction, FacadeRenderState> getFacades() {
|
||||
return this.facades;
|
||||
}
|
||||
|
||||
public ILightReader getWorld()
|
||||
{
|
||||
return this.world.get();
|
||||
}
|
||||
public ILightReader getWorld() {
|
||||
return this.world.get();
|
||||
}
|
||||
|
||||
public void setWorld( ILightReader world )
|
||||
{
|
||||
this.world = new WeakReference<>( world );
|
||||
}
|
||||
public void setWorld(ILightReader world) {
|
||||
this.world = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
public BlockPos getPos()
|
||||
{
|
||||
return this.pos;
|
||||
}
|
||||
public BlockPos getPos() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
public void setPos( BlockPos pos )
|
||||
{
|
||||
this.pos = pos;
|
||||
}
|
||||
public void setPos(BlockPos pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
public List<AxisAlignedBB> getBoundingBoxes()
|
||||
{
|
||||
return this.boundingBoxes;
|
||||
}
|
||||
public List<AxisAlignedBB> getBoundingBoxes() {
|
||||
return this.boundingBoxes;
|
||||
}
|
||||
|
||||
public EnumMap<Direction, IModelData> getPartModelData()
|
||||
{
|
||||
return this.partModelData;
|
||||
}
|
||||
public EnumMap<Direction, IModelData> getPartModelData() {
|
||||
return this.partModelData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ( ( this.attachmentConnections == null ) ? 0 : this.attachmentConnections.hashCode() );
|
||||
result = prime * result + ( ( this.cableBusAdjacent == null ) ? 0 : this.cableBusAdjacent.hashCode() );
|
||||
result = prime * result + ( ( this.cableColor == null ) ? 0 : this.cableColor.hashCode() );
|
||||
result = prime * result + ( ( this.cableType == null ) ? 0 : this.cableType.hashCode() );
|
||||
result = prime * result + ( ( this.channelsOnSide == null ) ? 0 : this.channelsOnSide.hashCode() );
|
||||
result = prime * result + ( ( this.connectionTypes == null ) ? 0 : this.connectionTypes.hashCode() );
|
||||
result = prime * result + ( ( this.coreType == null ) ? 0 : this.coreType.hashCode() );
|
||||
result = prime * result + ( ( this.partModelData == null ) ? 0 : this.partModelData.hashCode() );
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.attachmentConnections == null) ? 0 : this.attachmentConnections.hashCode());
|
||||
result = prime * result + ((this.cableBusAdjacent == null) ? 0 : this.cableBusAdjacent.hashCode());
|
||||
result = prime * result + ((this.cableColor == null) ? 0 : this.cableColor.hashCode());
|
||||
result = prime * result + ((this.cableType == null) ? 0 : this.cableType.hashCode());
|
||||
result = prime * result + ((this.channelsOnSide == null) ? 0 : this.channelsOnSide.hashCode());
|
||||
result = prime * result + ((this.connectionTypes == null) ? 0 : this.connectionTypes.hashCode());
|
||||
result = prime * result + ((this.coreType == null) ? 0 : this.coreType.hashCode());
|
||||
result = prime * result + ((this.partModelData == null) ? 0 : this.partModelData.hashCode());
|
||||
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;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CableBusRenderState other = (CableBusRenderState) obj;
|
||||
final CableBusRenderState other = (CableBusRenderState) obj;
|
||||
|
||||
return this.cableColor == other.cableColor && this.cableType == other.cableType && this.coreType == other.coreType && Objects
|
||||
.equals( this.attachmentConnections, other.attachmentConnections ) && Objects.equals( this.cableBusAdjacent, other.cableBusAdjacent ) && Objects
|
||||
.equals( this.channelsOnSide, other.channelsOnSide ) && Objects.equals( this.connectionTypes, other.connectionTypes ) && Objects
|
||||
.equals( this.partModelData, other.partModelData);
|
||||
}
|
||||
return this.cableColor == other.cableColor && this.cableType == other.cableType
|
||||
&& this.coreType == other.coreType
|
||||
&& Objects.equals(this.attachmentConnections, other.attachmentConnections)
|
||||
&& Objects.equals(this.cableBusAdjacent, other.cableBusAdjacent)
|
||||
&& Objects.equals(this.channelsOnSide, other.channelsOnSide)
|
||||
&& Objects.equals(this.connectionTypes, other.connectionTypes)
|
||||
&& Objects.equals(this.partModelData, other.partModelData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -32,57 +31,50 @@ import appeng.api.util.AECableType;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.core.AppEng;
|
||||
|
||||
|
||||
/**
|
||||
* AE can render the core of a cable (the core that connections are made to, in case the cable is not a straight line)
|
||||
* in three different ways:
|
||||
* - Glass
|
||||
* - Covered (also used by the Smart Cable)
|
||||
* - Dense
|
||||
* AE can render the core of a cable (the core that connections are made to, in
|
||||
* case the cable is not a straight line) in three different ways: - Glass -
|
||||
* Covered (also used by the Smart Cable) - Dense
|
||||
*/
|
||||
public enum CableCoreType
|
||||
{
|
||||
GLASS( "parts/cable/core/glass" ), COVERED( "parts/cable/core/covered" ), DENSE( "parts/cable/core/dense_smart" );
|
||||
public enum CableCoreType {
|
||||
GLASS("parts/cable/core/glass"), COVERED("parts/cable/core/covered"), DENSE("parts/cable/core/dense_smart");
|
||||
|
||||
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
|
||||
private static final Map<AECableType, CableCoreType> cableMapping = generateCableMapping();
|
||||
|
||||
/**
|
||||
* Creates the mapping that assigns a cable core type to an AE cable type.
|
||||
*/
|
||||
private static Map<AECableType, CableCoreType> generateCableMapping()
|
||||
{
|
||||
/**
|
||||
* Creates the mapping that assigns a cable core type to an AE cable type.
|
||||
*/
|
||||
private static Map<AECableType, CableCoreType> generateCableMapping() {
|
||||
|
||||
Map<AECableType, CableCoreType> result = new EnumMap<>( AECableType.class );
|
||||
Map<AECableType, CableCoreType> result = new EnumMap<>(AECableType.class);
|
||||
|
||||
result.put( AECableType.GLASS, CableCoreType.GLASS );
|
||||
result.put( AECableType.COVERED, CableCoreType.COVERED );
|
||||
result.put( AECableType.SMART, CableCoreType.COVERED );
|
||||
result.put( AECableType.DENSE_COVERED, CableCoreType.DENSE );
|
||||
result.put( AECableType.DENSE_SMART, CableCoreType.DENSE );
|
||||
result.put(AECableType.GLASS, CableCoreType.GLASS);
|
||||
result.put(AECableType.COVERED, CableCoreType.COVERED);
|
||||
result.put(AECableType.SMART, CableCoreType.COVERED);
|
||||
result.put(AECableType.DENSE_COVERED, CableCoreType.DENSE);
|
||||
result.put(AECableType.DENSE_SMART, CableCoreType.DENSE);
|
||||
|
||||
return ImmutableMap.copyOf( result );
|
||||
}
|
||||
return ImmutableMap.copyOf(result);
|
||||
}
|
||||
|
||||
private final String textureFolder;
|
||||
private final String textureFolder;
|
||||
|
||||
CableCoreType( String textureFolder )
|
||||
{
|
||||
this.textureFolder = textureFolder;
|
||||
}
|
||||
CableCoreType(String textureFolder) {
|
||||
this.textureFolder = textureFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of core that should be rendered when the given cable isn't straight and needs to have a core to
|
||||
* attach connections to.
|
||||
* Is null for the NULL cable.
|
||||
*/
|
||||
public static CableCoreType fromCableType( AECableType cableType )
|
||||
{
|
||||
return cableMapping.get( cableType );
|
||||
}
|
||||
/**
|
||||
* @return The type of core that should be rendered when the given cable isn't
|
||||
* straight and needs to have a core to attach connections to. Is null
|
||||
* for the NULL cable.
|
||||
*/
|
||||
public static CableCoreType fromCableType(AECableType cableType) {
|
||||
return cableMapping.get(cableType);
|
||||
}
|
||||
|
||||
public Material getTexture( AEColor color )
|
||||
{
|
||||
return new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase() ) );
|
||||
}
|
||||
public Material getTexture(AEColor color) {
|
||||
return new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, this.textureFolder + "/" + color.name().toLowerCase()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
@@ -34,479 +33,434 @@ import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* Builds the quads for a cube.
|
||||
*/
|
||||
public class CubeBuilder
|
||||
{
|
||||
public class CubeBuilder {
|
||||
|
||||
private final List<BakedQuad> output;
|
||||
private final List<BakedQuad> output;
|
||||
|
||||
private final EnumMap<Direction, TextureAtlasSprite> textures = new EnumMap<>( Direction.class );
|
||||
private final EnumMap<Direction, TextureAtlasSprite> textures = new EnumMap<>(Direction.class);
|
||||
|
||||
private EnumSet<Direction> drawFaces = EnumSet.allOf( Direction.class );
|
||||
private EnumSet<Direction> drawFaces = EnumSet.allOf(Direction.class);
|
||||
|
||||
private final EnumMap<Direction, Vector4f> customUv = new EnumMap<>( Direction.class );
|
||||
private final EnumMap<Direction, Vector4f> customUv = new EnumMap<>(Direction.class);
|
||||
|
||||
private byte[] uvRotations = new byte[Direction.values().length];
|
||||
private byte[] uvRotations = new byte[Direction.values().length];
|
||||
|
||||
private int color = 0xFFFFFFFF;
|
||||
private int color = 0xFFFFFFFF;
|
||||
|
||||
private boolean useStandardUV = false;
|
||||
private boolean useStandardUV = false;
|
||||
|
||||
private boolean renderFullBright;
|
||||
private boolean renderFullBright;
|
||||
|
||||
public CubeBuilder( List<BakedQuad> output )
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
public CubeBuilder(List<BakedQuad> output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public CubeBuilder()
|
||||
{
|
||||
this( new ArrayList<>( 6 ) );
|
||||
}
|
||||
public CubeBuilder() {
|
||||
this(new ArrayList<>(6));
|
||||
}
|
||||
|
||||
public void addCube( float x1, float y1, float z1, float x2, float y2, float z2 )
|
||||
{
|
||||
x1 /= 16.0f;
|
||||
y1 /= 16.0f;
|
||||
z1 /= 16.0f;
|
||||
x2 /= 16.0f;
|
||||
y2 /= 16.0f;
|
||||
z2 /= 16.0f;
|
||||
public void addCube(float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
x1 /= 16.0f;
|
||||
y1 /= 16.0f;
|
||||
z1 /= 16.0f;
|
||||
x2 /= 16.0f;
|
||||
y2 /= 16.0f;
|
||||
z2 /= 16.0f;
|
||||
|
||||
for( Direction face : this.drawFaces )
|
||||
{
|
||||
this.putFace( face, x1, y1, z1, x2, y2, z2 );
|
||||
}
|
||||
}
|
||||
for (Direction face : this.drawFaces) {
|
||||
this.putFace(face, x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
}
|
||||
|
||||
public void addQuad( Direction face, float x1, float y1, float z1, float x2, float y2, float z2 )
|
||||
{
|
||||
this.putFace( face, x1, y1, z1, x2, y2, z2 );
|
||||
}
|
||||
public void addQuad(Direction face, float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
this.putFace(face, x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
|
||||
private static final class UvVector
|
||||
{
|
||||
float u1;
|
||||
float u2;
|
||||
float v1;
|
||||
float v2;
|
||||
}
|
||||
private static final class UvVector {
|
||||
float u1;
|
||||
float u2;
|
||||
float v1;
|
||||
float v2;
|
||||
}
|
||||
|
||||
private void putFace( Direction face, float x1, float y1, float z1, float x2, float y2, float z2 )
|
||||
{
|
||||
private void putFace(Direction face, float x1, float y1, float z1, float x2, float y2, float z2) {
|
||||
|
||||
TextureAtlasSprite texture = this.textures.get( face );
|
||||
TextureAtlasSprite texture = this.textures.get(face);
|
||||
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder( texture );
|
||||
builder.setQuadOrientation( face );
|
||||
builder.setQuadTint( -1 );
|
||||
builder.setApplyDiffuseLighting( true );
|
||||
BakedQuadBuilder builder = new BakedQuadBuilder(texture);
|
||||
builder.setQuadOrientation(face);
|
||||
builder.setQuadTint(-1);
|
||||
builder.setApplyDiffuseLighting(true);
|
||||
|
||||
UvVector uv = new UvVector();
|
||||
UvVector uv = new UvVector();
|
||||
|
||||
// The user might have set specific UV coordinates for this face
|
||||
Vector4f customUv = this.customUv.get( face );
|
||||
if( customUv != null )
|
||||
{
|
||||
uv.u1 = texture.getInterpolatedU( customUv.getX() );
|
||||
uv.v1 = texture.getInterpolatedV( customUv.getY() );
|
||||
uv.u2 = texture.getInterpolatedU( customUv.getZ() );
|
||||
uv.v2 = texture.getInterpolatedV( customUv.getW() );
|
||||
}
|
||||
else if( this.useStandardUV )
|
||||
{
|
||||
uv = this.getStandardUv( face, texture, x1, y1, z1, x2, y2, z2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
uv = this.getDefaultUv( face, texture, x1, y1, z1, x2, y2, z2 );
|
||||
}
|
||||
// The user might have set specific UV coordinates for this face
|
||||
Vector4f customUv = this.customUv.get(face);
|
||||
if (customUv != null) {
|
||||
uv.u1 = texture.getInterpolatedU(customUv.getX());
|
||||
uv.v1 = texture.getInterpolatedV(customUv.getY());
|
||||
uv.u2 = texture.getInterpolatedU(customUv.getZ());
|
||||
uv.v2 = texture.getInterpolatedV(customUv.getW());
|
||||
} else if (this.useStandardUV) {
|
||||
uv = this.getStandardUv(face, texture, x1, y1, z1, x2, y2, z2);
|
||||
} else {
|
||||
uv = this.getDefaultUv(face, texture, x1, y1, z1, x2, y2, z2);
|
||||
}
|
||||
|
||||
switch( face )
|
||||
{
|
||||
case DOWN:
|
||||
this.putVertexTR( builder, face, x2, y1, z1, uv );
|
||||
this.putVertexBR( builder, face, x2, y1, z2, uv );
|
||||
this.putVertexBL( builder, face, x1, y1, z2, uv );
|
||||
this.putVertexTL( builder, face, x1, y1, z1, uv );
|
||||
break;
|
||||
case UP:
|
||||
this.putVertexTL( builder, face, x1, y2, z1, uv );
|
||||
this.putVertexBL( builder, face, x1, y2, z2, uv );
|
||||
this.putVertexBR( builder, face, x2, y2, z2, uv );
|
||||
this.putVertexTR( builder, face, x2, y2, z1, uv );
|
||||
break;
|
||||
case NORTH:
|
||||
this.putVertexBR( builder, face, x2, y2, z1, uv );
|
||||
this.putVertexTR( builder, face, x2, y1, z1, uv );
|
||||
this.putVertexTL( builder, face, x1, y1, z1, uv );
|
||||
this.putVertexBL( builder, face, x1, y2, z1, uv );
|
||||
break;
|
||||
case SOUTH:
|
||||
this.putVertexBL( builder, face, x1, y2, z2, uv );
|
||||
this.putVertexTL( builder, face, x1, y1, z2, uv );
|
||||
this.putVertexTR( builder, face, x2, y1, z2, uv );
|
||||
this.putVertexBR( builder, face, x2, y2, z2, uv );
|
||||
break;
|
||||
case WEST:
|
||||
this.putVertexTL( builder, face, x1, y1, z1, uv );
|
||||
this.putVertexTR( builder, face, x1, y1, z2, uv );
|
||||
this.putVertexBR( builder, face, x1, y2, z2, uv );
|
||||
this.putVertexBL( builder, face, x1, y2, z1, uv );
|
||||
break;
|
||||
case EAST:
|
||||
this.putVertexBR( builder, face, x2, y2, z1, uv );
|
||||
this.putVertexBL( builder, face, x2, y2, z2, uv );
|
||||
this.putVertexTL( builder, face, x2, y1, z2, uv );
|
||||
this.putVertexTR( builder, face, x2, y1, z1, uv );
|
||||
break;
|
||||
}
|
||||
switch (face) {
|
||||
case DOWN:
|
||||
this.putVertexTR(builder, face, x2, y1, z1, uv);
|
||||
this.putVertexBR(builder, face, x2, y1, z2, uv);
|
||||
this.putVertexBL(builder, face, x1, y1, z2, uv);
|
||||
this.putVertexTL(builder, face, x1, y1, z1, uv);
|
||||
break;
|
||||
case UP:
|
||||
this.putVertexTL(builder, face, x1, y2, z1, uv);
|
||||
this.putVertexBL(builder, face, x1, y2, z2, uv);
|
||||
this.putVertexBR(builder, face, x2, y2, z2, uv);
|
||||
this.putVertexTR(builder, face, x2, y2, z1, uv);
|
||||
break;
|
||||
case NORTH:
|
||||
this.putVertexBR(builder, face, x2, y2, z1, uv);
|
||||
this.putVertexTR(builder, face, x2, y1, z1, uv);
|
||||
this.putVertexTL(builder, face, x1, y1, z1, uv);
|
||||
this.putVertexBL(builder, face, x1, y2, z1, uv);
|
||||
break;
|
||||
case SOUTH:
|
||||
this.putVertexBL(builder, face, x1, y2, z2, uv);
|
||||
this.putVertexTL(builder, face, x1, y1, z2, uv);
|
||||
this.putVertexTR(builder, face, x2, y1, z2, uv);
|
||||
this.putVertexBR(builder, face, x2, y2, z2, uv);
|
||||
break;
|
||||
case WEST:
|
||||
this.putVertexTL(builder, face, x1, y1, z1, uv);
|
||||
this.putVertexTR(builder, face, x1, y1, z2, uv);
|
||||
this.putVertexBR(builder, face, x1, y2, z2, uv);
|
||||
this.putVertexBL(builder, face, x1, y2, z1, uv);
|
||||
break;
|
||||
case EAST:
|
||||
this.putVertexBR(builder, face, x2, y2, z1, uv);
|
||||
this.putVertexBL(builder, face, x2, y2, z2, uv);
|
||||
this.putVertexTL(builder, face, x2, y1, z2, uv);
|
||||
this.putVertexTR(builder, face, x2, y1, z1, uv);
|
||||
break;
|
||||
}
|
||||
|
||||
this.output.add( builder.build() );
|
||||
}
|
||||
this.output.add(builder.build());
|
||||
}
|
||||
|
||||
private UvVector getDefaultUv( Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 )
|
||||
{
|
||||
private UvVector getDefaultUv(Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2,
|
||||
float y2, float z2) {
|
||||
|
||||
UvVector uv = new UvVector();
|
||||
UvVector uv = new UvVector();
|
||||
|
||||
switch( face )
|
||||
{
|
||||
case DOWN:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( z1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( z2 * 16 );
|
||||
break;
|
||||
case UP:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( z1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( z2 * 16 );
|
||||
break;
|
||||
case NORTH:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case SOUTH:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case WEST:
|
||||
uv.u1 = texture.getInterpolatedU( z1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( z2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case EAST:
|
||||
uv.u1 = texture.getInterpolatedU( z2 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( z1 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
}
|
||||
switch (face) {
|
||||
case DOWN:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(z1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(z2 * 16);
|
||||
break;
|
||||
case UP:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(z1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(z2 * 16);
|
||||
break;
|
||||
case NORTH:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case SOUTH:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case WEST:
|
||||
uv.u1 = texture.getInterpolatedU(z1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(z2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case EAST:
|
||||
uv.u1 = texture.getInterpolatedU(z2 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(z1 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
}
|
||||
|
||||
return uv;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
|
||||
private UvVector getStandardUv( Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 )
|
||||
{
|
||||
UvVector uv = new UvVector();
|
||||
switch( face )
|
||||
{
|
||||
case DOWN:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - z1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - z2 * 16 );
|
||||
break;
|
||||
case UP:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( z1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( z2 * 16 );
|
||||
break;
|
||||
case NORTH:
|
||||
uv.u1 = texture.getInterpolatedU( 16 - x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( 16 - x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case SOUTH:
|
||||
uv.u1 = texture.getInterpolatedU( x1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( x2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case WEST:
|
||||
uv.u1 = texture.getInterpolatedU( z1 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( z2 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
case EAST:
|
||||
uv.u1 = texture.getInterpolatedU( 16 - z2 * 16 );
|
||||
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
|
||||
uv.u2 = texture.getInterpolatedU( 16 - z1 * 16 );
|
||||
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
|
||||
break;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
private UvVector getStandardUv(Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2,
|
||||
float y2, float z2) {
|
||||
UvVector uv = new UvVector();
|
||||
switch (face) {
|
||||
case DOWN:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - z1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - z2 * 16);
|
||||
break;
|
||||
case UP:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(z1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(z2 * 16);
|
||||
break;
|
||||
case NORTH:
|
||||
uv.u1 = texture.getInterpolatedU(16 - x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(16 - x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case SOUTH:
|
||||
uv.u1 = texture.getInterpolatedU(x1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(x2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case WEST:
|
||||
uv.u1 = texture.getInterpolatedU(z1 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(z2 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
case EAST:
|
||||
uv.u1 = texture.getInterpolatedU(16 - z2 * 16);
|
||||
uv.v1 = texture.getInterpolatedV(16 - y1 * 16);
|
||||
uv.u2 = texture.getInterpolatedU(16 - z1 * 16);
|
||||
uv.v2 = texture.getInterpolatedV(16 - y2 * 16);
|
||||
break;
|
||||
}
|
||||
return uv;
|
||||
}
|
||||
|
||||
// uv.u1, uv.v1
|
||||
private void putVertexTL( BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv )
|
||||
{
|
||||
float u, v;
|
||||
// uv.u1, uv.v1
|
||||
private void putVertexTL(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
|
||||
float u, v;
|
||||
|
||||
switch( this.uvRotations[face.ordinal()] )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
}
|
||||
switch (this.uvRotations[face.ordinal()]) {
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
}
|
||||
|
||||
this.putVertex( builder, face, x, y, z, u, v );
|
||||
}
|
||||
this.putVertex(builder, face, x, y, z, u, v);
|
||||
}
|
||||
|
||||
// uv.u2, uv.v1
|
||||
private void putVertexTR( BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv )
|
||||
{
|
||||
float u, v;
|
||||
// uv.u2, uv.v1
|
||||
private void putVertexTR(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
|
||||
float u, v;
|
||||
|
||||
switch( this.uvRotations[face.ordinal()] )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
}
|
||||
this.putVertex( builder, face, x, y, z, u, v );
|
||||
}
|
||||
switch (this.uvRotations[face.ordinal()]) {
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
}
|
||||
this.putVertex(builder, face, x, y, z, u, v);
|
||||
}
|
||||
|
||||
// uv.u2, uv.v2
|
||||
private void putVertexBR( BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv )
|
||||
{
|
||||
// uv.u2, uv.v2
|
||||
private void putVertexBR(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
|
||||
|
||||
float u;
|
||||
float v;
|
||||
float u;
|
||||
float v;
|
||||
|
||||
switch( this.uvRotations[face.ordinal()] )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
}
|
||||
switch (this.uvRotations[face.ordinal()]) {
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
}
|
||||
|
||||
this.putVertex( builder, face, x, y, z, u, v );
|
||||
}
|
||||
this.putVertex(builder, face, x, y, z, u, v);
|
||||
}
|
||||
|
||||
// uv.u1, uv.v2
|
||||
private void putVertexBL( BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv )
|
||||
{
|
||||
// uv.u1, uv.v2
|
||||
private void putVertexBL(BakedQuadBuilder builder, Direction face, float x, float y, float z, UvVector uv) {
|
||||
|
||||
float u;
|
||||
float v;
|
||||
float u;
|
||||
float v;
|
||||
|
||||
switch( this.uvRotations[face.ordinal()] )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
}
|
||||
switch (this.uvRotations[face.ordinal()]) {
|
||||
default:
|
||||
case 0:
|
||||
u = uv.u1;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 1: // 90° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v2;
|
||||
break;
|
||||
case 2: // 180° clockwise
|
||||
u = uv.u2;
|
||||
v = uv.v1;
|
||||
break;
|
||||
case 3: // 270° clockwise
|
||||
u = uv.u1;
|
||||
v = uv.v1;
|
||||
break;
|
||||
}
|
||||
|
||||
this.putVertex( builder, face, x, y, z, u, v );
|
||||
}
|
||||
this.putVertex(builder, face, x, y, z, u, v);
|
||||
}
|
||||
|
||||
private void putVertex( BakedQuadBuilder builder, Direction face, float x, float y, float z, float u, float v )
|
||||
{
|
||||
VertexFormat format = builder.getVertexFormat();
|
||||
private void putVertex(BakedQuadBuilder builder, Direction face, float x, float y, float z, float u, float v) {
|
||||
VertexFormat format = builder.getVertexFormat();
|
||||
|
||||
List<VertexFormatElement> elements = format.getElements();
|
||||
for( int i = 0; i < elements.size(); i++ )
|
||||
{
|
||||
VertexFormatElement e = elements.get( i );
|
||||
switch( e.getUsage() )
|
||||
{
|
||||
case POSITION:
|
||||
builder.put( i, x, y, z );
|
||||
break;
|
||||
case NORMAL:
|
||||
builder.put( i, face.getXOffset(), face.getYOffset(), face.getZOffset() );
|
||||
break;
|
||||
case COLOR:
|
||||
// Color format is RGBA
|
||||
float r = ( this.color >> 16 & 0xFF ) / 255f;
|
||||
float g = ( this.color >> 8 & 0xFF ) / 255f;
|
||||
float b = ( this.color & 0xFF ) / 255f;
|
||||
float a = ( this.color >> 24 & 0xFF ) / 255f;
|
||||
builder.put( i, r, g, b, a );
|
||||
break;
|
||||
case UV:
|
||||
if( e.getIndex() == 0 )
|
||||
{
|
||||
builder.put( i, u, v );
|
||||
break;
|
||||
}
|
||||
else if( e.getIndex() == 2 && renderFullBright )
|
||||
{
|
||||
// Force Brightness to 15, this is for full bright mode
|
||||
// this vertex element will only be present in that case
|
||||
final float lightMapU = (float) ( 15 * 0x20 ) / 0xFFFF;
|
||||
final float lightMapV = (float) ( 15 * 0x20 ) / 0xFFFF;
|
||||
builder.put( i, lightMapU, lightMapV );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
builder.put( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<VertexFormatElement> elements = format.getElements();
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
VertexFormatElement e = elements.get(i);
|
||||
switch (e.getUsage()) {
|
||||
case POSITION:
|
||||
builder.put(i, x, y, z);
|
||||
break;
|
||||
case NORMAL:
|
||||
builder.put(i, face.getXOffset(), face.getYOffset(), face.getZOffset());
|
||||
break;
|
||||
case COLOR:
|
||||
// Color format is RGBA
|
||||
float r = (this.color >> 16 & 0xFF) / 255f;
|
||||
float g = (this.color >> 8 & 0xFF) / 255f;
|
||||
float b = (this.color & 0xFF) / 255f;
|
||||
float a = (this.color >> 24 & 0xFF) / 255f;
|
||||
builder.put(i, r, g, b, a);
|
||||
break;
|
||||
case UV:
|
||||
if (e.getIndex() == 0) {
|
||||
builder.put(i, u, v);
|
||||
break;
|
||||
} else if (e.getIndex() == 2 && renderFullBright) {
|
||||
// Force Brightness to 15, this is for full bright mode
|
||||
// this vertex element will only be present in that case
|
||||
final float lightMapU = (float) (15 * 0x20) / 0xFFFF;
|
||||
final float lightMapV = (float) (15 * 0x20) / 0xFFFF;
|
||||
builder.put(i, lightMapU, lightMapV);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
builder.put(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTexture( TextureAtlasSprite texture )
|
||||
{
|
||||
for( Direction face : Direction.values() )
|
||||
{
|
||||
this.textures.put( face, texture );
|
||||
}
|
||||
}
|
||||
public void setTexture(TextureAtlasSprite texture) {
|
||||
for (Direction face : Direction.values()) {
|
||||
this.textures.put(face, texture);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTextures( TextureAtlasSprite up, TextureAtlasSprite down, TextureAtlasSprite north, TextureAtlasSprite south, TextureAtlasSprite east, TextureAtlasSprite west )
|
||||
{
|
||||
this.textures.put( Direction.UP, up );
|
||||
this.textures.put( Direction.DOWN, down );
|
||||
this.textures.put( Direction.NORTH, north );
|
||||
this.textures.put( Direction.SOUTH, south );
|
||||
this.textures.put( Direction.EAST, east );
|
||||
this.textures.put( Direction.WEST, west );
|
||||
}
|
||||
public void setTextures(TextureAtlasSprite up, TextureAtlasSprite down, TextureAtlasSprite north,
|
||||
TextureAtlasSprite south, TextureAtlasSprite east, TextureAtlasSprite west) {
|
||||
this.textures.put(Direction.UP, up);
|
||||
this.textures.put(Direction.DOWN, down);
|
||||
this.textures.put(Direction.NORTH, north);
|
||||
this.textures.put(Direction.SOUTH, south);
|
||||
this.textures.put(Direction.EAST, east);
|
||||
this.textures.put(Direction.WEST, west);
|
||||
}
|
||||
|
||||
public void setTexture( Direction facing, TextureAtlasSprite sprite )
|
||||
{
|
||||
this.textures.put( facing, sprite );
|
||||
}
|
||||
public void setTexture(Direction facing, TextureAtlasSprite sprite) {
|
||||
this.textures.put(facing, sprite);
|
||||
}
|
||||
|
||||
public void setDrawFaces( EnumSet<Direction> drawFaces )
|
||||
{
|
||||
this.drawFaces = drawFaces;
|
||||
}
|
||||
public void setDrawFaces(EnumSet<Direction> drawFaces) {
|
||||
this.drawFaces = drawFaces;
|
||||
}
|
||||
|
||||
public void setColor( int color )
|
||||
{
|
||||
this.color = color;
|
||||
}
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the vertex color for future vertices to the given RGB value, and forces the alpha component to 255.
|
||||
*/
|
||||
public void setColorRGB( int color )
|
||||
{
|
||||
this.setColor( color | 0xFF000000 );
|
||||
}
|
||||
/**
|
||||
* Sets the vertex color for future vertices to the given RGB value, and forces
|
||||
* the alpha component to 255.
|
||||
*/
|
||||
public void setColorRGB(int color) {
|
||||
this.setColor(color | 0xFF000000);
|
||||
}
|
||||
|
||||
public void setColorRGB( float r, float g, float b )
|
||||
{
|
||||
this.setColorRGB( (int) ( r * 255 ) << 16 | (int) ( g * 255 ) << 8 | (int) ( b * 255 ) );
|
||||
}
|
||||
public void setColorRGB(float r, float g, float b) {
|
||||
this.setColorRGB((int) (r * 255) << 16 | (int) (g * 255) << 8 | (int) (b * 255));
|
||||
}
|
||||
|
||||
public void setRenderFullBright( boolean renderFullBright )
|
||||
{
|
||||
this.renderFullBright = renderFullBright;
|
||||
}
|
||||
public void setRenderFullBright(boolean renderFullBright) {
|
||||
this.renderFullBright = renderFullBright;
|
||||
}
|
||||
|
||||
public void setCustomUv( Direction facing, float u1, float v1, float u2, float v2 )
|
||||
{
|
||||
this.customUv.put( facing, new Vector4f( u1, v1, u2, v2 ) );
|
||||
}
|
||||
public void setCustomUv(Direction facing, float u1, float v1, float u2, float v2) {
|
||||
this.customUv.put(facing, new Vector4f(u1, v1, u2, v2));
|
||||
}
|
||||
|
||||
public void setUvRotation( Direction facing, int rotation )
|
||||
{
|
||||
if( rotation == 2 )
|
||||
{
|
||||
rotation = 3;
|
||||
}
|
||||
else if( rotation == 3 )
|
||||
{
|
||||
rotation = 2;
|
||||
}
|
||||
Preconditions.checkArgument( rotation >= 0 && rotation <= 3, "rotation" );
|
||||
this.uvRotations[facing.ordinal()] = (byte) rotation;
|
||||
}
|
||||
public void setUvRotation(Direction facing, int rotation) {
|
||||
if (rotation == 2) {
|
||||
rotation = 3;
|
||||
} else if (rotation == 3) {
|
||||
rotation = 2;
|
||||
}
|
||||
Preconditions.checkArgument(rotation >= 0 && rotation <= 3, "rotation");
|
||||
this.uvRotations[facing.ordinal()] = (byte) rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* CubeBuilder uses UV optimized for cables by default.
|
||||
* This switches to standard UV coordinates.
|
||||
*/
|
||||
public void useStandardUV()
|
||||
{
|
||||
this.useStandardUV = true;
|
||||
}
|
||||
/**
|
||||
* CubeBuilder uses UV optimized for cables by default. This switches to
|
||||
* standard UV coordinates.
|
||||
*/
|
||||
public void useStandardUV() {
|
||||
this.useStandardUV = true;
|
||||
}
|
||||
|
||||
public List<BakedQuad> getOutput()
|
||||
{
|
||||
return this.output;
|
||||
}
|
||||
public List<BakedQuad> getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
@@ -30,61 +29,52 @@ import net.minecraft.world.ILightReader;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.lighting.WorldLightManager;
|
||||
|
||||
|
||||
/**
|
||||
* This is used to retrieve the ExtendedState of a block for facade rendering.
|
||||
* It fakes the block at BlockPos provided as the BlockState provided.
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBlockAccess implements ILightReader
|
||||
{
|
||||
public class FacadeBlockAccess implements ILightReader {
|
||||
|
||||
private final ILightReader world;
|
||||
private final BlockPos pos;
|
||||
private final Direction side;
|
||||
private final BlockState state;
|
||||
private final ILightReader world;
|
||||
private final BlockPos pos;
|
||||
private final Direction side;
|
||||
private final BlockState state;
|
||||
|
||||
public FacadeBlockAccess( ILightReader world, BlockPos pos, Direction side, BlockState state )
|
||||
{
|
||||
this.world = world;
|
||||
this.pos = pos;
|
||||
this.side = side;
|
||||
this.state = state;
|
||||
}
|
||||
public FacadeBlockAccess(ILightReader world, BlockPos pos, Direction side, BlockState state) {
|
||||
this.world = world;
|
||||
this.pos = pos;
|
||||
this.side = side;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TileEntity getTileEntity( BlockPos pos )
|
||||
{
|
||||
return this.world.getTileEntity( pos );
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public TileEntity getTileEntity(BlockPos pos) {
|
||||
return this.world.getTileEntity(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState( BlockPos pos )
|
||||
{
|
||||
if( this.pos == pos )
|
||||
{
|
||||
return this.state;
|
||||
}
|
||||
return this.world.getBlockState( pos );
|
||||
}
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
if (this.pos == pos) {
|
||||
return this.state;
|
||||
}
|
||||
return this.world.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidState getFluidState( BlockPos pos )
|
||||
{
|
||||
return world.getFluidState( pos );
|
||||
}
|
||||
@Override
|
||||
public IFluidState getFluidState(BlockPos pos) {
|
||||
return world.getFluidState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldLightManager getLightManager()
|
||||
{
|
||||
return world.getLightManager();
|
||||
}
|
||||
@Override
|
||||
public WorldLightManager getLightManager() {
|
||||
return world.getLightManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockColor( BlockPos blockPosIn, ColorResolver colorResolverIn )
|
||||
{
|
||||
return world.getBlockColor( blockPosIn, colorResolverIn );
|
||||
}
|
||||
@Override
|
||||
public int getBlockColor(BlockPos blockPosIn, ColorResolver colorResolverIn) {
|
||||
return world.getBlockColor(blockPosIn, colorResolverIn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -35,8 +34,8 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BlockRendererDispatcher;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.color.BlockColors;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -64,420 +63,374 @@ import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadFaceStr
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadReInterpolator;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadTinter;
|
||||
|
||||
|
||||
/**
|
||||
* The FacadeBuilder builds for facades..
|
||||
*
|
||||
* @author covers1624
|
||||
*/
|
||||
public class FacadeBuilder
|
||||
{
|
||||
public class FacadeBuilder {
|
||||
|
||||
public static final double THICK_THICKNESS = 2D / 16D;
|
||||
public static final double THIN_THICKNESS = 1D / 16D;
|
||||
public static final double THICK_THICKNESS = 2D / 16D;
|
||||
public static final double THIN_THICKNESS = 1D / 16D;
|
||||
|
||||
public static final AxisAlignedBB[] THICK_FACADE_BOXES = new AxisAlignedBB[] {
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0 )
|
||||
};
|
||||
public static final AxisAlignedBB[] THICK_FACADE_BOXES = new AxisAlignedBB[] {
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, THICK_THICKNESS, 1.0),
|
||||
new AxisAlignedBB(0.0, 1.0 - THICK_THICKNESS, 0.0, 1.0, 1.0, 1.0),
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 1.0, THICK_THICKNESS),
|
||||
new AxisAlignedBB(0.0, 0.0, 1.0 - THICK_THICKNESS, 1.0, 1.0, 1.0),
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, THICK_THICKNESS, 1.0, 1.0),
|
||||
new AxisAlignedBB(1.0 - THICK_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
|
||||
|
||||
public static final AxisAlignedBB[] THIN_FACADE_BOXES = new AxisAlignedBB[] {
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0 ),
|
||||
new AxisAlignedBB( 1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0 )
|
||||
};
|
||||
public static final AxisAlignedBB[] THIN_FACADE_BOXES = new AxisAlignedBB[] {
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, THIN_THICKNESS, 1.0),
|
||||
new AxisAlignedBB(0.0, 1.0 - THIN_THICKNESS, 0.0, 1.0, 1.0, 1.0),
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 1.0, THIN_THICKNESS),
|
||||
new AxisAlignedBB(0.0, 0.0, 1.0 - THIN_THICKNESS, 1.0, 1.0, 1.0),
|
||||
new AxisAlignedBB(0.0, 0.0, 0.0, THIN_THICKNESS, 1.0, 1.0),
|
||||
new AxisAlignedBB(1.0 - THIN_THICKNESS, 0.0, 0.0, 1.0, 1.0, 1.0) };
|
||||
|
||||
private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial( () -> BakedPipeline.builder()
|
||||
// Clamper is responsible for clamping the vertex to the bounds specified.
|
||||
.addElement( "clamper", QuadClamper.FACTORY )
|
||||
// Strips faces if they match a mask.
|
||||
.addElement( "face_stripper", QuadFaceStripper.FACTORY )
|
||||
// Kicks the edge inner corners in, solves Z fighting
|
||||
.addElement( "corner_kicker", QuadCornerKicker.FACTORY )
|
||||
// Re-Interpolates the UV's for the quad.
|
||||
.addElement( "interp", QuadReInterpolator.FACTORY )
|
||||
// Tints the quad if we need it to. Disabled by default.
|
||||
.addElement( "tinter", QuadTinter.FACTORY, false )
|
||||
// Overrides the quad's alpha if we are forcing transparent facades.
|
||||
.addElement( "transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride( 0x4C / 255F ) )
|
||||
.build()//
|
||||
);
|
||||
private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial( Quad::new );
|
||||
private final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> BakedPipeline.builder()
|
||||
// Clamper is responsible for clamping the vertex to the bounds specified.
|
||||
.addElement("clamper", QuadClamper.FACTORY)
|
||||
// Strips faces if they match a mask.
|
||||
.addElement("face_stripper", QuadFaceStripper.FACTORY)
|
||||
// Kicks the edge inner corners in, solves Z fighting
|
||||
.addElement("corner_kicker", QuadCornerKicker.FACTORY)
|
||||
// Re-Interpolates the UV's for the quad.
|
||||
.addElement("interp", QuadReInterpolator.FACTORY)
|
||||
// Tints the quad if we need it to. Disabled by default.
|
||||
.addElement("tinter", QuadTinter.FACTORY, false)
|
||||
// Overrides the quad's alpha if we are forcing transparent facades.
|
||||
.addElement("transparent", QuadAlphaOverride.FACTORY, false, e -> e.setAlphaOverride(0x4C / 255F)).build()//
|
||||
);
|
||||
private final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
|
||||
|
||||
public void buildFacadeQuads( RenderType layer, CableBusRenderState renderState, Random rand, List<BakedQuad> quads, Function<ResourceLocation, IBakedModel> modelLookup )
|
||||
{
|
||||
BakedPipeline pipeline = this.pipelines.get();
|
||||
Quad collectorQuad = this.collectors.get();
|
||||
boolean transparent = AEApi.instance().partHelper().getCableRenderMode().transparentFacades;
|
||||
Map<Direction, FacadeRenderState> facadeStates = renderState.getFacades();
|
||||
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
|
||||
Set<Direction> sidesWithParts = renderState.getAttachments().keySet();
|
||||
ILightReader parentWorld = renderState.getWorld();
|
||||
BlockPos pos = renderState.getPos();
|
||||
BlockColors blockColors = Minecraft.getInstance().getBlockColors();
|
||||
boolean thinFacades = isUseThinFacades( partBoxes );
|
||||
public void buildFacadeQuads(RenderType layer, CableBusRenderState renderState, Random rand, List<BakedQuad> quads,
|
||||
Function<ResourceLocation, IBakedModel> modelLookup) {
|
||||
BakedPipeline pipeline = this.pipelines.get();
|
||||
Quad collectorQuad = this.collectors.get();
|
||||
boolean transparent = AEApi.instance().partHelper().getCableRenderMode().transparentFacades;
|
||||
Map<Direction, FacadeRenderState> facadeStates = renderState.getFacades();
|
||||
List<AxisAlignedBB> partBoxes = renderState.getBoundingBoxes();
|
||||
Set<Direction> sidesWithParts = renderState.getAttachments().keySet();
|
||||
ILightReader parentWorld = renderState.getWorld();
|
||||
BlockPos pos = renderState.getPos();
|
||||
BlockColors blockColors = Minecraft.getInstance().getBlockColors();
|
||||
boolean thinFacades = isUseThinFacades(partBoxes);
|
||||
|
||||
for( Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet() )
|
||||
{
|
||||
Direction side = entry.getKey();
|
||||
int sideIndex = side.ordinal();
|
||||
FacadeRenderState facadeRenderState = entry.getValue();
|
||||
boolean renderStilt = !sidesWithParts.contains( side );
|
||||
if( layer == RenderType.getCutout() && renderStilt )
|
||||
{
|
||||
for( ResourceLocation part : PartCableAnchor.FACADE_MODELS.getModels() )
|
||||
{
|
||||
IBakedModel partModel = modelLookup.apply( part );
|
||||
QuadRotator rotator = new QuadRotator();
|
||||
quads.addAll( rotator.rotateQuads( gatherQuads( partModel, null, rand, EmptyModelData.INSTANCE ), side, Direction.UP ) );
|
||||
}
|
||||
}
|
||||
// If we are forcing transparency and this isn't the Translucent layer.
|
||||
if( transparent && layer != RenderType.getTranslucent() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (Entry<Direction, FacadeRenderState> entry : facadeStates.entrySet()) {
|
||||
Direction side = entry.getKey();
|
||||
int sideIndex = side.ordinal();
|
||||
FacadeRenderState facadeRenderState = entry.getValue();
|
||||
boolean renderStilt = !sidesWithParts.contains(side);
|
||||
if (layer == RenderType.getCutout() && renderStilt) {
|
||||
for (ResourceLocation part : PartCableAnchor.FACADE_MODELS.getModels()) {
|
||||
IBakedModel partModel = modelLookup.apply(part);
|
||||
QuadRotator rotator = new QuadRotator();
|
||||
quads.addAll(rotator.rotateQuads(gatherQuads(partModel, null, rand, EmptyModelData.INSTANCE), side,
|
||||
Direction.UP));
|
||||
}
|
||||
}
|
||||
// If we are forcing transparency and this isn't the Translucent layer.
|
||||
if (transparent && layer != RenderType.getTranslucent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockState blockState = facadeRenderState.getSourceBlock();
|
||||
// If we aren't forcing transparency let the block decide if it should render.
|
||||
if( !transparent && layer != null )
|
||||
{
|
||||
if( !RenderTypeLookup.canRenderInLayer( blockState, layer ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
BlockState blockState = facadeRenderState.getSourceBlock();
|
||||
// If we aren't forcing transparency let the block decide if it should render.
|
||||
if (!transparent && layer != null) {
|
||||
if (!RenderTypeLookup.canRenderInLayer(blockState, layer)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
AxisAlignedBB fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
|
||||
AxisAlignedBB facadeBox = fullBounds;
|
||||
// If we are a transparent facade, we need to modify out BB.
|
||||
if( facadeRenderState.isTransparent() )
|
||||
{
|
||||
double offset = thinFacades ? THIN_THICKNESS : THICK_THICKNESS;
|
||||
AEAxisAlignedBB tmpBB = null;
|
||||
for( Direction face : Direction.values() )
|
||||
{
|
||||
// Only faces that aren't on our axis
|
||||
if( face.getAxis() != side.getAxis() )
|
||||
{
|
||||
FacadeRenderState otherState = facadeStates.get( face );
|
||||
if( otherState != null && !otherState.isTransparent() )
|
||||
{
|
||||
if( tmpBB == null )
|
||||
{
|
||||
tmpBB = AEAxisAlignedBB.fromBounds( facadeBox );
|
||||
}
|
||||
switch( face )
|
||||
{
|
||||
case DOWN:
|
||||
tmpBB.minY += offset;
|
||||
break;
|
||||
case UP:
|
||||
tmpBB.maxY -= offset;
|
||||
break;
|
||||
case NORTH:
|
||||
tmpBB.minZ += offset;
|
||||
break;
|
||||
case SOUTH:
|
||||
tmpBB.maxZ -= offset;
|
||||
break;
|
||||
case WEST:
|
||||
tmpBB.minX += offset;
|
||||
break;
|
||||
case EAST:
|
||||
tmpBB.maxX -= offset;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException( "Switch falloff. " + String.valueOf( face ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( tmpBB != null )
|
||||
{
|
||||
facadeBox = tmpBB.getBoundingBox();
|
||||
}
|
||||
}
|
||||
AxisAlignedBB fullBounds = thinFacades ? THIN_FACADE_BOXES[sideIndex] : THICK_FACADE_BOXES[sideIndex];
|
||||
AxisAlignedBB facadeBox = fullBounds;
|
||||
// If we are a transparent facade, we need to modify out BB.
|
||||
if (facadeRenderState.isTransparent()) {
|
||||
double offset = thinFacades ? THIN_THICKNESS : THICK_THICKNESS;
|
||||
AEAxisAlignedBB tmpBB = null;
|
||||
for (Direction face : Direction.values()) {
|
||||
// Only faces that aren't on our axis
|
||||
if (face.getAxis() != side.getAxis()) {
|
||||
FacadeRenderState otherState = facadeStates.get(face);
|
||||
if (otherState != null && !otherState.isTransparent()) {
|
||||
if (tmpBB == null) {
|
||||
tmpBB = AEAxisAlignedBB.fromBounds(facadeBox);
|
||||
}
|
||||
switch (face) {
|
||||
case DOWN:
|
||||
tmpBB.minY += offset;
|
||||
break;
|
||||
case UP:
|
||||
tmpBB.maxY -= offset;
|
||||
break;
|
||||
case NORTH:
|
||||
tmpBB.minZ += offset;
|
||||
break;
|
||||
case SOUTH:
|
||||
tmpBB.maxZ -= offset;
|
||||
break;
|
||||
case WEST:
|
||||
tmpBB.minX += offset;
|
||||
break;
|
||||
case EAST:
|
||||
tmpBB.maxX -= offset;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Switch falloff. " + String.valueOf(face));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmpBB != null) {
|
||||
facadeBox = tmpBB.getBoundingBox();
|
||||
}
|
||||
}
|
||||
|
||||
AEAxisAlignedBB cutOutBox = getCutOutBox( facadeBox, partBoxes );
|
||||
List<AxisAlignedBB> holeStrips = getBoxes( facadeBox, cutOutBox, side.getAxis() );
|
||||
ILightReader facadeAccess = new FacadeBlockAccess( parentWorld, pos, side, blockState );
|
||||
AEAxisAlignedBB cutOutBox = getCutOutBox(facadeBox, partBoxes);
|
||||
List<AxisAlignedBB> holeStrips = getBoxes(facadeBox, cutOutBox, side.getAxis());
|
||||
ILightReader facadeAccess = new FacadeBlockAccess(parentWorld, pos, side, blockState);
|
||||
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
||||
IBakedModel model = dispatcher.getModelForState( blockState );
|
||||
IModelData modelData = model.getModelData( facadeAccess, pos, blockState, EmptyModelData.INSTANCE );
|
||||
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
|
||||
IBakedModel model = dispatcher.getModelForState(blockState);
|
||||
IModelData modelData = model.getModelData(facadeAccess, pos, blockState, EmptyModelData.INSTANCE);
|
||||
|
||||
List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// If we are forcing transparent facades, fake the render layer, and grab all quads.
|
||||
if( transparent || layer == null )
|
||||
{
|
||||
for( RenderType forcedLayer : RenderType.getBlockRenderTypes() )
|
||||
{
|
||||
// Check if the block renders on the layer we want to force.
|
||||
if( RenderTypeLookup.canRenderInLayer( blockState, forcedLayer ) )
|
||||
{
|
||||
// Force the layer and gather quads.
|
||||
ForgeHooksClient.setRenderLayer( forcedLayer );
|
||||
modelQuads.addAll( gatherQuads( model, blockState, rand, modelData) );
|
||||
}
|
||||
}
|
||||
List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
// If we are forcing transparent facades, fake the render layer, and grab all
|
||||
// quads.
|
||||
if (transparent || layer == null) {
|
||||
for (RenderType forcedLayer : RenderType.getBlockRenderTypes()) {
|
||||
// Check if the block renders on the layer we want to force.
|
||||
if (RenderTypeLookup.canRenderInLayer(blockState, forcedLayer)) {
|
||||
// Force the layer and gather quads.
|
||||
ForgeHooksClient.setRenderLayer(forcedLayer);
|
||||
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
}
|
||||
}
|
||||
|
||||
// Reset.
|
||||
ForgeHooksClient.setRenderLayer( layer );
|
||||
}
|
||||
else
|
||||
{
|
||||
modelQuads.addAll( gatherQuads( model, blockState, rand, modelData ) );
|
||||
}
|
||||
// Reset.
|
||||
ForgeHooksClient.setRenderLayer(layer);
|
||||
} else {
|
||||
modelQuads.addAll(gatherQuads(model, blockState, rand, modelData));
|
||||
}
|
||||
|
||||
// No quads.. Cool, next!
|
||||
if( modelQuads.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// No quads.. Cool, next!
|
||||
if (modelQuads.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grab out pipeline elements.
|
||||
QuadClamper clamper = pipeline.getElement( "clamper", QuadClamper.class );
|
||||
QuadFaceStripper edgeStripper = pipeline.getElement( "face_stripper", QuadFaceStripper.class );
|
||||
QuadTinter tinter = pipeline.getElement( "tinter", QuadTinter.class );
|
||||
QuadCornerKicker kicker = pipeline.getElement( "corner_kicker", QuadCornerKicker.class );
|
||||
// Grab out pipeline elements.
|
||||
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
QuadFaceStripper edgeStripper = pipeline.getElement("face_stripper", QuadFaceStripper.class);
|
||||
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
QuadCornerKicker kicker = pipeline.getElement("corner_kicker", QuadCornerKicker.class);
|
||||
|
||||
// Set global element states.
|
||||
// Set global element states.
|
||||
|
||||
// calculate the side mask.
|
||||
int facadeMask = 0;
|
||||
for( Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet() )
|
||||
{
|
||||
Direction s = ent.getKey();
|
||||
if( s.getAxis() != side.getAxis() )
|
||||
{
|
||||
FacadeRenderState otherState = ent.getValue();
|
||||
if( !otherState.isTransparent() )
|
||||
{
|
||||
facadeMask |= 1 << s.ordinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Setup the edge stripper.
|
||||
edgeStripper.setBounds( fullBounds );
|
||||
edgeStripper.setMask( facadeMask );
|
||||
// calculate the side mask.
|
||||
int facadeMask = 0;
|
||||
for (Entry<Direction, FacadeRenderState> ent : facadeStates.entrySet()) {
|
||||
Direction s = ent.getKey();
|
||||
if (s.getAxis() != side.getAxis()) {
|
||||
FacadeRenderState otherState = ent.getValue();
|
||||
if (!otherState.isTransparent()) {
|
||||
facadeMask |= 1 << s.ordinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Setup the edge stripper.
|
||||
edgeStripper.setBounds(fullBounds);
|
||||
edgeStripper.setMask(facadeMask);
|
||||
|
||||
// Setup the kicker.
|
||||
kicker.setSide( sideIndex );
|
||||
kicker.setFacadeMask( facadeMask );
|
||||
kicker.setBox( fullBounds );
|
||||
kicker.setThickness( thinFacades ? THIN_THICKNESS : THICK_THICKNESS );
|
||||
// Setup the kicker.
|
||||
kicker.setSide(sideIndex);
|
||||
kicker.setFacadeMask(facadeMask);
|
||||
kicker.setBox(fullBounds);
|
||||
kicker.setThickness(thinFacades ? THIN_THICKNESS : THICK_THICKNESS);
|
||||
|
||||
for( BakedQuad quad : modelQuads )
|
||||
{
|
||||
// lookup the format in CachedFormat.
|
||||
CachedFormat format = CachedFormat.lookup( DefaultVertexFormats.BLOCK );
|
||||
// If this quad has a tint index, setup the tinter.
|
||||
if( quad.hasTintIndex() )
|
||||
{
|
||||
tinter.setTint( blockColors.getColor( blockState, facadeAccess, pos, quad.getTintIndex() ) );
|
||||
}
|
||||
for( AxisAlignedBB box : holeStrips )
|
||||
{
|
||||
// setup the clamper for this box
|
||||
clamper.setClampBounds( box );
|
||||
// Reset the pipeline, clears all enabled/disabled states.
|
||||
pipeline.reset( format );
|
||||
// Reset out collector.
|
||||
collectorQuad.reset( format );
|
||||
// Enable / disable the optional elements
|
||||
pipeline.setElementState( "tinter", quad.hasTintIndex() );
|
||||
pipeline.setElementState( "transparent", transparent );
|
||||
// Prepare the pipeline for a quad.
|
||||
pipeline.prepare( collectorQuad );
|
||||
for (BakedQuad quad : modelQuads) {
|
||||
// lookup the format in CachedFormat.
|
||||
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
|
||||
// If this quad has a tint index, setup the tinter.
|
||||
if (quad.hasTintIndex()) {
|
||||
tinter.setTint(blockColors.getColor(blockState, facadeAccess, pos, quad.getTintIndex()));
|
||||
}
|
||||
for (AxisAlignedBB box : holeStrips) {
|
||||
// setup the clamper for this box
|
||||
clamper.setClampBounds(box);
|
||||
// Reset the pipeline, clears all enabled/disabled states.
|
||||
pipeline.reset(format);
|
||||
// Reset out collector.
|
||||
collectorQuad.reset(format);
|
||||
// Enable / disable the optional elements
|
||||
pipeline.setElementState("tinter", quad.hasTintIndex());
|
||||
pipeline.setElementState("transparent", transparent);
|
||||
// Prepare the pipeline for a quad.
|
||||
pipeline.prepare(collectorQuad);
|
||||
|
||||
// Pipe our quad into the pipeline.
|
||||
quad.pipe( pipeline );
|
||||
// Check if the collector got any data.
|
||||
if( collectorQuad.full )
|
||||
{
|
||||
// Add the result.
|
||||
quads.add( collectorQuad.bake() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pipe our quad into the pipeline.
|
||||
quad.pipe(pipeline);
|
||||
// Check if the collector got any data.
|
||||
if (collectorQuad.full) {
|
||||
// Add the result.
|
||||
quads.add(collectorQuad.bake());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is slow, so should be cached.
|
||||
*
|
||||
* @return The model.
|
||||
*/
|
||||
public List<BakedQuad> buildFacadeItemQuads( ItemStack textureItem, Direction side )
|
||||
{
|
||||
List<BakedQuad> facadeQuads = new ArrayList<>();
|
||||
IBakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelWithOverrides( textureItem, null, null );
|
||||
List<BakedQuad> modelQuads = gatherQuads( model, null, new Random(), EmptyModelData.INSTANCE );
|
||||
/**
|
||||
* This is slow, so should be cached.
|
||||
*
|
||||
* @return The model.
|
||||
*/
|
||||
public List<BakedQuad> buildFacadeItemQuads(ItemStack textureItem, Direction side) {
|
||||
List<BakedQuad> facadeQuads = new ArrayList<>();
|
||||
IBakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelWithOverrides(textureItem, null,
|
||||
null);
|
||||
List<BakedQuad> modelQuads = gatherQuads(model, null, new Random(), EmptyModelData.INSTANCE);
|
||||
|
||||
BakedPipeline pipeline = this.pipelines.get();
|
||||
Quad collectorQuad = this.collectors.get();
|
||||
BakedPipeline pipeline = this.pipelines.get();
|
||||
Quad collectorQuad = this.collectors.get();
|
||||
|
||||
// Grab pipeline elements.
|
||||
QuadClamper clamper = pipeline.getElement( "clamper", QuadClamper.class );
|
||||
QuadTinter tinter = pipeline.getElement( "tinter", QuadTinter.class );
|
||||
// Grab pipeline elements.
|
||||
QuadClamper clamper = pipeline.getElement("clamper", QuadClamper.class);
|
||||
QuadTinter tinter = pipeline.getElement("tinter", QuadTinter.class);
|
||||
|
||||
for( BakedQuad quad : modelQuads )
|
||||
{
|
||||
// Lookup the CachedFormat for this quads format.
|
||||
CachedFormat format = CachedFormat.lookup( DefaultVertexFormats.BLOCK );
|
||||
// Reset the pipeline.
|
||||
pipeline.reset( format );
|
||||
// Reset the collector.
|
||||
collectorQuad.reset( format );
|
||||
// If we have a tint index, setup the tinter and enable it.
|
||||
if( quad.hasTintIndex() )
|
||||
{
|
||||
tinter.setTint( Minecraft.getInstance().getItemColors().getColor( textureItem, quad.getTintIndex() ) );
|
||||
pipeline.enableElement( "tinter" );
|
||||
}
|
||||
// Disable elements we don't need for items.
|
||||
pipeline.disableElement( "face_stripper" );
|
||||
pipeline.disableElement( "corner_kicker" );
|
||||
// Setup the clamper
|
||||
clamper.setClampBounds( THICK_FACADE_BOXES[side.ordinal()] );
|
||||
// Prepare the pipeline.
|
||||
pipeline.prepare( collectorQuad );
|
||||
// Pipe our quad into the pipeline.
|
||||
quad.pipe( pipeline );
|
||||
// Check the collector for data and add the quad if there was.
|
||||
if( collectorQuad.full )
|
||||
{
|
||||
facadeQuads.add( collectorQuad.bake() );
|
||||
}
|
||||
}
|
||||
return facadeQuads;
|
||||
}
|
||||
for (BakedQuad quad : modelQuads) {
|
||||
// Lookup the CachedFormat for this quads format.
|
||||
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
|
||||
// Reset the pipeline.
|
||||
pipeline.reset(format);
|
||||
// Reset the collector.
|
||||
collectorQuad.reset(format);
|
||||
// If we have a tint index, setup the tinter and enable it.
|
||||
if (quad.hasTintIndex()) {
|
||||
tinter.setTint(Minecraft.getInstance().getItemColors().getColor(textureItem, quad.getTintIndex()));
|
||||
pipeline.enableElement("tinter");
|
||||
}
|
||||
// Disable elements we don't need for items.
|
||||
pipeline.disableElement("face_stripper");
|
||||
pipeline.disableElement("corner_kicker");
|
||||
// Setup the clamper
|
||||
clamper.setClampBounds(THICK_FACADE_BOXES[side.ordinal()]);
|
||||
// Prepare the pipeline.
|
||||
pipeline.prepare(collectorQuad);
|
||||
// Pipe our quad into the pipeline.
|
||||
quad.pipe(pipeline);
|
||||
// Check the collector for data and add the quad if there was.
|
||||
if (collectorQuad.full) {
|
||||
facadeQuads.add(collectorQuad.bake());
|
||||
}
|
||||
}
|
||||
return facadeQuads;
|
||||
}
|
||||
|
||||
// Helper to gather all quads from a model into a list.
|
||||
private static List<BakedQuad> gatherQuads( IBakedModel model, BlockState state, Random rand, IModelData data )
|
||||
{
|
||||
List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
for( Direction face : Direction.values() )
|
||||
{
|
||||
modelQuads.addAll( model.getQuads( state, face, rand, data) );
|
||||
}
|
||||
modelQuads.addAll( model.getQuads( state, null, rand, data ) );
|
||||
return modelQuads;
|
||||
}
|
||||
// Helper to gather all quads from a model into a list.
|
||||
private static List<BakedQuad> gatherQuads(IBakedModel model, BlockState state, Random rand, IModelData data) {
|
||||
List<BakedQuad> modelQuads = new ArrayList<>();
|
||||
for (Direction face : Direction.values()) {
|
||||
modelQuads.addAll(model.getQuads(state, face, rand, data));
|
||||
}
|
||||
modelQuads.addAll(model.getQuads(state, null, rand, data));
|
||||
return modelQuads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the actual facade bounding box, and the bounding boxes of all parts, determine the biggest union of AABB
|
||||
* that intersect with the facade's bounding
|
||||
* box. This AABB will need to be "cut out" when the facade is rendered.
|
||||
*/
|
||||
@Nullable
|
||||
private static AEAxisAlignedBB getCutOutBox( AxisAlignedBB facadeBox, List<AxisAlignedBB> partBoxes )
|
||||
{
|
||||
AEAxisAlignedBB b = null;
|
||||
for( AxisAlignedBB bb : partBoxes )
|
||||
{
|
||||
if( bb.intersects( facadeBox ) )
|
||||
{
|
||||
if( b == null )
|
||||
{
|
||||
b = AEAxisAlignedBB.fromBounds( bb );
|
||||
}
|
||||
else
|
||||
{
|
||||
b.maxX = Math.max( b.maxX, bb.maxX );
|
||||
b.maxY = Math.max( b.maxY, bb.maxY );
|
||||
b.maxZ = Math.max( b.maxZ, bb.maxZ );
|
||||
b.minX = Math.min( b.minX, bb.minX );
|
||||
b.minY = Math.min( b.minY, bb.minY );
|
||||
b.minZ = Math.min( b.minZ, bb.minZ );
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
/**
|
||||
* Given the actual facade bounding box, and the bounding boxes of all parts,
|
||||
* determine the biggest union of AABB that intersect with the facade's bounding
|
||||
* box. This AABB will need to be "cut out" when the facade is rendered.
|
||||
*/
|
||||
@Nullable
|
||||
private static AEAxisAlignedBB getCutOutBox(AxisAlignedBB facadeBox, List<AxisAlignedBB> partBoxes) {
|
||||
AEAxisAlignedBB b = null;
|
||||
for (AxisAlignedBB bb : partBoxes) {
|
||||
if (bb.intersects(facadeBox)) {
|
||||
if (b == null) {
|
||||
b = AEAxisAlignedBB.fromBounds(bb);
|
||||
} else {
|
||||
b.maxX = Math.max(b.maxX, bb.maxX);
|
||||
b.maxY = Math.max(b.maxY, bb.maxY);
|
||||
b.maxZ = Math.max(b.maxZ, bb.maxZ);
|
||||
b.minX = Math.min(b.minX, bb.minX);
|
||||
b.minY = Math.min(b.minY, bb.minY);
|
||||
b.minZ = Math.min(b.minZ, bb.minZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the box segments around the specified hole. If the specified hole is null, a Singleton of the Facade
|
||||
* box is returned.
|
||||
*
|
||||
* @param fb The Facade's box.
|
||||
* @param hole The hole to 'cut'.
|
||||
* @param axis The axis the facade is on.
|
||||
*
|
||||
* @return The box segments.
|
||||
*/
|
||||
private static List<AxisAlignedBB> getBoxes( AxisAlignedBB fb, AEAxisAlignedBB hole, Axis axis )
|
||||
{
|
||||
if( hole == null )
|
||||
{
|
||||
return Collections.singletonList( fb );
|
||||
}
|
||||
List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
switch( axis )
|
||||
{
|
||||
case Y:
|
||||
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, hole.minX, fb.maxY, fb.maxZ ) );
|
||||
boxes.add( new AxisAlignedBB( hole.maxX, fb.minY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
|
||||
/**
|
||||
* Generates the box segments around the specified hole. If the specified hole
|
||||
* is null, a Singleton of the Facade box is returned.
|
||||
*
|
||||
* @param fb The Facade's box.
|
||||
* @param hole The hole to 'cut'.
|
||||
* @param axis The axis the facade is on.
|
||||
*
|
||||
* @return The box segments.
|
||||
*/
|
||||
private static List<AxisAlignedBB> getBoxes(AxisAlignedBB fb, AEAxisAlignedBB hole, Axis axis) {
|
||||
if (hole == null) {
|
||||
return Collections.singletonList(fb);
|
||||
}
|
||||
List<AxisAlignedBB> boxes = new ArrayList<>();
|
||||
switch (axis) {
|
||||
case Y:
|
||||
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, hole.minX, fb.maxY, fb.maxZ));
|
||||
boxes.add(new AxisAlignedBB(hole.maxX, fb.minY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
|
||||
|
||||
boxes.add( new AxisAlignedBB( hole.minX, fb.minY, fb.minZ, hole.maxX, fb.maxY, hole.minZ ) );
|
||||
boxes.add( new AxisAlignedBB( hole.minX, fb.minY, hole.maxZ, hole.maxX, fb.maxY, fb.maxZ ) );
|
||||
boxes.add(new AxisAlignedBB(hole.minX, fb.minY, fb.minZ, hole.maxX, fb.maxY, hole.minZ));
|
||||
boxes.add(new AxisAlignedBB(hole.minX, fb.minY, hole.maxZ, hole.maxX, fb.maxY, fb.maxZ));
|
||||
|
||||
break;
|
||||
case Z:
|
||||
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ ) );
|
||||
boxes.add( new AxisAlignedBB( fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
|
||||
break;
|
||||
case Z:
|
||||
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
|
||||
boxes.add(new AxisAlignedBB(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
|
||||
|
||||
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, fb.minZ, hole.minX, hole.maxY, fb.maxZ ) );
|
||||
boxes.add( new AxisAlignedBB( hole.maxX, hole.minY, fb.minZ, fb.maxX, hole.maxY, fb.maxZ ) );
|
||||
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, fb.minZ, hole.minX, hole.maxY, fb.maxZ));
|
||||
boxes.add(new AxisAlignedBB(hole.maxX, hole.minY, fb.minZ, fb.maxX, hole.maxY, fb.maxZ));
|
||||
|
||||
break;
|
||||
case X:
|
||||
boxes.add( new AxisAlignedBB( fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ ) );
|
||||
boxes.add( new AxisAlignedBB( fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ ) );
|
||||
break;
|
||||
case X:
|
||||
boxes.add(new AxisAlignedBB(fb.minX, fb.minY, fb.minZ, fb.maxX, hole.minY, fb.maxZ));
|
||||
boxes.add(new AxisAlignedBB(fb.minX, hole.maxY, fb.minZ, fb.maxX, fb.maxY, fb.maxZ));
|
||||
|
||||
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, fb.minZ, fb.maxX, hole.maxY, hole.minZ ) );
|
||||
boxes.add( new AxisAlignedBB( fb.minX, hole.minY, hole.maxZ, fb.maxX, hole.maxY, fb.maxZ ) );
|
||||
break;
|
||||
default:
|
||||
// should never happen.
|
||||
throw new RuntimeException( "switch falloff. " + String.valueOf( axis ) );
|
||||
}
|
||||
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, fb.minZ, fb.maxX, hole.maxY, hole.minZ));
|
||||
boxes.add(new AxisAlignedBB(fb.minX, hole.minY, hole.maxZ, fb.maxX, hole.maxY, fb.maxZ));
|
||||
break;
|
||||
default:
|
||||
// should never happen.
|
||||
throw new RuntimeException("switch falloff. " + String.valueOf(axis));
|
||||
}
|
||||
|
||||
return boxes;
|
||||
}
|
||||
return boxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if any of the part's bounding boxes intersects with the outside 2 voxel wide layer. If so, we should
|
||||
* use thinner facades (1 voxel deep).
|
||||
*/
|
||||
private static boolean isUseThinFacades( List<AxisAlignedBB> partBoxes )
|
||||
{
|
||||
final double min = 2.0 / 16.0;
|
||||
final double max = 14.0 / 16.0;
|
||||
/**
|
||||
* Determines if any of the part's bounding boxes intersects with the outside 2
|
||||
* voxel wide layer. If so, we should use thinner facades (1 voxel deep).
|
||||
*/
|
||||
private static boolean isUseThinFacades(List<AxisAlignedBB> partBoxes) {
|
||||
final double min = 2.0 / 16.0;
|
||||
final double max = 14.0 / 16.0;
|
||||
|
||||
for( AxisAlignedBB bb : partBoxes )
|
||||
{
|
||||
int o = 0;
|
||||
o += bb.maxX > max ? 1 : 0;
|
||||
o += bb.maxY > max ? 1 : 0;
|
||||
o += bb.maxZ > max ? 1 : 0;
|
||||
o += bb.minX < min ? 1 : 0;
|
||||
o += bb.minY < min ? 1 : 0;
|
||||
o += bb.minZ < min ? 1 : 0;
|
||||
for (AxisAlignedBB bb : partBoxes) {
|
||||
int o = 0;
|
||||
o += bb.maxX > max ? 1 : 0;
|
||||
o += bb.maxY > max ? 1 : 0;
|
||||
o += bb.maxZ > max ? 1 : 0;
|
||||
o += bb.minX < min ? 1 : 0;
|
||||
o += bb.minY < min ? 1 : 0;
|
||||
o += bb.minZ < min ? 1 : 0;
|
||||
|
||||
if( o >= 2 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (o >= 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,28 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
||||
|
||||
/**
|
||||
* Captures the state required to render a facade properly.
|
||||
*/
|
||||
public class FacadeRenderState
|
||||
{
|
||||
public class FacadeRenderState {
|
||||
|
||||
// The block state to use for rendering this facade
|
||||
private final BlockState sourceBlock;
|
||||
// The block state to use for rendering this facade
|
||||
private final BlockState sourceBlock;
|
||||
|
||||
private final boolean transparent;
|
||||
private final boolean transparent;
|
||||
|
||||
public FacadeRenderState( BlockState sourceBlock, boolean transparent )
|
||||
{
|
||||
this.sourceBlock = sourceBlock;
|
||||
this.transparent = transparent;
|
||||
}
|
||||
public FacadeRenderState(BlockState sourceBlock, boolean transparent) {
|
||||
this.sourceBlock = sourceBlock;
|
||||
this.transparent = transparent;
|
||||
}
|
||||
|
||||
public BlockState getSourceBlock()
|
||||
{
|
||||
return this.sourceBlock;
|
||||
}
|
||||
public BlockState getSourceBlock() {
|
||||
return this.sourceBlock;
|
||||
}
|
||||
|
||||
public boolean isTransparent()
|
||||
{
|
||||
return this.transparent;
|
||||
}
|
||||
public boolean isTransparent() {
|
||||
return this.transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -15,130 +14,104 @@ import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.util.Platform;
|
||||
import net.minecraftforge.client.model.data.IDynamicBakedModel;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.util.Platform;
|
||||
|
||||
public class P2PTunnelFrequencyBakedModel implements IDynamicBakedModel
|
||||
{
|
||||
public class P2PTunnelFrequencyBakedModel implements IDynamicBakedModel {
|
||||
|
||||
private final TextureAtlasSprite texture;
|
||||
private final TextureAtlasSprite texture;
|
||||
|
||||
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize( 100 ).build();
|
||||
private final static Cache<Long, List<BakedQuad>> modelCache = CacheBuilder.newBuilder().maximumSize(100).build();
|
||||
|
||||
private static final int[][] QUAD_OFFSETS = new int[][] {
|
||||
{ 4, 10, 2 },
|
||||
{ 10, 10, 2 },
|
||||
{ 4, 4, 2 },
|
||||
{ 10, 4, 2 }
|
||||
};
|
||||
private static final int[][] QUAD_OFFSETS = new int[][] { { 4, 10, 2 }, { 10, 10, 2 }, { 4, 4, 2 }, { 10, 4, 2 } };
|
||||
|
||||
public P2PTunnelFrequencyBakedModel( final TextureAtlasSprite texture )
|
||||
{
|
||||
this.texture = texture;
|
||||
}
|
||||
public P2PTunnelFrequencyBakedModel(final TextureAtlasSprite texture) {
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BakedQuad> getQuads( BlockState state, Direction side, Random rand, IModelData modelData )
|
||||
{
|
||||
if( side != null || !(modelData instanceof P2PTunnelFrequencyModelData) )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@Override
|
||||
public List<BakedQuad> getQuads(BlockState state, Direction side, Random rand, IModelData modelData) {
|
||||
if (side != null || !(modelData instanceof P2PTunnelFrequencyModelData)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
P2PTunnelFrequencyModelData freqModelData = (P2PTunnelFrequencyModelData) modelData;
|
||||
P2PTunnelFrequencyModelData freqModelData = (P2PTunnelFrequencyModelData) modelData;
|
||||
|
||||
return this.getPartQuads( freqModelData.getFrequency());
|
||||
}
|
||||
return this.getPartQuads(freqModelData.getFrequency());
|
||||
}
|
||||
|
||||
private List<BakedQuad> getQuadsForFrequency( final short frequency, final boolean active )
|
||||
{
|
||||
final AEColor[] colors = Platform.p2p().toColors( frequency );
|
||||
final CubeBuilder cb = new CubeBuilder();
|
||||
private List<BakedQuad> getQuadsForFrequency(final short frequency, final boolean active) {
|
||||
final AEColor[] colors = Platform.p2p().toColors(frequency);
|
||||
final CubeBuilder cb = new CubeBuilder();
|
||||
|
||||
cb.setTexture( this.texture );
|
||||
cb.useStandardUV();
|
||||
cb.setRenderFullBright( active );
|
||||
cb.setTexture(this.texture);
|
||||
cb.useStandardUV();
|
||||
cb.setRenderFullBright(active);
|
||||
|
||||
for( int i = 0; i < 4; ++i )
|
||||
{
|
||||
final int[] offs = QUAD_OFFSETS[i];
|
||||
for( int j = 0; j < 4; ++j )
|
||||
{
|
||||
final AEColor c = colors[j];
|
||||
if( active )
|
||||
{
|
||||
cb.setColorRGB( c.dye.getColorValue() );
|
||||
}
|
||||
else
|
||||
{
|
||||
final float[] cv = c.dye.getColorComponentValues();
|
||||
cb.setColorRGB( cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f );
|
||||
}
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
final int[] offs = QUAD_OFFSETS[i];
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
final AEColor c = colors[j];
|
||||
if (active) {
|
||||
cb.setColorRGB(c.dye.getColorValue());
|
||||
} else {
|
||||
final float[] cv = c.dye.getColorComponentValues();
|
||||
cb.setColorRGB(cv[0] * 0.5f, cv[1] * 0.5f, cv[2] * 0.5f);
|
||||
}
|
||||
|
||||
final int startx = j % 2;
|
||||
final int starty = 1 - j / 2;
|
||||
final int startx = j % 2;
|
||||
final int starty = 1 - j / 2;
|
||||
|
||||
cb.addCube( offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1, offs[2] + 1 );
|
||||
}
|
||||
cb.addCube(offs[0] + startx, offs[1] + starty, offs[2], offs[0] + startx + 1, offs[1] + starty + 1,
|
||||
offs[2] + 1);
|
||||
}
|
||||
|
||||
}
|
||||
return cb.getOutput();
|
||||
}
|
||||
}
|
||||
return cb.getOutput();
|
||||
}
|
||||
|
||||
private List<BakedQuad> getPartQuads(long partFlags)
|
||||
{
|
||||
try
|
||||
{
|
||||
return modelCache.get( partFlags, () ->
|
||||
{
|
||||
short frequency = (short) ( partFlags & 0xffffL );
|
||||
boolean active = ( partFlags & 0x10000L ) != 0;
|
||||
return this.getQuadsForFrequency( frequency, active );
|
||||
} );
|
||||
}
|
||||
catch( ExecutionException e )
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
private List<BakedQuad> getPartQuads(long partFlags) {
|
||||
try {
|
||||
return modelCache.get(partFlags, () -> {
|
||||
short frequency = (short) (partFlags & 0xffffL);
|
||||
boolean active = (partFlags & 0x10000L) != 0;
|
||||
return this.getQuadsForFrequency(frequency, active);
|
||||
});
|
||||
} catch (ExecutionException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@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 func_230044_c_()
|
||||
{
|
||||
return false;//TODO
|
||||
}
|
||||
@Override
|
||||
public boolean func_230044_c_() {
|
||||
return false;// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltInRenderer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isBuiltInRenderer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture()
|
||||
{
|
||||
return this.texture;
|
||||
}
|
||||
@Override
|
||||
public TextureAtlasSprite getParticleTexture() {
|
||||
return this.texture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemOverrideList getOverrides()
|
||||
{
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
@Override
|
||||
public ItemOverrideList getOverrides() {
|
||||
return ItemOverrideList.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
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,32 +13,31 @@ 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;
|
||||
|
||||
public class P2PTunnelFrequencyModel implements IModelGeometry<P2PTunnelFrequencyModel>
|
||||
{
|
||||
private static final Material TEXTURE = new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation( AppEng.MOD_ID, "parts/p2p_tunnel_frequency" ) );
|
||||
public class P2PTunnelFrequencyModel implements IModelGeometry<P2PTunnelFrequencyModel> {
|
||||
private static final Material TEXTURE = new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE,
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/p2p_tunnel_frequency"));
|
||||
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform, ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
try
|
||||
{
|
||||
final TextureAtlasSprite texture = spriteGetter.apply( TEXTURE );
|
||||
return new P2PTunnelFrequencyBakedModel( texture );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public IBakedModel bake(IModelConfiguration owner, ModelBakery bakery,
|
||||
Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform modelTransform,
|
||||
ItemOverrideList overrides, ResourceLocation modelLocation) {
|
||||
try {
|
||||
final TextureAtlasSprite texture = spriteGetter.apply(TEXTURE);
|
||||
return new P2PTunnelFrequencyBakedModel(texture);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
import appeng.client.render.model.AEInternalModelData;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.data.ModelProperty;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import appeng.client.render.model.AEInternalModelData;
|
||||
|
||||
public final class P2PTunnelFrequencyModelData extends AEInternalModelData {
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,73 +33,62 @@ import appeng.thirdparty.codechicken.lib.model.Quad;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.BakedPipeline;
|
||||
import appeng.thirdparty.codechicken.lib.model.pipeline.transformers.QuadMatrixTransformer;
|
||||
|
||||
|
||||
/**
|
||||
* Assuming a default-orientation of forward=NORTH and up=UP, this class rotates a given list of quads to the desired
|
||||
* facing
|
||||
* Assuming a default-orientation of forward=NORTH and up=UP, this class rotates
|
||||
* a given list of quads to the desired facing
|
||||
*/
|
||||
public class QuadRotator
|
||||
{
|
||||
private static final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial( () -> //
|
||||
BakedPipeline.builder()//
|
||||
.addElement( "transformer", QuadMatrixTransformer.FACTORY )//
|
||||
.build() );
|
||||
private static final ThreadLocal<Quad> collectors = ThreadLocal.withInitial( Quad::new );
|
||||
public class QuadRotator {
|
||||
private static final ThreadLocal<BakedPipeline> pipelines = ThreadLocal.withInitial(() -> //
|
||||
BakedPipeline.builder()//
|
||||
.addElement("transformer", QuadMatrixTransformer.FACTORY)//
|
||||
.build());
|
||||
private static final ThreadLocal<Quad> collectors = ThreadLocal.withInitial(Quad::new);
|
||||
|
||||
public List<BakedQuad> rotateQuads( List<BakedQuad> quads, Direction newForward, Direction newUp )
|
||||
{
|
||||
if( newForward == Direction.NORTH && newUp == Direction.UP )
|
||||
{
|
||||
return quads; // This is the default orientation
|
||||
}
|
||||
FacingToRotation rotation = getRotation( newForward, newUp );
|
||||
if( rotation.isRedundant() )
|
||||
{
|
||||
return quads;
|
||||
}
|
||||
public List<BakedQuad> rotateQuads(List<BakedQuad> quads, Direction newForward, Direction newUp) {
|
||||
if (newForward == Direction.NORTH && newUp == Direction.UP) {
|
||||
return quads; // This is the default orientation
|
||||
}
|
||||
FacingToRotation rotation = getRotation(newForward, newUp);
|
||||
if (rotation.isRedundant()) {
|
||||
return quads;
|
||||
}
|
||||
|
||||
List<BakedQuad> result = new ArrayList<>( quads.size() );
|
||||
List<BakedQuad> result = new ArrayList<>(quads.size());
|
||||
|
||||
CachedFormat format = CachedFormat.lookup( DefaultVertexFormats.BLOCK );
|
||||
BakedPipeline pipeline = pipelines.get();
|
||||
Quad collector = collectors.get();
|
||||
QuadMatrixTransformer transformer = pipeline.getElement( "transformer", QuadMatrixTransformer.class );
|
||||
CachedFormat format = CachedFormat.lookup(DefaultVertexFormats.BLOCK);
|
||||
BakedPipeline pipeline = pipelines.get();
|
||||
Quad collector = collectors.get();
|
||||
QuadMatrixTransformer transformer = pipeline.getElement("transformer", QuadMatrixTransformer.class);
|
||||
|
||||
// FIXME: Temporary rotation fix
|
||||
Matrix4f mat = new Matrix4f();
|
||||
mat.setTranslation(-0.5f, -0.5f, -0.5f);
|
||||
mat.multiplyBackward(rotation.getMat());
|
||||
mat.translate(new Vector3f(0.5f, 0.5f, 0.5f));
|
||||
// FIXME: Temporary rotation fix
|
||||
Matrix4f mat = new Matrix4f();
|
||||
mat.setTranslation(-0.5f, -0.5f, -0.5f);
|
||||
mat.multiplyBackward(rotation.getMat());
|
||||
mat.translate(new Vector3f(0.5f, 0.5f, 0.5f));
|
||||
|
||||
for( BakedQuad quad : quads )
|
||||
{
|
||||
pipeline.reset( format );
|
||||
collector.reset( format );
|
||||
for (BakedQuad quad : quads) {
|
||||
pipeline.reset(format);
|
||||
collector.reset(format);
|
||||
|
||||
transformer.setMatrix( mat );
|
||||
pipeline.prepare( collector );
|
||||
quad.pipe( pipeline );
|
||||
result.add( collector.bake() );
|
||||
}
|
||||
transformer.setMatrix(mat);
|
||||
pipeline.prepare(collector);
|
||||
quad.pipe(pipeline);
|
||||
result.add(collector.bake());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private FacingToRotation getRotation( Direction forward, Direction up )
|
||||
{
|
||||
// Sanitize forward/up
|
||||
if( forward.getAxis() == up.getAxis() )
|
||||
{
|
||||
if( up.getAxis() == Direction.Axis.Y )
|
||||
{
|
||||
up = Direction.NORTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
up = Direction.UP;
|
||||
}
|
||||
}
|
||||
private FacingToRotation getRotation(Direction forward, Direction up) {
|
||||
// Sanitize forward/up
|
||||
if (forward.getAxis() == up.getAxis()) {
|
||||
if (up.getAxis() == Direction.Axis.Y) {
|
||||
up = Direction.NORTH;
|
||||
} else {
|
||||
up = Direction.UP;
|
||||
}
|
||||
}
|
||||
|
||||
return FacingToRotation.get( forward, up );
|
||||
}
|
||||
return FacingToRotation.get(forward, up);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
package appeng.client.render.cablebus;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -29,72 +28,58 @@ import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import appeng.core.AppEng;
|
||||
|
||||
|
||||
/**
|
||||
* Manages the channel textures for smart cables.
|
||||
*/
|
||||
public class SmartCableTextures
|
||||
{
|
||||
public class SmartCableTextures {
|
||||
|
||||
public static final Material[] SMART_CHANNELS_TEXTURES = Arrays.stream( new ResourceLocation[] {
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_00" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_01" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_02" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_03" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_04" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_10" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_11" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_12" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_13" ),//
|
||||
new ResourceLocation( AppEng.MOD_ID, "parts/cable/smart/channels_14" )//
|
||||
} ).map( e -> new Material( AtlasTexture.LOCATION_BLOCKS_TEXTURE, e ) ).toArray( Material[]::new );
|
||||
public static final Material[] SMART_CHANNELS_TEXTURES = Arrays
|
||||
.stream(new ResourceLocation[] { new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_00"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_01"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_02"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_03"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_04"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_10"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_11"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_12"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_13"), //
|
||||
new ResourceLocation(AppEng.MOD_ID, "parts/cable/smart/channels_14")//
|
||||
}).map(e -> new Material(AtlasTexture.LOCATION_BLOCKS_TEXTURE, e)).toArray(Material[]::new);
|
||||
|
||||
// Textures used to display channels on smart cables. There's two sets of 5 textures each, and
|
||||
// one of each set are composed together to get even/odd colored channels
|
||||
private final TextureAtlasSprite[] textures;
|
||||
// Textures used to display channels on smart cables. There's two sets of 5
|
||||
// textures each, and
|
||||
// one of each set are composed together to get even/odd colored channels
|
||||
private final TextureAtlasSprite[] textures;
|
||||
|
||||
public SmartCableTextures( Function<Material, TextureAtlasSprite> bakedTextureGetter )
|
||||
{
|
||||
this.textures = Arrays.stream( SMART_CHANNELS_TEXTURES )//
|
||||
.map( bakedTextureGetter )//
|
||||
.toArray( TextureAtlasSprite[]::new );
|
||||
}
|
||||
public SmartCableTextures(Function<Material, TextureAtlasSprite> bakedTextureGetter) {
|
||||
this.textures = Arrays.stream(SMART_CHANNELS_TEXTURES)//
|
||||
.map(bakedTextureGetter)//
|
||||
.toArray(TextureAtlasSprite[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* The odd variant is used for displaying channels 1-4 as in use.
|
||||
*/
|
||||
public TextureAtlasSprite getOddTextureForChannels( int channels )
|
||||
{
|
||||
if( channels < 0 )
|
||||
{
|
||||
return this.textures[0];
|
||||
}
|
||||
else if( channels <= 4 )
|
||||
{
|
||||
return this.textures[channels];
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.textures[4];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The odd variant is used for displaying channels 1-4 as in use.
|
||||
*/
|
||||
public TextureAtlasSprite getOddTextureForChannels(int channels) {
|
||||
if (channels < 0) {
|
||||
return this.textures[0];
|
||||
} else if (channels <= 4) {
|
||||
return this.textures[channels];
|
||||
} else {
|
||||
return this.textures[4];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The odd variant is used for displaying channels 5-8 as in use.
|
||||
*/
|
||||
public TextureAtlasSprite getEvenTextureForChannels( int channels )
|
||||
{
|
||||
if( channels < 5 )
|
||||
{
|
||||
return this.textures[5];
|
||||
}
|
||||
else if( channels <= 8 )
|
||||
{
|
||||
return this.textures[1 + channels];
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.textures[9];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The odd variant is used for displaying channels 5-8 as in use.
|
||||
*/
|
||||
public TextureAtlasSprite getEvenTextureForChannels(int channels) {
|
||||
if (channels < 5) {
|
||||
return this.textures[5];
|
||||
} else if (channels <= 8) {
|
||||
return this.textures[1 + channels];
|
||||
} else {
|
||||
return this.textures[9];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user