|
21 | 21 | package com.falsepattern.lib.util; |
22 | 22 |
|
23 | 23 | import com.falsepattern.lib.StableAPI; |
24 | | -import lombok.NoArgsConstructor; |
| 24 | +import com.falsepattern.lib.internal.render.ClampedIcon; |
| 25 | +import com.falsepattern.lib.internal.render.FullTextureIcon; |
25 | 26 | import lombok.SneakyThrows; |
| 27 | +import lombok.experimental.UtilityClass; |
26 | 28 | import lombok.val; |
27 | 29 |
|
28 | 30 | import net.minecraft.client.Minecraft; |
| 31 | +import net.minecraft.client.renderer.RenderBlocks; |
29 | 32 | import net.minecraft.util.IIcon; |
30 | 33 | import net.minecraft.util.Timer; |
31 | 34 | import cpw.mods.fml.relauncher.ReflectionHelper; |
32 | 35 | import cpw.mods.fml.relauncher.SideOnly; |
| 36 | +import org.lwjgl.opengl.GL11; |
| 37 | + |
| 38 | +import java.util.Collections; |
33 | 39 |
|
34 | 40 | import static cpw.mods.fml.relauncher.Side.CLIENT; |
35 | | -import static lombok.AccessLevel.PRIVATE; |
36 | 41 | import static net.minecraft.client.Minecraft.getMinecraft; |
37 | 42 |
|
38 | 43 | @SideOnly(CLIENT) |
39 | | -@NoArgsConstructor(access = PRIVATE) |
| 44 | +@UtilityClass |
40 | 45 | @StableAPI(since = "0.8.0") |
41 | 46 | public final class RenderUtil { |
42 | | - private final static Timer MINECRAFT_TIMER = getMinecraftTimer(); |
| 47 | + private static final Timer MINECRAFT_TIMER = getMinecraftTimer(); |
43 | 48 |
|
44 | | - @StableAPI.Expose |
45 | | - @SneakyThrows |
46 | | - private static Timer getMinecraftTimer() { |
47 | | - val timerField = ReflectionHelper.findField(Minecraft.class, "timer", "field_71428_T"); |
48 | | - timerField.setAccessible(true); |
49 | | - return (Timer) timerField.get(getMinecraft()); |
| 49 | + /** |
| 50 | + * Sets the OpenGL translation, relative to the player's position. |
| 51 | + * <p> |
| 52 | + * This is useful for rendering things that are not part of the world mesh, but should be rendered as if they were. |
| 53 | + * <p> |
| 54 | + * It's good practice to make this call inside a {@link GL11#glPushMatrix() push}/{@link GL11#glPopMatrix() pop} matrix block. |
| 55 | + */ |
| 56 | + @StableAPI.Expose(since = "0.12.0") |
| 57 | + public static void setGLTranslationRelativeToPlayer() { |
| 58 | + val player = getMinecraft().thePlayer; |
| 59 | + val partialTick = partialTick(); |
| 60 | + |
| 61 | + val offsetX = (float) (player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTick); |
| 62 | + val offsetY = (float) (player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTick); |
| 63 | + val offsetZ = (float) (player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTick); |
| 64 | + |
| 65 | + GL11.glTranslatef(-offsetX, -offsetY, -offsetZ); |
50 | 66 | } |
51 | 67 |
|
| 68 | + /** |
| 69 | + * Provides a texture icon with the given name and dimensions. |
| 70 | + * <p> |
| 71 | + * This is useful for rendering textures that are not part of the Minecraft texture atlas. |
| 72 | + * |
| 73 | + * @param iconName The icon name |
| 74 | + * @param width The icon width in pixels |
| 75 | + * @param height The icon height in pixels |
| 76 | + * @return The full resolution texture icon. |
| 77 | + */ |
52 | 78 | @StableAPI.Expose(since = "0.10.0") |
53 | 79 | public static IIcon getFullTextureIcon(String iconName, int width, int height) { |
54 | | - return new IIcon() { |
55 | | - @Override |
56 | | - public int getIconWidth() { |
57 | | - return width; |
58 | | - } |
59 | | - |
60 | | - @Override |
61 | | - public int getIconHeight() { |
62 | | - return height; |
63 | | - } |
64 | | - |
65 | | - @Override |
66 | | - public float getMinU() { |
67 | | - return 0; |
68 | | - } |
69 | | - |
70 | | - @Override |
71 | | - public float getMaxU() { |
72 | | - return 1; |
73 | | - } |
74 | | - |
75 | | - @Override |
76 | | - public float getInterpolatedU(double u) { |
77 | | - return (float) (u / 16D); |
78 | | - } |
79 | | - |
80 | | - @Override |
81 | | - public float getMinV() { |
82 | | - return 0; |
83 | | - } |
84 | | - |
85 | | - @Override |
86 | | - public float getMaxV() { |
87 | | - return 1; |
88 | | - } |
89 | | - |
90 | | - @Override |
91 | | - public float getInterpolatedV(double v) { |
92 | | - return (float) (v / 16D); |
93 | | - } |
| 80 | + return new FullTextureIcon(iconName, width, height); |
| 81 | + } |
94 | 82 |
|
95 | | - @Override |
96 | | - public String getIconName() { |
97 | | - return iconName; |
98 | | - } |
99 | | - }; |
| 83 | + /** |
| 84 | + * Wraps the given icon as a clamped icon. |
| 85 | + * <p> |
| 86 | + * A clamped icon will clamp the coordinates given to {@link IIcon#getInterpolatedU(double)} and {@link IIcon#getInterpolatedV(double)} to the range of 0 to 16. |
| 87 | + * <p> |
| 88 | + * This is helpful when using {@link RenderBlocks} but having different bounds. |
| 89 | + * |
| 90 | + * @param icon The icon to clamp |
| 91 | + */ |
| 92 | + @StableAPI.Expose(since = "0.12.0") |
| 93 | + public static IIcon wrapAsClampedIcon(IIcon icon) { |
| 94 | + return new ClampedIcon(icon); |
100 | 95 | } |
101 | 96 |
|
| 97 | + /** |
| 98 | + * Provides the partial tick between the last and next client tick, in the range of 0 to 1. |
| 99 | + * <p> |
| 100 | + * Sometimes referred to as 'subTick', it is used mostly for interpolation in rendering. |
| 101 | + * |
| 102 | + * @return The current partial tick |
| 103 | + */ |
102 | 104 | @StableAPI.Expose |
103 | 105 | public static float partialTick() { |
104 | 106 | return MINECRAFT_TIMER.renderPartialTicks; |
105 | 107 | } |
| 108 | + |
| 109 | + @StableAPI.Expose |
| 110 | + @SneakyThrows |
| 111 | + private static Timer getMinecraftTimer() { |
| 112 | + val timerField = ReflectionHelper.findField(Minecraft.class, "timer", "field_71428_T"); |
| 113 | + timerField.setAccessible(true); |
| 114 | + return (Timer) timerField.get(getMinecraft()); |
| 115 | + } |
106 | 116 | } |
0 commit comments