mirror of
https://github.com/GTNewHorizons/CodeChickenCore.git
synced 2026-11-12 00:07:33 +00:00
Fix missing colour tint on block particles (#57)
This commit is contained in:
1 parent
ba757e4237
commit
2077a8da86
2 files changed
+91
-16
No files matched your search
@@ -1,5 +1,7 @@
|
||||
package codechicken.lib.render;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.minecraft.client.particle.EffectRenderer;
|
||||
import net.minecraft.client.particle.EntityFX;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
@@ -11,6 +13,9 @@ import codechicken.lib.vec.Vector3;
|
||||
|
||||
public class EntityDigIconFX extends EntityFX {
|
||||
|
||||
/** Tint that leaves the particle colour untouched, for materials that don't colour their texture. */
|
||||
public static final int NO_TINT = 0xFFFFFF;
|
||||
|
||||
public EntityDigIconFX(World world, double x, double y, double z, double dx, double dy, double dz, IIcon icon) {
|
||||
super(world, x, y, z, dx, dy, dz);
|
||||
particleIcon = icon;
|
||||
@@ -19,6 +24,18 @@ public class EntityDigIconFX extends EntityFX {
|
||||
particleScale /= 2.0F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the particle colour by an 0xRRGGBB tint, the equivalent of vanilla
|
||||
* EntityDiggingFX.applyColourMultiplier. Materials that draw a greyscale texture and colour it at render time
|
||||
* (leaves, grass tops) need this, or their particles come out flat grey.
|
||||
*/
|
||||
public EntityDigIconFX applyColourMultiplier(int colour) {
|
||||
particleRed *= (colour >> 16 & 255) / 255F;
|
||||
particleGreen *= (colour >> 8 & 255) / 255F;
|
||||
particleBlue *= (colour & 255) / 255F;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFXLayer() {
|
||||
return 1;
|
||||
@@ -90,8 +107,24 @@ public class EntityDigIconFX extends EntityFX {
|
||||
f9);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated the particle is never tinted, so a material that colours a greyscale texture at render time (leaves,
|
||||
* grass tops) breaks into grey particles. Use
|
||||
* {@link #addBlockHitEffects(World, Cuboid6, int, IIcon, int, EffectRenderer)}, passing
|
||||
* {@link #NO_TINT} for materials whose texture is already coloured.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon,
|
||||
EffectRenderer effectRenderer) {
|
||||
addBlockHitEffects(world, bounds, side, icon, NO_TINT, effectRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a hit particle on side of bounds, tinted by colour (0xRRGGBB, {@link #NO_TINT} for none). The caller
|
||||
* resolves the tint for the side it hit, so per-face materials like grass can tint only the faces that need it.
|
||||
*/
|
||||
public static void addBlockHitEffects(World world, Cuboid6 bounds, int side, IIcon icon, int colour,
|
||||
EffectRenderer effectRenderer) {
|
||||
float border = 0.1F;
|
||||
Vector3 diff = bounds.max.copy().subtract(bounds.min).add(-2 * border);
|
||||
diff.x *= world.rand.nextDouble();
|
||||
@@ -106,13 +139,34 @@ public class EntityDigIconFX extends EntityFX {
|
||||
if (side == 4) diff.x = bounds.min.x - border;
|
||||
if (side == 5) diff.x = bounds.max.x + border;
|
||||
|
||||
effectRenderer.addEffect(
|
||||
new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon).multiplyVelocity(0.2F)
|
||||
.multipleParticleScaleBy(0.6F));
|
||||
EntityDigIconFX fx = new EntityDigIconFX(world, pos.x, pos.y, pos.z, 0, 0, 0, icon);
|
||||
effectRenderer.addEffect(fx.applyColourMultiplier(colour).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated the particles are never tinted, so a material that colours a greyscale texture at render time
|
||||
* (leaves, grass tops) breaks into grey particles. Use
|
||||
* {@link #addBlockDestroyEffects(World, Cuboid6, IIcon[], int[], EffectRenderer)}, passing
|
||||
* {@link #NO_TINT} for the faces whose texture is already coloured.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons,
|
||||
EffectRenderer effectRenderer) {
|
||||
int[] colours = new int[icons.length];
|
||||
Arrays.fill(colours, NO_TINT);
|
||||
addBlockDestroyEffects(world, bounds, icons, colours, effectRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns break particles filling bounds, each drawn from a random face. colours holds the 0xRRGGBB tint for the
|
||||
* matching entry of icons ({@link #NO_TINT} for none) and must be the same length, so a particle is tinted by the
|
||||
* face it was taken from.
|
||||
*/
|
||||
public static void addBlockDestroyEffects(World world, Cuboid6 bounds, IIcon[] icons, int[] colours,
|
||||
EffectRenderer effectRenderer) {
|
||||
if (icons.length != colours.length)
|
||||
throw new IllegalArgumentException("icons and colours must have the same length");
|
||||
|
||||
Vector3 diff = bounds.max.copy().subtract(bounds.min);
|
||||
Vector3 center = bounds.min.copy().add(bounds.max).multiply(0.5);
|
||||
Vector3 density = diff.copy().multiply(4);
|
||||
@@ -121,19 +175,20 @@ public class EntityDigIconFX extends EntityFX {
|
||||
density.z = Math.ceil(density.z);
|
||||
|
||||
for (int i = 0; i < density.x; ++i) for (int j = 0; j < density.y; ++j) for (int k = 0; k < density.z; ++k) {
|
||||
double x = bounds.min.x + (i + 0.5) * diff.x / density.x;
|
||||
double y = bounds.min.y + (j + 0.5) * diff.y / density.y;
|
||||
double z = bounds.min.z + (k + 0.5) * diff.z / density.z;
|
||||
effectRenderer.addEffect(
|
||||
new EntityDigIconFX(
|
||||
world,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
x - center.x,
|
||||
y - center.y,
|
||||
z - center.z,
|
||||
icons[world.rand.nextInt(icons.length)]));
|
||||
double px = bounds.min.x + (i + 0.5) * diff.x / density.x;
|
||||
double py = bounds.min.y + (j + 0.5) * diff.y / density.y;
|
||||
double pz = bounds.min.z + (k + 0.5) * diff.z / density.z;
|
||||
int iconSide = world.rand.nextInt(icons.length);
|
||||
EntityDigIconFX fx = new EntityDigIconFX(
|
||||
world,
|
||||
px,
|
||||
py,
|
||||
pz,
|
||||
px - center.x,
|
||||
py - center.y,
|
||||
pz - center.z,
|
||||
icons[iconSide]);
|
||||
effectRenderer.addEffect(fx.applyColourMultiplier(colours[iconSide]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package codechicken.lib.render;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import net.minecraft.util.IIcon;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class EntityDigIconFXTest {
|
||||
|
||||
@Test
|
||||
public void rejectsMismatchedIconAndColourCountsBeforeSpawning() {
|
||||
IllegalArgumentException exception = assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> EntityDigIconFX.addBlockDestroyEffects(null, null, new IIcon[1], new int[0], null));
|
||||
|
||||
assertEquals("icons and colours must have the same length", exception.getMessage());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user