Skip to content

Commit fd10ed6

Browse files
committed
Merge pull request dan200#553 from SquidDev-CC/ComputerCraft/feature/fancy-printout
Fancy rendering of printouts
2 parents 5f0addb + c0bdd4f commit fd10ed6

File tree

4 files changed

+245
-25
lines changed

4 files changed

+245
-25
lines changed

src/main/java/dan200/computercraft/client/gui/GuiPrintout.java

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020

2121
public class GuiPrintout extends GuiContainer
2222
{
23-
private static final ResourceLocation background = new ResourceLocation( "computercraft", "textures/gui/printout.png" );
24-
25-
private static final int xSize = 172;
26-
private static final int ySize = 209;
23+
public static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printout.png" );
24+
public static final int X_SIZE = 172;
25+
public static final int Y_SIZE = 209;
2726

2827
private final boolean m_book;
2928
private final int m_pages;
@@ -142,57 +141,57 @@ public void drawScreen(int mouseX, int mouseY, float f)
142141

143142
// Draw the printout
144143
GlStateManager.color( 1.0f, 1.0f, 1.0f, 1.0f );
145-
this.mc.getTextureManager().bindTexture( background );
144+
this.mc.getTextureManager().bindTexture( BACKGROUND );
146145

147-
int startY = (height - ySize) / 2;
148-
//int startX = (width - xSize) / 2 - (m_page * 8);
149-
int startX = (width - (xSize + (m_pages - 1)*8)) / 2;
146+
int startY = (height - Y_SIZE) / 2;
147+
//int startX = (width - X_SIZE) / 2 - (m_page * 8);
148+
int startX = (width - (X_SIZE + (m_pages - 1)*8)) / 2;
150149

151150
if( m_book )
152151
{
153152
// Border
154-
drawTexturedModalRect( startX - 8, startY - 8, xSize + 48, 0, 12, ySize + 24);
155-
drawTexturedModalRect( startX + xSize + (m_pages - 1)*8 - 4, startY - 8, xSize + 48 + 12, 0, 12, ySize + 24);
153+
drawTexturedModalRect( startX - 8, startY - 8, X_SIZE + 48, 0, 12, Y_SIZE + 24);
154+
drawTexturedModalRect( startX + X_SIZE + (m_pages - 1)*8 - 4, startY - 8, X_SIZE + 48 + 12, 0, 12, Y_SIZE + 24);
156155

157-
drawTexturedModalRect( startX, startY - 8, 0, ySize, xSize, 12);
158-
drawTexturedModalRect( startX, startY + ySize - 4, 0, ySize + 12, xSize, 12);
156+
drawTexturedModalRect( startX, startY - 8, 0, Y_SIZE, X_SIZE, 12);
157+
drawTexturedModalRect( startX, startY + Y_SIZE - 4, 0, Y_SIZE + 12, X_SIZE, 12);
159158
for( int n=1; n<m_pages; ++n )
160159
{
161-
drawTexturedModalRect( startX + xSize + (n-1)*8, startY - 8, 0, ySize, 8, 12);
162-
drawTexturedModalRect( startX + xSize + (n-1)*8, startY + ySize - 4, 0, ySize + 12, 8, 12);
160+
drawTexturedModalRect( startX + X_SIZE + (n-1)*8, startY - 8, 0, Y_SIZE, 8, 12);
161+
drawTexturedModalRect( startX + X_SIZE + (n-1)*8, startY + Y_SIZE - 4, 0, Y_SIZE + 12, 8, 12);
163162
}
164163
}
165164

166165
// Left half
167166
if( m_page == 0 )
168167
{
169-
drawTexturedModalRect( startX, startY, 24, 0, xSize / 2, ySize);
170-
drawTexturedModalRect( startX, startY, 0, 0, 12, ySize);
168+
drawTexturedModalRect( startX, startY, 24, 0, X_SIZE / 2, Y_SIZE );
169+
drawTexturedModalRect( startX, startY, 0, 0, 12, Y_SIZE );
171170
}
172171
else
173172
{
174-
drawTexturedModalRect( startX, startY, 0, 0, 12, ySize);
173+
drawTexturedModalRect( startX, startY, 0, 0, 12, Y_SIZE );
175174
for( int n=1; n<m_page; ++n )
176175
{
177-
drawTexturedModalRect( startX + n*8, startY, 12, 0, 12, ySize);
176+
drawTexturedModalRect( startX + n*8, startY, 12, 0, 12, Y_SIZE );
178177
}
179-
drawTexturedModalRect( startX + m_page*8, startY, 24, 0, xSize / 2, ySize);
178+
drawTexturedModalRect( startX + m_page*8, startY, 24, 0, X_SIZE / 2, Y_SIZE );
180179
}
181180

182181
// Right half
183182
if( m_page == (m_pages - 1) )
184183
{
185-
drawTexturedModalRect( startX + m_page*8 + xSize/2, startY, 24 + xSize / 2, 0, xSize / 2, ySize);
186-
drawTexturedModalRect( startX + m_page*8 + (xSize - 12), startY, 24 + xSize + 12, 0, 12, ySize);
184+
drawTexturedModalRect( startX + m_page*8 + X_SIZE /2, startY, 24 + X_SIZE / 2, 0, X_SIZE / 2, Y_SIZE );
185+
drawTexturedModalRect( startX + m_page*8 + (X_SIZE - 12), startY, 24 + X_SIZE + 12, 0, 12, Y_SIZE );
187186
}
188187
else
189188
{
190-
drawTexturedModalRect( startX + (m_pages - 1)*8 + (xSize - 12), startY, 24 + xSize + 12, 0, 12, ySize);
189+
drawTexturedModalRect( startX + (m_pages - 1)*8 + (X_SIZE - 12), startY, 24 + X_SIZE + 12, 0, 12, Y_SIZE );
191190
for( int n=m_pages-2; n>=m_page; --n )
192191
{
193-
drawTexturedModalRect( startX + n*8 + (xSize - 12), startY, 24 + xSize, 0, 12, ySize);
192+
drawTexturedModalRect( startX + n*8 + (X_SIZE - 12), startY, 24 + X_SIZE, 0, 12, Y_SIZE );
194193
}
195-
drawTexturedModalRect( startX + m_page*8 + xSize/2, startY, 24 + xSize / 2, 0, xSize / 2, ySize);
194+
drawTexturedModalRect( startX + m_page*8 + X_SIZE /2, startY, 24 + X_SIZE / 2, 0, X_SIZE / 2, Y_SIZE );
196195
}
197196

198197
// Draw the text

src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import dan200.computercraft.ComputerCraft;
1010
import dan200.computercraft.client.gui.*;
1111
import dan200.computercraft.client.render.ItemPocketRenderer;
12+
import dan200.computercraft.client.render.ItemPrintoutRenderer;
1213
import dan200.computercraft.client.render.RenderOverlayCable;
1314
import dan200.computercraft.client.render.TileEntityCableRenderer;
1415
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
@@ -497,6 +498,7 @@ private void registerForgeHandlers()
497498
MinecraftForge.EVENT_BUS.register( handlers );
498499
MinecraftForge.EVENT_BUS.register( new RenderOverlayCable() );
499500
MinecraftForge.EVENT_BUS.register( new ItemPocketRenderer() );
501+
MinecraftForge.EVENT_BUS.register( new ItemPrintoutRenderer() );
500502
}
501503

