001 package net.minecraft.client.gui;
002
003 import cpw.mods.fml.relauncher.Side;
004 import cpw.mods.fml.relauncher.SideOnly;
005 import java.util.List;
006 import net.minecraft.client.Minecraft;
007 import net.minecraft.client.renderer.Tessellator;
008 import org.lwjgl.input.Mouse;
009 import org.lwjgl.opengl.GL11;
010
011 @SideOnly(Side.CLIENT)
012 public abstract class GuiSlot
013 {
014 private final Minecraft mc;
015
016 /**
017 * The width of the GuiScreen. Affects the container rendering, but not the overlays.
018 */
019 private int width;
020
021 /**
022 * The height of the GuiScreen. Affects the container rendering, but not the overlays or the scrolling.
023 */
024 private int height;
025
026 /** The top of the slot container. Affects the overlays and scrolling. */
027 protected int top;
028
029 /** The bottom of the slot container. Affects the overlays and scrolling. */
030 protected int bottom;
031 private int right;
032 private int left;
033
034 /** The height of a slot. */
035 protected final int slotHeight;
036
037 /** button id of the button used to scroll up */
038 private int scrollUpButtonID;
039
040 /** the buttonID of the button used to scroll down */
041 private int scrollDownButtonID;
042
043 /** X axis position of the mouse */
044 protected int mouseX;
045
046 /** Y axis position of the mouse */
047 protected int mouseY;
048
049 /** where the mouse was in the window when you first clicked to scroll */
050 private float initialClickY = -2.0F;
051
052 /**
053 * what to multiply the amount you moved your mouse by(used for slowing down scrolling when over the items and no on
054 * scroll bar)
055 */
056 private float scrollMultiplier;
057
058 /** how far down this slot has been scrolled */
059 private float amountScrolled;
060
061 /** the element in the list that was selected */
062 private int selectedElement = -1;
063
064 /** the time when this button was last clicked. */
065 private long lastClicked = 0L;
066
067 /** true if a selected element in this gui will show an outline box */
068 private boolean showSelectionBox = true;
069 private boolean field_77243_s;
070 private int field_77242_t;
071
072 public String BACKGROUND_IMAGE = "/gui/background.png";
073
074 public GuiSlot(Minecraft par1Minecraft, int par2, int par3, int par4, int par5, int par6)
075 {
076 this.mc = par1Minecraft;
077 this.width = par2;
078 this.height = par3;
079 this.top = par4;
080 this.bottom = par5;
081 this.slotHeight = par6;
082 this.left = 0;
083 this.right = par2;
084 }
085
086 public void func_77207_a(int par1, int par2, int par3, int par4)
087 {
088 this.width = par1;
089 this.height = par2;
090 this.top = par3;
091 this.bottom = par4;
092 this.left = 0;
093 this.right = par1;
094 }
095
096 public void setShowSelectionBox(boolean par1)
097 {
098 this.showSelectionBox = par1;
099 }
100
101 protected void func_77223_a(boolean par1, int par2)
102 {
103 this.field_77243_s = par1;
104 this.field_77242_t = par2;
105
106 if (!par1)
107 {
108 this.field_77242_t = 0;
109 }
110 }
111
112 /**
113 * Gets the size of the current slot list.
114 */
115 protected abstract int getSize();
116
117 /**
118 * the element in the slot that was clicked, boolean for wether it was double clicked or not
119 */
120 protected abstract void elementClicked(int var1, boolean var2);
121
122 /**
123 * returns true if the element passed in is currently selected
124 */
125 protected abstract boolean isSelected(int var1);
126
127 /**
128 * return the height of the content being scrolled
129 */
130 protected int getContentHeight()
131 {
132 return this.getSize() * this.slotHeight + this.field_77242_t;
133 }
134
135 protected abstract void drawBackground();
136
137 protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5);
138
139 protected void func_77222_a(int par1, int par2, Tessellator par3Tessellator) {}
140
141 protected void func_77224_a(int par1, int par2) {}
142
143 protected void func_77215_b(int par1, int par2) {}
144
145 public int func_77210_c(int par1, int par2)
146 {
147 int var3 = this.width / 2 - 110;
148 int var4 = this.width / 2 + 110;
149 int var5 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
150 int var6 = var5 / this.slotHeight;
151 return par1 >= var3 && par1 <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1;
152 }
153
154 /**
155 * Registers the IDs that can be used for the scrollbar's buttons.
156 */
157 public void registerScrollButtons(List par1List, int par2, int par3)
158 {
159 this.scrollUpButtonID = par2;
160 this.scrollDownButtonID = par3;
161 }
162
163 /**
164 * stop the thing from scrolling out of bounds
165 */
166 private void bindAmountScrolled()
167 {
168 int var1 = this.func_77209_d();
169
170 if (var1 < 0)
171 {
172 var1 /= 2;
173 }
174
175 if (this.amountScrolled < 0.0F)
176 {
177 this.amountScrolled = 0.0F;
178 }
179
180 if (this.amountScrolled > (float)var1)
181 {
182 this.amountScrolled = (float)var1;
183 }
184 }
185
186 public int func_77209_d()
187 {
188 return this.getContentHeight() - (this.bottom - this.top - 4);
189 }
190
191 public void func_77208_b(int par1)
192 {
193 this.amountScrolled += (float)par1;
194 this.bindAmountScrolled();
195 this.initialClickY = -2.0F;
196 }
197
198 public void actionPerformed(GuiButton par1GuiButton)
199 {
200 if (par1GuiButton.enabled)
201 {
202 if (par1GuiButton.id == this.scrollUpButtonID)
203 {
204 this.amountScrolled -= (float)(this.slotHeight * 2 / 3);
205 this.initialClickY = -2.0F;
206 this.bindAmountScrolled();
207 }
208 else if (par1GuiButton.id == this.scrollDownButtonID)
209 {
210 this.amountScrolled += (float)(this.slotHeight * 2 / 3);
211 this.initialClickY = -2.0F;
212 this.bindAmountScrolled();
213 }
214 }
215 }
216
217 /**
218 * draws the slot to the screen, pass in mouse's current x and y and partial ticks
219 */
220 public void drawScreen(int par1, int par2, float par3)
221 {
222 this.mouseX = par1;
223 this.mouseY = par2;
224 this.drawBackground();
225 int var4 = this.getSize();
226 int var5 = this.getScrollBarX();
227 int var6 = var5 + 6;
228 int var9;
229 int var10;
230 int var11;
231 int var13;
232 int var19;
233
234 if (Mouse.isButtonDown(0))
235 {
236 if (this.initialClickY == -1.0F)
237 {
238 boolean var7 = true;
239
240 if (par2 >= this.top && par2 <= this.bottom)
241 {
242 int var8 = this.width / 2 - 110;
243 var9 = this.width / 2 + 110;
244 var10 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4;
245 var11 = var10 / this.slotHeight;
246
247 if (par1 >= var8 && par1 <= var9 && var11 >= 0 && var10 >= 0 && var11 < var4)
248 {
249 boolean var12 = var11 == this.selectedElement && Minecraft.getSystemTime() - this.lastClicked < 250L;
250 this.elementClicked(var11, var12);
251 this.selectedElement = var11;
252 this.lastClicked = Minecraft.getSystemTime();
253 }
254 else if (par1 >= var8 && par1 <= var9 && var10 < 0)
255 {
256 this.func_77224_a(par1 - var8, par2 - this.top + (int)this.amountScrolled - 4);
257 var7 = false;
258 }
259
260 if (par1 >= var5 && par1 <= var6)
261 {
262 this.scrollMultiplier = -1.0F;
263 var19 = this.func_77209_d();
264
265 if (var19 < 1)
266 {
267 var19 = 1;
268 }
269
270 var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
271
272 if (var13 < 32)
273 {
274 var13 = 32;
275 }
276
277 if (var13 > this.bottom - this.top - 8)
278 {
279 var13 = this.bottom - this.top - 8;
280 }
281
282 this.scrollMultiplier /= (float)(this.bottom - this.top - var13) / (float)var19;
283 }
284 else
285 {
286 this.scrollMultiplier = 1.0F;
287 }
288
289 if (var7)
290 {
291 this.initialClickY = (float)par2;
292 }
293 else
294 {
295 this.initialClickY = -2.0F;
296 }
297 }
298 else
299 {
300 this.initialClickY = -2.0F;
301 }
302 }
303 else if (this.initialClickY >= 0.0F)
304 {
305 this.amountScrolled -= ((float)par2 - this.initialClickY) * this.scrollMultiplier;
306 this.initialClickY = (float)par2;
307 }
308 }
309 else
310 {
311 while (!this.mc.gameSettings.touchscreen && Mouse.next())
312 {
313 int var16 = Mouse.getEventDWheel();
314
315 if (var16 != 0)
316 {
317 if (var16 > 0)
318 {
319 var16 = -1;
320 }
321 else if (var16 < 0)
322 {
323 var16 = 1;
324 }
325
326 this.amountScrolled += (float)(var16 * this.slotHeight / 2);
327 }
328 }
329
330 this.initialClickY = -1.0F;
331 }
332
333 this.bindAmountScrolled();
334 GL11.glDisable(GL11.GL_LIGHTING);
335 GL11.glDisable(GL11.GL_FOG);
336 Tessellator var18 = Tessellator.instance;
337 drawContainerBackground(var18);
338 var9 = this.width / 2 - 92 - 16;
339 var10 = this.top + 4 - (int)this.amountScrolled;
340
341 if (this.field_77243_s)
342 {
343 this.func_77222_a(var9, var10, var18);
344 }
345
346 int var14;
347
348 for (var11 = 0; var11 < var4; ++var11)
349 {
350 var19 = var10 + var11 * this.slotHeight + this.field_77242_t;
351 var13 = this.slotHeight - 4;
352
353 if (var19 <= this.bottom && var19 + var13 >= this.top)
354 {
355 if (this.showSelectionBox && this.isSelected(var11))
356 {
357 var14 = this.width / 2 - 110;
358 int var15 = this.width / 2 + 110;
359 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
360 GL11.glDisable(GL11.GL_TEXTURE_2D);
361 var18.startDrawingQuads();
362 var18.setColorOpaque_I(8421504);
363 var18.addVertexWithUV((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
364 var18.addVertexWithUV((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
365 var18.addVertexWithUV((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
366 var18.addVertexWithUV((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
367 var18.setColorOpaque_I(0);
368 var18.addVertexWithUV((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
369 var18.addVertexWithUV((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
370 var18.addVertexWithUV((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
371 var18.addVertexWithUV((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
372 var18.draw();
373 GL11.glEnable(GL11.GL_TEXTURE_2D);
374 }
375
376 this.drawSlot(var11, var9, var19, var13, var18);
377 }
378 }
379
380 GL11.glDisable(GL11.GL_DEPTH_TEST);
381 byte var20 = 4;
382 this.overlayBackground(0, this.top, 255, 255);
383 this.overlayBackground(this.bottom, this.height, 255, 255);
384 GL11.glEnable(GL11.GL_BLEND);
385 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
386 GL11.glDisable(GL11.GL_ALPHA_TEST);
387 GL11.glShadeModel(GL11.GL_SMOOTH);
388 GL11.glDisable(GL11.GL_TEXTURE_2D);
389 var18.startDrawingQuads();
390 var18.setColorRGBA_I(0, 0);
391 var18.addVertexWithUV((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
392 var18.addVertexWithUV((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
393 var18.setColorRGBA_I(0, 255);
394 var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
395 var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
396 var18.draw();
397 var18.startDrawingQuads();
398 var18.setColorRGBA_I(0, 255);
399 var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
400 var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
401 var18.setColorRGBA_I(0, 0);
402 var18.addVertexWithUV((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
403 var18.addVertexWithUV((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
404 var18.draw();
405 var19 = this.func_77209_d();
406
407 if (var19 > 0)
408 {
409 var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
410
411 if (var13 < 32)
412 {
413 var13 = 32;
414 }
415
416 if (var13 > this.bottom - this.top - 8)
417 {
418 var13 = this.bottom - this.top - 8;
419 }
420
421 var14 = (int)this.amountScrolled * (this.bottom - this.top - var13) / var19 + this.top;
422
423 if (var14 < this.top)
424 {
425 var14 = this.top;
426 }
427
428 var18.startDrawingQuads();
429 var18.setColorRGBA_I(0, 255);
430 var18.addVertexWithUV((double)var5, (double)this.bottom, 0.0D, 0.0D, 1.0D);
431 var18.addVertexWithUV((double)var6, (double)this.bottom, 0.0D, 1.0D, 1.0D);
432 var18.addVertexWithUV((double)var6, (double)this.top, 0.0D, 1.0D, 0.0D);
433 var18.addVertexWithUV((double)var5, (double)this.top, 0.0D, 0.0D, 0.0D);
434 var18.draw();
435 var18.startDrawingQuads();
436 var18.setColorRGBA_I(8421504, 255);
437 var18.addVertexWithUV((double)var5, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
438 var18.addVertexWithUV((double)var6, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
439 var18.addVertexWithUV((double)var6, (double)var14, 0.0D, 1.0D, 0.0D);
440 var18.addVertexWithUV((double)var5, (double)var14, 0.0D, 0.0D, 0.0D);
441 var18.draw();
442 var18.startDrawingQuads();
443 var18.setColorRGBA_I(12632256, 255);
444 var18.addVertexWithUV((double)var5, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
445 var18.addVertexWithUV((double)(var6 - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
446 var18.addVertexWithUV((double)(var6 - 1), (double)var14, 0.0D, 1.0D, 0.0D);
447 var18.addVertexWithUV((double)var5, (double)var14, 0.0D, 0.0D, 0.0D);
448 var18.draw();
449 }
450
451 this.func_77215_b(par1, par2);
452 GL11.glEnable(GL11.GL_TEXTURE_2D);
453 GL11.glShadeModel(GL11.GL_FLAT);
454 GL11.glEnable(GL11.GL_ALPHA_TEST);
455 GL11.glDisable(GL11.GL_BLEND);
456 }
457
458 protected int getScrollBarX()
459 {
460 return this.width / 2 + 124;
461 }
462
463 /**
464 * Overlays the background to hide scrolled items
465 */
466 protected void overlayBackground(int par1, int par2, int par3, int par4)
467 {
468 Tessellator var5 = Tessellator.instance;
469 GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.mc.renderEngine.getTexture(BACKGROUND_IMAGE));
470 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
471 float var6 = 32.0F;
472 var5.startDrawingQuads();
473 var5.setColorRGBA_I(4210752, par4);
474 var5.addVertexWithUV(0.0D, (double)par2, 0.0D, 0.0D, (double)((float)par2 / var6));
475 var5.addVertexWithUV((double)this.width, (double)par2, 0.0D, (double)((float)this.width / var6), (double)((float)par2 / var6));
476 var5.setColorRGBA_I(4210752, par3);
477 var5.addVertexWithUV((double)this.width, (double)par1, 0.0D, (double)((float)this.width / var6), (double)((float)par1 / var6));
478 var5.addVertexWithUV(0.0D, (double)par1, 0.0D, 0.0D, (double)((float)par1 / var6));
479 var5.draw();
480 }
481
482 protected void drawContainerBackground(Tessellator tess)
483 {
484 GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.renderEngine.getTexture(BACKGROUND_IMAGE));
485 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
486 float height = 32.0F;
487 tess.startDrawingQuads();
488 tess.setColorOpaque_I(2105376);
489 tess.addVertexWithUV((double)left, (double)bottom, 0.0D, (double)(left / height), (double)((bottom + (int)amountScrolled) / height));
490 tess.addVertexWithUV((double)right, (double)bottom, 0.0D, (double)(right / height), (double)((bottom + (int)amountScrolled) / height));
491 tess.addVertexWithUV((double)right, (double)top, 0.0D, (double)(right / height), (double)((top + (int)amountScrolled) / height));
492 tess.addVertexWithUV((double)left, (double)top, 0.0D, (double)(left / height), (double)((top + (int)amountScrolled) / height));
493 tess.draw();
494 }
495 }