001package net.minecraft.client.gui; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.List; 006import net.minecraft.client.Minecraft; 007import net.minecraft.client.renderer.Tessellator; 008import org.lwjgl.input.Mouse; 009import org.lwjgl.opengl.GL11; 010 011@SideOnly(Side.CLIENT) 012public 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 i, boolean flag); 121 122 /** 123 * returns true if the element passed in is currently selected 124 */ 125 protected abstract boolean isSelected(int i); 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 i, int j, int k, int l, Tessellator tessellator); 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 k = this.width / 2 - 110; 148 int l = this.width / 2 + 110; 149 int i1 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4; 150 int j1 = i1 / this.slotHeight; 151 return par1 >= k && par1 <= l && j1 >= 0 && i1 >= 0 && j1 < this.getSize() ? j1 : -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 i = this.func_77209_d(); 169 170 if (i < 0) 171 { 172 i /= 2; 173 } 174 175 if (this.amountScrolled < 0.0F) 176 { 177 this.amountScrolled = 0.0F; 178 } 179 180 if (this.amountScrolled > (float)i) 181 { 182 this.amountScrolled = (float)i; 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 k = this.getSize(); 226 int l = this.getScrollBarX(); 227 int i1 = l + 6; 228 int j1; 229 int k1; 230 int l1; 231 int i2; 232 int j2; 233 234 if (Mouse.isButtonDown(0)) 235 { 236 if (this.initialClickY == -1.0F) 237 { 238 boolean flag = true; 239 240 if (par2 >= this.top && par2 <= this.bottom) 241 { 242 int k2 = this.width / 2 - 110; 243 j1 = this.width / 2 + 110; 244 k1 = par2 - this.top - this.field_77242_t + (int)this.amountScrolled - 4; 245 l1 = k1 / this.slotHeight; 246 247 if (par1 >= k2 && par1 <= j1 && l1 >= 0 && k1 >= 0 && l1 < k) 248 { 249 boolean flag1 = l1 == this.selectedElement && Minecraft.getSystemTime() - this.lastClicked < 250L; 250 this.elementClicked(l1, flag1); 251 this.selectedElement = l1; 252 this.lastClicked = Minecraft.getSystemTime(); 253 } 254 else if (par1 >= k2 && par1 <= j1 && k1 < 0) 255 { 256 this.func_77224_a(par1 - k2, par2 - this.top + (int)this.amountScrolled - 4); 257 flag = false; 258 } 259 260 if (par1 >= l && par1 <= i1) 261 { 262 this.scrollMultiplier = -1.0F; 263 j2 = this.func_77209_d(); 264 265 if (j2 < 1) 266 { 267 j2 = 1; 268 } 269 270 i2 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight()); 271 272 if (i2 < 32) 273 { 274 i2 = 32; 275 } 276 277 if (i2 > this.bottom - this.top - 8) 278 { 279 i2 = this.bottom - this.top - 8; 280 } 281 282 this.scrollMultiplier /= (float)(this.bottom - this.top - i2) / (float)j2; 283 } 284 else 285 { 286 this.scrollMultiplier = 1.0F; 287 } 288 289 if (flag) 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 l2 = Mouse.getEventDWheel(); 314 315 if (l2 != 0) 316 { 317 if (l2 > 0) 318 { 319 l2 = -1; 320 } 321 else if (l2 < 0) 322 { 323 l2 = 1; 324 } 325 326 this.amountScrolled += (float)(l2 * 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 tessellator = Tessellator.instance; 337 drawContainerBackground(tessellator); 338 j1 = this.width / 2 - 92 - 16; 339 k1 = this.top + 4 - (int)this.amountScrolled; 340 341 if (this.field_77243_s) 342 { 343 this.func_77222_a(j1, k1, tessellator); 344 } 345 346 int i3; 347 348 for (l1 = 0; l1 < k; ++l1) 349 { 350 j2 = k1 + l1 * this.slotHeight + this.field_77242_t; 351 i2 = this.slotHeight - 4; 352 353 if (j2 <= this.bottom && j2 + i2 >= this.top) 354 { 355 if (this.showSelectionBox && this.isSelected(l1)) 356 { 357 i3 = this.width / 2 - 110; 358 int j3 = this.width / 2 + 110; 359 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); 360 GL11.glDisable(GL11.GL_TEXTURE_2D); 361 tessellator.startDrawingQuads(); 362 tessellator.setColorOpaque_I(8421504); 363 tessellator.addVertexWithUV((double)i3, (double)(j2 + i2 + 2), 0.0D, 0.0D, 1.0D); 364 tessellator.addVertexWithUV((double)j3, (double)(j2 + i2 + 2), 0.0D, 1.0D, 1.0D); 365 tessellator.addVertexWithUV((double)j3, (double)(j2 - 2), 0.0D, 1.0D, 0.0D); 366 tessellator.addVertexWithUV((double)i3, (double)(j2 - 2), 0.0D, 0.0D, 0.0D); 367 tessellator.setColorOpaque_I(0); 368 tessellator.addVertexWithUV((double)(i3 + 1), (double)(j2 + i2 + 1), 0.0D, 0.0D, 1.0D); 369 tessellator.addVertexWithUV((double)(j3 - 1), (double)(j2 + i2 + 1), 0.0D, 1.0D, 1.0D); 370 tessellator.addVertexWithUV((double)(j3 - 1), (double)(j2 - 1), 0.0D, 1.0D, 0.0D); 371 tessellator.addVertexWithUV((double)(i3 + 1), (double)(j2 - 1), 0.0D, 0.0D, 0.0D); 372 tessellator.draw(); 373 GL11.glEnable(GL11.GL_TEXTURE_2D); 374 } 375 376 this.drawSlot(l1, j1, j2, i2, tessellator); 377 } 378 } 379 380 GL11.glDisable(GL11.GL_DEPTH_TEST); 381 byte b0 = 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 tessellator.startDrawingQuads(); 390 tessellator.setColorRGBA_I(0, 0); 391 tessellator.addVertexWithUV((double)this.left, (double)(this.top + b0), 0.0D, 0.0D, 1.0D); 392 tessellator.addVertexWithUV((double)this.right, (double)(this.top + b0), 0.0D, 1.0D, 1.0D); 393 tessellator.setColorRGBA_I(0, 255); 394 tessellator.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D); 395 tessellator.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D); 396 tessellator.draw(); 397 tessellator.startDrawingQuads(); 398 tessellator.setColorRGBA_I(0, 255); 399 tessellator.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D); 400 tessellator.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D); 401 tessellator.setColorRGBA_I(0, 0); 402 tessellator.addVertexWithUV((double)this.right, (double)(this.bottom - b0), 0.0D, 1.0D, 0.0D); 403 tessellator.addVertexWithUV((double)this.left, (double)(this.bottom - b0), 0.0D, 0.0D, 0.0D); 404 tessellator.draw(); 405 j2 = this.func_77209_d(); 406 407 if (j2 > 0) 408 { 409 i2 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight(); 410 411 if (i2 < 32) 412 { 413 i2 = 32; 414 } 415 416 if (i2 > this.bottom - this.top - 8) 417 { 418 i2 = this.bottom - this.top - 8; 419 } 420 421 i3 = (int)this.amountScrolled * (this.bottom - this.top - i2) / j2 + this.top; 422 423 if (i3 < this.top) 424 { 425 i3 = this.top; 426 } 427 428 tessellator.startDrawingQuads(); 429 tessellator.setColorRGBA_I(0, 255); 430 tessellator.addVertexWithUV((double)l, (double)this.bottom, 0.0D, 0.0D, 1.0D); 431 tessellator.addVertexWithUV((double)i1, (double)this.bottom, 0.0D, 1.0D, 1.0D); 432 tessellator.addVertexWithUV((double)i1, (double)this.top, 0.0D, 1.0D, 0.0D); 433 tessellator.addVertexWithUV((double)l, (double)this.top, 0.0D, 0.0D, 0.0D); 434 tessellator.draw(); 435 tessellator.startDrawingQuads(); 436 tessellator.setColorRGBA_I(8421504, 255); 437 tessellator.addVertexWithUV((double)l, (double)(i3 + i2), 0.0D, 0.0D, 1.0D); 438 tessellator.addVertexWithUV((double)i1, (double)(i3 + i2), 0.0D, 1.0D, 1.0D); 439 tessellator.addVertexWithUV((double)i1, (double)i3, 0.0D, 1.0D, 0.0D); 440 tessellator.addVertexWithUV((double)l, (double)i3, 0.0D, 0.0D, 0.0D); 441 tessellator.draw(); 442 tessellator.startDrawingQuads(); 443 tessellator.setColorRGBA_I(12632256, 255); 444 tessellator.addVertexWithUV((double)l, (double)(i3 + i2 - 1), 0.0D, 0.0D, 1.0D); 445 tessellator.addVertexWithUV((double)(i1 - 1), (double)(i3 + i2 - 1), 0.0D, 1.0D, 1.0D); 446 tessellator.addVertexWithUV((double)(i1 - 1), (double)i3, 0.0D, 1.0D, 0.0D); 447 tessellator.addVertexWithUV((double)l, (double)i3, 0.0D, 0.0D, 0.0D); 448 tessellator.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 tessellator = Tessellator.instance; 469 this.mc.renderEngine.bindTexture(BACKGROUND_IMAGE); 470 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); 471 float f = 32.0F; 472 tessellator.startDrawingQuads(); 473 tessellator.setColorRGBA_I(4210752, par4); 474 tessellator.addVertexWithUV(0.0D, (double)par2, 0.0D, 0.0D, (double)((float)par2 / f)); 475 tessellator.addVertexWithUV((double)this.width, (double)par2, 0.0D, (double)((float)this.width / f), (double)((float)par2 / f)); 476 tessellator.setColorRGBA_I(4210752, par3); 477 tessellator.addVertexWithUV((double)this.width, (double)par1, 0.0D, (double)((float)this.width / f), (double)((float)par1 / f)); 478 tessellator.addVertexWithUV(0.0D, (double)par1, 0.0D, 0.0D, (double)((float)par1 / f)); 479 tessellator.draw(); 480 } 481 482 protected void drawContainerBackground(Tessellator tess) 483 { 484 this.mc.renderEngine.bindTexture(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}