502504
public class ForgeHandlers
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package dan200.computercraft.client.render;
2+
3+
import dan200.computercraft.ComputerCraft;
4+
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
5+
import dan200.computercraft.client.gui.GuiPrintout;
6+
import dan200.computercraft.core.terminal.TextBuffer;
7+
import dan200.computercraft.shared.media.items.ItemPrintout;
8+
import dan200.computercraft.shared.util.Palette;
9+
import net.minecraft.client.Minecraft;
10+
import net.minecraft.client.renderer.BufferBuilder;
11+
import net.minecraft.client.renderer.GlStateManager;
12+
import net.minecraft.client.renderer.ItemRenderer;
13+
import net.minecraft.client.renderer.Tessellator;
14+
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
15+
import net.minecraft.entity.player.EntityPlayer;
16+
import net.minecraft.item.ItemStack;
17+
import net.minecraft.util.EnumHand;
18+
import net.minecraft.util.EnumHandSide;
19+
import net.minecraft.util.math.MathHelper;
20+
import net.minecraftforge.client.event.RenderItemInFrameEvent;
21+
import net.minecraftforge.client.event.RenderSpecificHandEvent;
22+
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
23+
import org.lwjgl.opengl.GL11;
24+
25+
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
26+
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
27+
import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE;
28+
import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH;
29+
30+
public class ItemPrintoutRenderer
31+
{
32+
@SubscribeEvent
33+
public void onRenderInHand( RenderSpecificHandEvent event )
34+
{
35+
ItemStack stack = event.getItemStack();
36+
if( stack.getItem() != ComputerCraft.Items.printout ) return;
37+
38+
// We only allow single pages to be viewed in-hand for now
39+
if( ItemPrintout.getType( stack ) != ItemPrintout.Type.Single ) return;
40+
41+
event.setCanceled( true );
42+
43+
EntityPlayer player = Minecraft.getMinecraft().player;
44+
45+
GlStateManager.pushMatrix();
46+
if( event.getHand() == EnumHand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
47+
{
48+
renderPrintoutFirstPersonCentre(
49+
event.getInterpolatedPitch(),
50+
event.getEquipProgress(),
51+
event.getSwingProgress(),
52+
stack
53+
);
54+
}
55+
else
56+
{
57+
renderPrintoutFirstPersonSide(
58+
event.getHand() == EnumHand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
59+
event.getEquipProgress(),
60+
event.getSwingProgress(),
61+
stack
62+
);
63+
}
64+
GlStateManager.popMatrix();
65+
}
66+
67+
/**
68+
* Renders a pocket computer to one side of the player.
69+
*
70+
* @param side The side to render on
71+
* @param equipProgress The equip progress of this item
72+
* @param swingProgress The swing progress of this item
73+
* @param stack The stack to render
74+
* @see ItemRenderer#renderMapFirstPersonSide(float, EnumHandSide, float, ItemStack)
75+
*/
76+
private void renderPrintoutFirstPersonSide( EnumHandSide side, float equipProgress, float swingProgress, ItemStack stack )
77+
{
78+
Minecraft minecraft = Minecraft.getMinecraft();
79+
float offset = side == EnumHandSide.RIGHT ? 1f : -1f;
80+
GlStateManager.translate( offset * 0.125f, -0.125f, 0f );
81+
82+
// If the player is not invisible then render a single arm
83+
if( !minecraft.player.isInvisible() )
84+
{
85+
GlStateManager.pushMatrix();
86+
GlStateManager.rotate( offset * 10f, 0f, 0f, 1f );
87+
minecraft.getItemRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
88+
GlStateManager.popMatrix();
89+
}
90+
91+
// Setup the appropriate transformations. This is just copied from the
92+
// corresponding method in ItemRenderer.
93+
GlStateManager.pushMatrix();
94+
GlStateManager.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f );
95+
float f1 = MathHelper.sqrt( swingProgress );
96+
float f2 = MathHelper.sin( f1 * (float) Math.PI );
97+
float f3 = -0.5f * f2;
98+
float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
99+
float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
100+
GlStateManager.translate( offset * f3, f4 - 0.3f * f2, f5 );
101+
GlStateManager.rotate( f2 * -45f, 1f, 0f, 0f );
102+
GlStateManager.rotate( offset * f2 * -30f, 0f, 1f, 0f );
103+
104+
renderPrintoutFirstPerson( stack );
105+
106+
GlStateManager.popMatrix();
107+
}
108+
109+
/**
110+
* Render an item in the middle of the screen
111+
*
112+
* @param pitch The pitch of the player
113+
* @param equipProgress The equip progress of this item
114+
* @param swingProgress The swing progress of this item
115+
* @param stack The stack to render
116+
* @see ItemRenderer#renderMapFirstPerson(float, float, float)
117+
*/
118+
private void renderPrintoutFirstPersonCentre( float pitch, float equipProgress, float swingProgress, ItemStack stack )
119+
{
120+
ItemRenderer itemRenderer = Minecraft.getMinecraft().getItemRenderer();
121+
122+
// Setup the appropriate transformations. This is just copied from the
123+
// corresponding method in ItemRenderer.
124+
float swingRt = MathHelper.sqrt( swingProgress );
125+
float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
126+
float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
127+
GlStateManager.translate( 0f, -tX / 2f, tZ );
128+
float pitchAngle = itemRenderer.getMapAngleFromPitch( pitch );
129+
GlStateManager.translate( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
130+
GlStateManager.rotate( pitchAngle * -85f, 1f, 0f, 0f );
131+
itemRenderer.renderArms();
132+
float rX = MathHelper.sin( swingRt * (float) Math.PI );
133+
GlStateManager.rotate( rX * 20f, 1f, 0f, 0f );
134+
GlStateManager.scale( 2f, 2f, 2f );
135+
136+
renderPrintoutFirstPerson( stack );
137+
}
138+
139+
140+
private static void renderPrintoutFirstPerson( ItemStack stack )
141+
{
142+
// Setup various transformations. Note that these are partially adapated from the corresponding method
143+
// in ItemRenderer.renderMapFirstPerson
144+
GlStateManager.disableLighting();
145+
146+
GlStateManager.rotate( 180f, 0f, 1f, 0f );
147+
GlStateManager.rotate( 180f, 0f, 0f, 1f );
148+
GlStateManager.scale( 0.38f, 0.38f, 0.38f );
149+
GlStateManager.translate( -0.5f, -0.5f, 0.0f );
150+
151+
drawPrintout( stack );
152+
153+
GlStateManager.enableLighting();
154+
}
155+
156+
@SubscribeEvent
157+
public void onRenderInFrame( RenderItemInFrameEvent event )
158+
{
159+
ItemStack stack = event.getItem();
160+
if( stack.getItem() != ComputerCraft.Items.printout ) return;
161+
162+
// We only allow single pages to be viewed in-hand for now
163+
if( ItemPrintout.getType( stack ) != ItemPrintout.Type.Single ) return;
164+
165+
event.setCanceled( true );
166+
167+
GlStateManager.disableLighting();
168+
169+
// Move a little bit forward to ensure we're not clipping with the frame
170+
GlStateManager.translate( 0.0f, 0.0f, -0.001f );
171+
GlStateManager.rotate( 180f, 0f, 0f, 1f );
172+
GlStateManager.translate( -0.5f, -0.5f, 0.0f );
173+
174+
drawPrintout( stack );
175+
176+
GlStateManager.enableLighting();
177+
}
178+
179+
private static void drawPrintout( ItemStack stack )
180+
{
181+
int xMargin = 13;
182+
int yMargin = 11;
183+
184+
int width = LINE_MAX_LENGTH * FONT_WIDTH + xMargin * 2;
185+
int height = LINES_PER_PAGE * FONT_HEIGHT + yMargin * 2;
186+
int max = Math.max( height, width );
187+
188+
// Scale the printout to fit correctly.
189+
double scale = 1.0 / max;
190+
GlStateManager.scale( scale, scale, scale );
191+
GlStateManager.translate( (max - width) / 2.0f, (max - height) / 2.0f, 0.0f );
192+
193+
drawBackground( 0, 0, 0.01 );
194+
195+
FixedWidthFontRenderer fontRenderer = (FixedWidthFontRenderer) ComputerCraft.getFixedWidthFontRenderer();
196+
197+
String[] text = ItemPrintout.getText( stack );
198+
String[] colours = ItemPrintout.getColours( stack );
199+
for( int line = 0; line < LINES_PER_PAGE && line < text.length; ++line )
200+
{
201+
fontRenderer.drawString( new TextBuffer( text[ line ] ), xMargin, yMargin + line * FONT_HEIGHT, new TextBuffer( colours[ line ] ), null, 0, 0, false, Palette.DEFAULT );
202+
}
203+
}
204+
205+
private static void drawBackground( double x, double y, double z )
206+
{
207+
Minecraft mc = Minecraft.getMinecraft();
208+
mc.getTextureManager().bindTexture( GuiPrintout.BACKGROUND );
209+
210+
Tessellator tessellator = Tessellator.getInstance();
211+
BufferBuilder buffer = tessellator.getBuffer();
212+
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
213+
buffer.pos( x, y + GuiPrintout.Y_SIZE, z ).tex( 24 / 256.0, GuiPrintout.Y_SIZE / 256.0 ).endVertex();
214+
buffer.pos( x + GuiPrintout.X_SIZE, y + GuiPrintout.Y_SIZE, z ).tex( (24 + GuiPrintout.X_SIZE) / 256.0, GuiPrintout.Y_SIZE / 256.0 ).endVertex();
215+
buffer.pos( x + GuiPrintout.X_SIZE, y, z ).tex( (24 + GuiPrintout.X_SIZE) / 256.0, 0 ).endVertex();
216+
buffer.pos( x, y, z ).tex( 24 / 256.0, 0 ).endVertex();
217+
tessellator.draw();
218+
}
219+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RecordMedia (and related methods)
22
public net.minecraft.item.ItemRecord field_185076_b # sound
33
public net.minecraft.item.ItemRecord field_185077_c # displayName
4-
# ItemPocketRenderer
4+
# ItemPocketRenderer/ItemPrintoutRenderer
55
public net.minecraft.client.renderer.ItemRenderer func_187466_c()V # renderArms
66
public net.minecraft.client.renderer.ItemRenderer func_178100_c(F)F # getMapAngleFromPitch
77
public net.minecraft.client.renderer.ItemRenderer func_187456_a(FFLnet/minecraft/util/EnumHandSide;)V # renderArmFirstPerson

0 commit comments

Comments
 (0)