private static void drawBox() { GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, 0.0f); GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(1.0f, -1.0f, 0.0f); GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(1.0f, 1.0f, 0.0f); GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, 0.0f); GL11.glEnd(); }
static { logger.config("fbo: supported=%s", fboSupported); logger.config("GL13: supported=%s, enabled=%s", gl13Supported, useGL13); int bits = GL11.GL_VIEWPORT_BIT | GL11.GL_SCISSOR_BIT | GL11.GL_DEPTH_BITS | GL11.GL_LIGHTING_BIT; if (useGL13) { bits |= GL13.GL_MULTISAMPLE_BIT; } glAttributes = bits; GL11.glNewList(drawList, GL11.GL_COMPILE); drawBox(); GL11.glEndList(); }
void read(ByteBuffer buffer) { EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer); buffer.position(0); GL11.glReadPixels( x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer); }
void delete() { if (!deleted) { deleted = true; if (ownTexture) { GL11.glDeleteTextures(texture); } EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffer); } }
private FancyDial(TextureAtlasSprite icon, PropertiesFile properties) { this.icon = icon; this.properties = properties; name = IconAPI.getIconName(icon); x0 = IconAPI.getIconX0(icon); y0 = IconAPI.getIconY0(icon); width = IconAPI.getIconWidth(icon); height = IconAPI.getIconHeight(icon); scratchBuffer = ByteBuffer.allocateDirect(4 * width * height); int itemsTexture = TexturePackAPI.getTextureIfLoaded(TexturePackAPI.ITEMS_PNG); if (itemsTexture < 0) { logger.severe("could not get items texture"); return; } itemsFBO = new FBO(itemsTexture, x0, y0, width, height); if (useScratchTexture) { logger.fine("rendering %s to %dx%d scratch texture", name, width, height); for (int i = 0; i < scratchFBO.length; i++) { scratchFBO[i] = new FBO(width, height); } } else { logger.fine("rendering %s directly to atlas", name); } boolean debug = false; for (int i = 0; ; i++) { Layer layer = newLayer(properties, "." + i); if (layer == null) { if (i > 0) { break; } continue; } layers.add(layer); debug |= layer.debug; logger.fine(" new %s", layer); } keyboard = new InputHandler(name, debug); if (layers.size() < 2) { logger.error("custom %s needs at least two layers defined", name); return; } outputFrames = properties.getInt("outputFrames", 0); int glError = GL11.glGetError(); if (glError != 0) { logger.severe("%s during %s setup", GLU.gluErrorString(glError), name); return; } ok = true; }
void write(ByteBuffer buffer) { GLAPI.glBindTexture(texture); buffer.position(0); GL11.glTexSubImage2D( GL11.GL_TEXTURE_2D, 0, x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer); }
public static boolean update(TextureAtlasSprite icon, boolean itemFrameRenderer) { if (!initialized) { logger.finer("deferring %s update until initialization finishes", IconAPI.getIconName(icon)); return false; } if (!active) { return false; } int oldFB = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT); if (oldFB != 0 && warnCount < 10) { logger.finer( "rendering %s while non-default framebuffer %d is active", IconAPI.getIconName(icon), oldFB); warnCount++; } int oldTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); try { FancyDial instance = getInstance(icon); return instance != null && instance.render(itemFrameRenderer); } finally { EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFB); GLAPI.glBindTexture(oldTexture); } }
void unbind() { GL11.glPopAttrib(); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPopMatrix(); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPopMatrix(); if (lightmapEnabled) { GL13.glActiveTexture(GL13.GL_TEXTURE1); GL11.glEnable(GL11.GL_TEXTURE_2D); GL13.glActiveTexture(GL13.GL_TEXTURE0); } GL11.glEnable(GL11.GL_BLEND); GLAPI.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); }
private void renderImpl(double angle) { for (Layer layer : layers) { layer.blendMethod.applyBlending(); GL11.glPushMatrix(); TexturePackAPI.bindTexture(layer.textureName); float offsetX = layer.offsetX; float offsetY = layer.offsetY; float scaleX = layer.scaleX; float scaleY = layer.scaleY; if (layer.debug) { offsetX += offsetXDelta; offsetY += offsetYDelta; scaleX += scaleXDelta; scaleY += scaleYDelta; } GL11.glTranslatef(offsetX, offsetY, 0.0f); GL11.glScalef(scaleX, scaleY, 1.0f); float layerAngle = (float) (angle * layer.rotationMultiplier + layer.rotationOffset); GL11.glRotatef(layerAngle, 0.0f, 0.0f, 1.0f); GL11.glCallList(drawList); GL11.glPopMatrix(); } }
@Override public void renderContentLayer(int localWidth, int localHeight, boolean isTranslatable) { String tStation = StatCollector.translateToLocal("manual.page.modifier1"); if (icons.length > 3) tStation = StatCollector.translateToLocal("manual.page.modifier2"); if (icons.length > 4) tStation = StatCollector.translateToLocal("manual.page.modifier3"); if (isTranslatable) tStation = StatCollector.translateToLocal(tStation); manual.fonts.drawString("\u00a7n" + tStation, localWidth + 60, localHeight + 4, 0); GL11.glScalef(2f, 2f, 2f); GL11.glEnable(GL12.GL_RESCALE_NORMAL); RenderHelper.enableGUIStandardItemLighting(); ItemStack toolstack = MantleClientRegistry.getManualIcon("ironpick"); if (type.equals("weapon")) toolstack = MantleClientRegistry.getManualIcon("ironlongsword"); if (type.equals("travelgoggles")) toolstack = MantleClientRegistry.getManualIcon("travelgoggles"); if (type.equals("travelvest")) toolstack = MantleClientRegistry.getManualIcon("travelvest"); if (type.equals("travelwings")) toolstack = MantleClientRegistry.getManualIcon("travelwings"); if (type.equals("travelboots")) toolstack = MantleClientRegistry.getManualIcon("travelboots"); if (type.equals("travelbelt")) toolstack = MantleClientRegistry.getManualIcon("travelbelt"); if (type.equals("travelglove")) toolstack = MantleClientRegistry.getManualIcon("travelglove"); if (type.equals("travelmulti")) toolstack = toolMulti[counter]; // update displayed item if (iconsMulti != null && iconsMulti.length > 0 && type.equals("travelmulti") && System.currentTimeMillis() - lastUpdate > 1000) { lastUpdate = System.currentTimeMillis(); counter++; if (counter >= iconsMulti.length) counter = 0; icons = iconsMulti[counter]; toolstack = toolMulti[counter]; } manual.renderitem.zLevel = 100; if (icons.length < 4) { manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, toolstack, (localWidth + 54) / 2, (localHeight + 54) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[0], (localWidth + 130) / 2, (localHeight + 54) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[1], (localWidth + 18) / 2, (localHeight + 36) / 2); if (icons[2] != null) manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[2], (localWidth + 18) / 2, (localHeight + 74) / 2); } else { manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, toolstack, (localWidth + 74) / 2, (localHeight + 54) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[0], (localWidth + 140) / 2, (localHeight + 54) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[1], (localWidth - 2) / 2, (localHeight + 36) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[2], (localWidth - 2) / 2, (localHeight + 74) / 2); manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[3], (localWidth + 36) / 2, (localHeight + 36) / 2); if (icons[4] != null) manual.renderitem.renderItemAndEffectIntoGUI( manual.fonts, manual.getMC().renderEngine, icons[4], (localWidth + 36) / 2, (localHeight + 74) / 2); } manual.renderitem.zLevel = 0; GL11.glScalef(0.5F, 0.5F, 0.5F); RenderHelper.disableStandardItemLighting(); GL11.glDisable(GL12.GL_RESCALE_NORMAL); }
private static int blankTexture(int width, int height) { int texture = GL11.glGenTextures(); MipmapHelper.setupTexture(texture, width, height, "scratch"); return texture; }
void bind() { EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer); GL11.glPushAttrib(glAttributes); GL11.glViewport(x0, y0, width, height); GL11.glEnable(GL11.GL_SCISSOR_TEST); GL11.glScissor(x0, y0, width, height); lightmapEnabled = false; if (gl13Supported) { GL13.glActiveTexture(GL13.GL_TEXTURE1); lightmapEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D); if (lightmapEnabled) { GL11.glDisable(GL11.GL_TEXTURE_2D); } GL13.glActiveTexture(GL13.GL_TEXTURE0); } GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_DEPTH_TEST); GLAPI.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_ALPHA_TEST); GLAPI.glAlphaFunc(GL11.GL_GREATER, 0.01f); if (useGL13) { GL11.glDisable(GL13.GL_MULTISAMPLE); } GLAPI.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPushMatrix(); GL11.glLoadIdentity(); GL11.glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPushMatrix(); GL11.glLoadIdentity(); }
private boolean render(boolean itemFrameRenderer) { if (!ok) { return false; } if (!itemFrameRenderer) { boolean changed = true; if (!keyboard.isEnabled()) { changed = false; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD2)) { scaleYDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD8)) { scaleYDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD4)) { scaleXDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD6)) { scaleXDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_DOWN)) { offsetYDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_UP)) { offsetYDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_LEFT)) { offsetXDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_RIGHT)) { offsetXDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_MULTIPLY)) { scaleXDelta = scaleYDelta = offsetXDelta = offsetYDelta = 0.0f; } else { changed = false; } if (changed) { logger.info(""); logger.info("scaleX %+f", scaleXDelta); logger.info("scaleY %+f", scaleYDelta); logger.info("offsetX %+f", offsetXDelta); logger.info("offsetY %+f", offsetYDelta); lastAngle = ANGLE_UNSET; } if (outputFrames > 0) { writeCustomImage(); outputFrames = 0; } } double angle = getAngle(icon); if (!useScratchTexture) { // render directly to items.png if (angle != lastAngle) { renderToItems(angle); lastAngle = angle; } } else if (itemFrameRenderer) { // look in itemFrames cache first ByteBuffer buffer = itemFrames.get(angle); if (buffer == null) { logger.fine("rendering %s at angle %f for item frame", name, angle); buffer = ByteBuffer.allocateDirect(width * height * 4); renderToItems(angle); itemsFBO.read(buffer); itemFrames.put(angle, buffer); } else { itemsFBO.write(buffer); } lastItemFrameRenderer = true; } else if (lastAngle == ANGLE_UNSET) { // first time rendering - render all N copies for (FBO fbo : scratchFBO) { renderToFB(angle, fbo); } scratchFBO[0].read(scratchBuffer); itemsFBO.write(scratchBuffer); lastAngle = angle; scratchIndex = 0; } else if (lastItemFrameRenderer || angle != lastAngle) { // render to buffer i + 1 // update items.png from buffer i int nextIndex = (scratchIndex + 1) % NUM_SCRATCH_TEXTURES; if (angle != lastAngle) { renderToFB(angle, scratchFBO[nextIndex]); scratchFBO[scratchIndex].read(scratchBuffer); } itemsFBO.write(scratchBuffer); lastAngle = angle; scratchIndex = nextIndex; lastItemFrameRenderer = false; } int glError = GL11.glGetError(); if (glError != 0) { logger.severe("%s during %s update", GLU.gluErrorString(glError), name); ok = false; } return ok; }
public class FancyDial { private static final MCLogger logger = MCLogger.getLogger(MCPatcherUtils.CUSTOM_ANIMATIONS, "Animation"); private static final double ANGLE_UNSET = Double.MAX_VALUE; private static final int NUM_SCRATCH_TEXTURES = 3; private static final boolean fboSupported = GLContext.getCapabilities().GL_EXT_framebuffer_object; private static final boolean gl13Supported = GLContext.getCapabilities().OpenGL13; private static final boolean enableCompass = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "fancyCompass", true); private static final boolean enableClock = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "fancyClock", true); private static final boolean useGL13 = gl13Supported && Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "useGL13", true); private static final boolean useScratchTexture = Config.getBoolean(MCPatcherUtils.EXTENDED_HD, "useScratchTexture", true); private static final int glAttributes; private static boolean initialized; private static boolean active; private static final int drawList = GL11.glGenLists(1); private static final Map<TextureAtlasSprite, ResourceLocation> setupInfo = new IdentityHashMap<TextureAtlasSprite, ResourceLocation>(); private static final Map<TextureAtlasSprite, FancyDial> instances = new IdentityHashMap<TextureAtlasSprite, FancyDial>(); private static int warnCount; private final TextureAtlasSprite icon; private final PropertiesFile properties; private final String name; private final int x0; private final int y0; private final int width; private final int height; private final ByteBuffer scratchBuffer; private final FBO[] scratchFBO = new FBO[NUM_SCRATCH_TEXTURES]; private FBO itemsFBO; private int scratchIndex; private Map<Double, ByteBuffer> itemFrames = new TreeMap<Double, ByteBuffer>(); private int outputFrames; private boolean ok; private double lastAngle = ANGLE_UNSET; private boolean lastItemFrameRenderer; private final List<Layer> layers = new ArrayList<Layer>(); private InputHandler keyboard; private static final float STEP = 0.01f; private float scaleXDelta; private float scaleYDelta; private float offsetXDelta; private float offsetYDelta; static { logger.config("fbo: supported=%s", fboSupported); logger.config("GL13: supported=%s, enabled=%s", gl13Supported, useGL13); int bits = GL11.GL_VIEWPORT_BIT | GL11.GL_SCISSOR_BIT | GL11.GL_DEPTH_BITS | GL11.GL_LIGHTING_BIT; if (useGL13) { bits |= GL13.GL_MULTISAMPLE_BIT; } glAttributes = bits; GL11.glNewList(drawList, GL11.GL_COMPILE); drawBox(); GL11.glEndList(); } public static void setup(TextureAtlasSprite icon) { if (!fboSupported) { return; } String name = IconAPI.getIconName(icon).replaceFirst("^minecraft:items/", ""); if (icon instanceof TextureClock && name.equals("compass")) { // 1.5 bug name = "clock"; } if ("compass".equals(name)) { if (!enableCompass) { return; } } else if ("clock".equals(name)) { if (!enableClock) { return; } } else { logger.warning("ignoring custom animation for %s not compass or clock", name); return; } ResourceLocation resource = TexturePackAPI.newMCPatcherResourceLocation( "/misc/" + name + ".properties", "dial/" + name + ".properties"); if (TexturePackAPI.hasResource(resource)) { logger.fine("found custom %s (%s)", name, resource); setupInfo.put(icon, resource); active = true; } } public static boolean update(TextureAtlasSprite icon, boolean itemFrameRenderer) { if (!initialized) { logger.finer("deferring %s update until initialization finishes", IconAPI.getIconName(icon)); return false; } if (!active) { return false; } int oldFB = GL11.glGetInteger(EXTFramebufferObject.GL_FRAMEBUFFER_BINDING_EXT); if (oldFB != 0 && warnCount < 10) { logger.finer( "rendering %s while non-default framebuffer %d is active", IconAPI.getIconName(icon), oldFB); warnCount++; } int oldTexture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); try { FancyDial instance = getInstance(icon); return instance != null && instance.render(itemFrameRenderer); } finally { EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, oldFB); GLAPI.glBindTexture(oldTexture); } } static void clearAll() { logger.finer("FancyDial.clearAll"); if (initialized) { active = false; setupInfo.clear(); } for (FancyDial instance : instances.values()) { if (instance != null) { instance.finish(); } } instances.clear(); initialized = true; } static void registerAnimations() { TextureObject texture = TexturePackAPI.getTextureObject(TexturePackAPI.ITEMS_PNG); if (texture instanceof TextureAtlas) { List<TextureAtlasSprite> animations = ((TextureAtlas) texture).animations; for (FancyDial instance : instances.values()) { instance.registerAnimation(animations); } } } void registerAnimation(List<TextureAtlasSprite> animations) { if (animations.contains(icon)) { return; } animations.add(icon); if (icon.animationFrames == null) { icon.animationFrames = new ArrayList<int[]>(); } if (icon.animationFrames.isEmpty()) { int[] dummyRGB = new int[width * height]; Arrays.fill(dummyRGB, 0xffff00ff); icon.animationFrames.add(dummyRGB); } logger.fine("registered %s animation", name); } private static FancyDial getInstance(TextureAtlasSprite icon) { if (instances.containsKey(icon)) { return instances.get(icon); } ResourceLocation resource = setupInfo.remove(icon); instances.put(icon, null); if (resource == null) { return null; } PropertiesFile properties = PropertiesFile.get(logger, resource); if (properties == null) { return null; } try { FancyDial instance = new FancyDial(icon, properties); if (instance.ok) { instances.put(icon, instance); return instance; } instance.finish(); } catch (Throwable e) { e.printStackTrace(); } return null; } private FancyDial(TextureAtlasSprite icon, PropertiesFile properties) { this.icon = icon; this.properties = properties; name = IconAPI.getIconName(icon); x0 = IconAPI.getIconX0(icon); y0 = IconAPI.getIconY0(icon); width = IconAPI.getIconWidth(icon); height = IconAPI.getIconHeight(icon); scratchBuffer = ByteBuffer.allocateDirect(4 * width * height); int itemsTexture = TexturePackAPI.getTextureIfLoaded(TexturePackAPI.ITEMS_PNG); if (itemsTexture < 0) { logger.severe("could not get items texture"); return; } itemsFBO = new FBO(itemsTexture, x0, y0, width, height); if (useScratchTexture) { logger.fine("rendering %s to %dx%d scratch texture", name, width, height); for (int i = 0; i < scratchFBO.length; i++) { scratchFBO[i] = new FBO(width, height); } } else { logger.fine("rendering %s directly to atlas", name); } boolean debug = false; for (int i = 0; ; i++) { Layer layer = newLayer(properties, "." + i); if (layer == null) { if (i > 0) { break; } continue; } layers.add(layer); debug |= layer.debug; logger.fine(" new %s", layer); } keyboard = new InputHandler(name, debug); if (layers.size() < 2) { logger.error("custom %s needs at least two layers defined", name); return; } outputFrames = properties.getInt("outputFrames", 0); int glError = GL11.glGetError(); if (glError != 0) { logger.severe("%s during %s setup", GLU.gluErrorString(glError), name); return; } ok = true; } private boolean render(boolean itemFrameRenderer) { if (!ok) { return false; } if (!itemFrameRenderer) { boolean changed = true; if (!keyboard.isEnabled()) { changed = false; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD2)) { scaleYDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD8)) { scaleYDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD4)) { scaleXDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_NUMPAD6)) { scaleXDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_DOWN)) { offsetYDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_UP)) { offsetYDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_LEFT)) { offsetXDelta -= STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_RIGHT)) { offsetXDelta += STEP; } else if (keyboard.isKeyPressed(Keyboard.KEY_MULTIPLY)) { scaleXDelta = scaleYDelta = offsetXDelta = offsetYDelta = 0.0f; } else { changed = false; } if (changed) { logger.info(""); logger.info("scaleX %+f", scaleXDelta); logger.info("scaleY %+f", scaleYDelta); logger.info("offsetX %+f", offsetXDelta); logger.info("offsetY %+f", offsetYDelta); lastAngle = ANGLE_UNSET; } if (outputFrames > 0) { writeCustomImage(); outputFrames = 0; } } double angle = getAngle(icon); if (!useScratchTexture) { // render directly to items.png if (angle != lastAngle) { renderToItems(angle); lastAngle = angle; } } else if (itemFrameRenderer) { // look in itemFrames cache first ByteBuffer buffer = itemFrames.get(angle); if (buffer == null) { logger.fine("rendering %s at angle %f for item frame", name, angle); buffer = ByteBuffer.allocateDirect(width * height * 4); renderToItems(angle); itemsFBO.read(buffer); itemFrames.put(angle, buffer); } else { itemsFBO.write(buffer); } lastItemFrameRenderer = true; } else if (lastAngle == ANGLE_UNSET) { // first time rendering - render all N copies for (FBO fbo : scratchFBO) { renderToFB(angle, fbo); } scratchFBO[0].read(scratchBuffer); itemsFBO.write(scratchBuffer); lastAngle = angle; scratchIndex = 0; } else if (lastItemFrameRenderer || angle != lastAngle) { // render to buffer i + 1 // update items.png from buffer i int nextIndex = (scratchIndex + 1) % NUM_SCRATCH_TEXTURES; if (angle != lastAngle) { renderToFB(angle, scratchFBO[nextIndex]); scratchFBO[scratchIndex].read(scratchBuffer); } itemsFBO.write(scratchBuffer); lastAngle = angle; scratchIndex = nextIndex; lastItemFrameRenderer = false; } int glError = GL11.glGetError(); if (glError != 0) { logger.severe("%s during %s update", GLU.gluErrorString(glError), name); ok = false; } return ok; } private void writeCustomImage() { try { BufferedImage image = new BufferedImage(width, outputFrames * height, BufferedImage.TYPE_INT_ARGB); IntBuffer intBuffer = scratchBuffer.asIntBuffer(); int[] argb = new int[width * height]; File path = MCPatcherUtils.getGamePath("custom_" + name + ".png"); logger.info("generating %d %s frames", outputFrames, name); for (int i = 0; i < outputFrames; i++) { renderToItems(i * (360.0 / outputFrames)); itemsFBO.read(scratchBuffer); intBuffer.position(0); for (int j = 0; j < argb.length; j++) { switch (MipmapHelper.TEX_FORMAT) { case GL12.GL_BGRA: int bgra = intBuffer.get(j); argb[j] = (bgra << 24) | ((bgra & 0xff00) << 8) | ((bgra & 0xff0000) >> 8) | (bgra >>> 24); break; default: if (i == 0 && j == 0) { logger.warning( "unhandled texture format %d, color channels may be incorrect", MipmapHelper.TEX_FORMAT); } // fall through case GL11.GL_RGBA: argb[j] = Integer.rotateRight(intBuffer.get(j), 8); break; } } image.setRGB(0, i * height, width, height, argb, 0, width); } ImageIO.write(image, "png", path); logger.info("wrote %dx%d %s", image.getWidth(), image.getHeight(), path.getPath()); } catch (Throwable e) { e.printStackTrace(); } } private void renderToItems(double angle) { renderToFB(angle, itemsFBO); } private void renderToFB(double angle, FBO fbo) { if (fbo != null) { fbo.bind(); renderImpl(angle); fbo.unbind(); } } private void renderImpl(double angle) { for (Layer layer : layers) { layer.blendMethod.applyBlending(); GL11.glPushMatrix(); TexturePackAPI.bindTexture(layer.textureName); float offsetX = layer.offsetX; float offsetY = layer.offsetY; float scaleX = layer.scaleX; float scaleY = layer.scaleY; if (layer.debug) { offsetX += offsetXDelta; offsetY += offsetYDelta; scaleX += scaleXDelta; scaleY += scaleYDelta; } GL11.glTranslatef(offsetX, offsetY, 0.0f); GL11.glScalef(scaleX, scaleY, 1.0f); float layerAngle = (float) (angle * layer.rotationMultiplier + layer.rotationOffset); GL11.glRotatef(layerAngle, 0.0f, 0.0f, 1.0f); GL11.glCallList(drawList); GL11.glPopMatrix(); } } private static void drawBox() { GL11.glBegin(GL11.GL_QUADS); GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3f(-1.0f, -1.0f, 0.0f); GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3f(1.0f, -1.0f, 0.0f); GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3f(1.0f, 1.0f, 0.0f); GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3f(-1.0f, 1.0f, 0.0f); GL11.glEnd(); } private void finish() { for (int i = 0; i < scratchFBO.length; i++) { if (scratchFBO[i] != null) { scratchFBO[i].delete(); scratchFBO[i] = null; } } if (itemsFBO != null) { itemsFBO.delete(); itemsFBO = null; } itemFrames.clear(); layers.clear(); ok = false; } @Override public String toString() { return String.format("FancyDial{%s, %dx%d @ %d,%d}", name, width, height, x0, y0); } @Override protected void finalize() throws Throwable { finish(); super.finalize(); } private static double getAngle(Icon icon) { if (icon instanceof TextureCompass) { return ((TextureCompass) icon).currentAngle * 180.0 / Math.PI; } else if (icon instanceof TextureClock) { return ((TextureClock) icon).currentAngle * 360.0; } else { return 0.0; } } Layer newLayer(PropertiesFile properties, String suffix) { ResourceLocation textureResource = properties.getResourceLocation("source" + suffix, ""); if (textureResource == null) { return null; } if (!TexturePackAPI.hasResource(textureResource)) { properties.error("could not read %s", textureResource); return null; } float scaleX = properties.getFloat("scaleX" + suffix, 1.0f); float scaleY = properties.getFloat("scaleY" + suffix, 1.0f); float offsetX = properties.getFloat("offsetX" + suffix, 0.0f); float offsetY = properties.getFloat("offsetY" + suffix, 0.0f); float angleMultiplier = properties.getFloat("rotationSpeed" + suffix, 0.0f); float angleOffset = properties.getFloat("rotationOffset" + suffix, 0.0f); String blend = properties.getString("blend" + suffix, "alpha"); BlendMethod blendMethod = BlendMethod.parse(blend); if (blendMethod == null) { properties.error("unknown blend method %s", blend); return null; } boolean debug = properties.getBoolean("debug" + suffix, false); return new Layer( textureResource, scaleX, scaleY, offsetX, offsetY, angleMultiplier, angleOffset, blendMethod, debug); } private class Layer { final ResourceLocation textureName; final float scaleX; final float scaleY; final float offsetX; final float offsetY; final float rotationMultiplier; final float rotationOffset; final BlendMethod blendMethod; final boolean debug; Layer( ResourceLocation textureName, float scaleX, float scaleY, float offsetX, float offsetY, float rotationMultiplier, float rotationOffset, BlendMethod blendMethod, boolean debug) { this.textureName = textureName; this.scaleX = scaleX; this.scaleY = scaleY; this.offsetX = offsetX; this.offsetY = offsetY; this.rotationMultiplier = rotationMultiplier; this.rotationOffset = rotationOffset; this.blendMethod = blendMethod; this.debug = debug; } @Override public String toString() { return String.format( "Layer{%s %f %f %+f %+f x%f}", textureName, scaleX, scaleY, offsetX, offsetY, rotationMultiplier); } } private static class FBO { private final int texture; private final boolean ownTexture; private final int x0; private final int y0; private final int width; private final int height; private final int frameBuffer; private boolean lightmapEnabled; private boolean deleted; FBO(int width, int height) { this(blankTexture(width, height), true, 0, 0, width, height); } FBO(int texture, int x0, int y0, int width, int height) { this(texture, false, x0, y0, width, height); } private FBO(int texture, boolean ownTexture, int x0, int y0, int width, int height) { this.texture = texture; this.ownTexture = ownTexture; this.x0 = x0; this.y0 = y0; this.width = width; this.height = height; frameBuffer = EXTFramebufferObject.glGenFramebuffersEXT(); if (frameBuffer < 0) { throw new RuntimeException("could not get framebuffer object"); } GLAPI.glBindTexture(texture); EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer); EXTFramebufferObject.glFramebufferTexture2DEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT, GL11.GL_TEXTURE_2D, texture, 0); } void bind() { EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer); GL11.glPushAttrib(glAttributes); GL11.glViewport(x0, y0, width, height); GL11.glEnable(GL11.GL_SCISSOR_TEST); GL11.glScissor(x0, y0, width, height); lightmapEnabled = false; if (gl13Supported) { GL13.glActiveTexture(GL13.GL_TEXTURE1); lightmapEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D); if (lightmapEnabled) { GL11.glDisable(GL11.GL_TEXTURE_2D); } GL13.glActiveTexture(GL13.GL_TEXTURE0); } GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_DEPTH_TEST); GLAPI.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); GL11.glDisable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_ALPHA_TEST); GLAPI.glAlphaFunc(GL11.GL_GREATER, 0.01f); if (useGL13) { GL11.glDisable(GL13.GL_MULTISAMPLE); } GLAPI.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPushMatrix(); GL11.glLoadIdentity(); GL11.glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPushMatrix(); GL11.glLoadIdentity(); } void unbind() { GL11.glPopAttrib(); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glPopMatrix(); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glPopMatrix(); if (lightmapEnabled) { GL13.glActiveTexture(GL13.GL_TEXTURE1); GL11.glEnable(GL11.GL_TEXTURE_2D); GL13.glActiveTexture(GL13.GL_TEXTURE0); } GL11.glEnable(GL11.GL_BLEND); GLAPI.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); EXTFramebufferObject.glBindFramebufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, 0); } void read(ByteBuffer buffer) { EXTFramebufferObject.glBindFramebufferEXT( EXTFramebufferObject.GL_FRAMEBUFFER_EXT, frameBuffer); buffer.position(0); GL11.glReadPixels( x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer); } void write(ByteBuffer buffer) { GLAPI.glBindTexture(texture); buffer.position(0); GL11.glTexSubImage2D( GL11.GL_TEXTURE_2D, 0, x0, y0, width, height, MipmapHelper.TEX_FORMAT, MipmapHelper.TEX_DATA_TYPE, buffer); } void delete() { if (!deleted) { deleted = true; if (ownTexture) { GL11.glDeleteTextures(texture); } EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffer); } } @Override protected void finalize() throws Throwable { delete(); super.finalize(); } private static int blankTexture(int width, int height) { int texture = GL11.glGenTextures(); MipmapHelper.setupTexture(texture, width, height, "scratch"); return texture; } } }
protected void drawToolTip(List par1List, int par2, int par3) { if (!par1List.isEmpty()) { GL11.glDisable(GL12.GL_RESCALE_NORMAL); RenderHelper.disableStandardItemLighting(); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); int k = 0; Iterator iterator = par1List.iterator(); while (iterator.hasNext()) { String s = (String) iterator.next(); int l = this.fontRenderer.getStringWidth(s); if (l > k) { k = l; } } int i1 = par2 + 12; int j1 = par3 - 12; int k1 = 8; if (par1List.size() > 1) { k1 += 2 + (par1List.size() - 1) * 10; } if (i1 + k > this.width) { i1 -= 28 + k; } if (j1 + k1 + 6 > this.height) { j1 = this.height - k1 - 6; } this.zLevel = 300.0F; itemRenderer.zLevel = 300.0F; int l1 = -267386864; this.drawGradientRect(i1 - 3, j1 - 4, i1 + k + 3, j1 - 3, l1, l1); this.drawGradientRect(i1 - 3, j1 + k1 + 3, i1 + k + 3, j1 + k1 + 4, l1, l1); this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 + k1 + 3, l1, l1); this.drawGradientRect(i1 - 4, j1 - 3, i1 - 3, j1 + k1 + 3, l1, l1); this.drawGradientRect(i1 + k + 3, j1 - 3, i1 + k + 4, j1 + k1 + 3, l1, l1); int i2 = 1347420415; int j2 = (i2 & 16711422) >> 1 | i2 & -16777216; this.drawGradientRect(i1 - 3, j1 - 3 + 1, i1 - 3 + 1, j1 + k1 + 3 - 1, i2, j2); this.drawGradientRect(i1 + k + 2, j1 - 3 + 1, i1 + k + 3, j1 + k1 + 3 - 1, i2, j2); this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 - 3 + 1, i2, i2); this.drawGradientRect(i1 - 3, j1 + k1 + 2, i1 + k + 3, j1 + k1 + 3, j2, j2); for (int k2 = 0; k2 < par1List.size(); ++k2) { String s1 = (String) par1List.get(k2); this.fontRenderer.drawStringWithShadow(s1, i1, j1, -1); if (k2 == 0) { j1 += 2; } j1 += 10; } this.zLevel = 0.0F; itemRenderer.zLevel = 0.0F; } }
@Override protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(background); int cornerX = (width - xSize) / 2 + 36; int cornerY = (height - ySize) / 2; drawTexturedModalRect(cornerX + 46, cornerY, 0, 0, 176, ySize); // Fuel - Lava this.mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); if (scomp.fuelGague > 0) { Icon lavaIcon = Block.lavaStill.getIcon(0, 0); int fuel = scomp.getScaledFuelGague(52); int count = 0; while (fuel > 0) { int size = fuel >= 16 ? 16 : fuel; fuel -= size; drawLiquidRect(cornerX + 117, (cornerY + 68) - size - 16 * count, lavaIcon, 12, size); count++; } } FluidTankInfo[] info = logic.getTankInfo(ForgeDirection.UNKNOWN); int capacity = 0; for (int i = 0; i < info.length - 1; i++) { FluidStack liquid = info[i].fluid; if (liquid != null) capacity += info[i].capacity; } // Liquids - molten metal int base = 0; for (int i = 0; i < info.length - 1; i++) { FluidStack liquid = info[i].fluid; Icon renderIndex = liquid.getFluid().getStillIcon(); int basePos = 54; if (capacity > 0) { int liquidSize = liquid.amount * 52 / capacity; if (liquidSize == 0) liquidSize = 1; while (liquidSize > 0) { int size = liquidSize >= 16 ? 16 : liquidSize; drawLiquidRect(cornerX + basePos, (cornerY + 68) - size - base, renderIndex, 16, size); drawLiquidRect( cornerX + basePos + 16, (cornerY + 68) - size - base, renderIndex, 16, size); drawLiquidRect( cornerX + basePos + 32, (cornerY + 68) - size - base, renderIndex, 16, size); drawLiquidRect( cornerX + basePos + 48, (cornerY + 68) - size - base, renderIndex, 4, size); liquidSize -= size; base += size; } } } // Liquid gague GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(background); drawTexturedModalRect(cornerX + 54, cornerY + 16, 176, 76, 52, 52); // Side inventory GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(backgroundSide); // if (logic.layers > 0) { /*if (logic.layers == 1) { drawTexturedModalRect(cornerX - 46, cornerY, 0, 0, 98, 43); drawTexturedModalRect(cornerX - 46, cornerY + 43, 0, 133, 98, 25); } else if (logic.layers == 2) { drawTexturedModalRect(cornerX - 46, cornerY, 0, 0, 98, 61); drawTexturedModalRect(cornerX - 46, cornerY + 61, 0, 97, 98, 61); } else*/ { drawTexturedModalRect(cornerX - 46, cornerY, 0, 0, 98, ySize - 8); } drawTexturedModalRect(cornerX + 32, (int) (cornerY + 8 + 127 * currentScroll), 98, 0, 12, 15); } // Temperature int slotSize = logic.getSizeInventory(); if (slotSize > 24) slotSize = 24; for (int iter = 0; iter < slotSize; iter++) { int slotTemp = logic.getTempForSlot(iter + slotPos * 3) - 20; int maxTemp = logic.getMeltingPointForSlot(iter + slotPos * 3) - 20; if (slotTemp > 0 && maxTemp > 0) { int size = 16 * slotTemp / maxTemp + 1; drawTexturedModalRect( cornerX - 38 + (iter % 3 * 22), cornerY + 8 + (iter / 3 * 18) + 16 - size, 98, 15 + 16 - size, 5, size); } } }