Jump to content

Bug while printing images into GUIs


Raycoms

Recommended Posts

We are printing several types of images into our GUI's using the following code.

 

 this.mc.getTextureManager().bindTexture(resourceLocation);

        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        //Draw
        drawModalRectWithCustomSizedTexture(x, y,
                imageOffsetX, imageOffsetY,
                imageWidth != 0 ? imageWidth : getWidth(),
                imageHeight != 0 ? imageHeight : getHeight(),
                mapWidth, mapHeight);

 

This usually works very well.

But if our resource is the icons.png from minecraft and we turn on f3 the images messes completely up and displays some white strange artifacts.

This also happens if any text is written out ingame.

 

Strangely this does not happen if we put the following line of code before the bingTexture.

 

        this.mc.getTextureManager().tick(); 

 

 

Link to comment
Share on other sites

Okay, we have an image class:

 

package com.blockout.controls;

import com.blockout.Pane;
import com.blockout.PaneParams;
import com.minecolonies.util.Log;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Tuple;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
import java.util.Iterator;

/**
* Simple image element.
*/
public class Image extends Pane
{
    public static final int MINECRAFT_DEFAULT_TEXTURE_MAP_SIZE = 256;

    protected ResourceLocation resourceLocation;
    protected int imageOffsetX = 0;
    protected int imageOffsetY = 0;
    protected int imageWidth = 0;
    protected int imageHeight = 0;
    protected int mapWidth = MINECRAFT_DEFAULT_TEXTURE_MAP_SIZE;
    protected int mapHeight = MINECRAFT_DEFAULT_TEXTURE_MAP_SIZE;

    /**
     * Default Constructor.
     */
    public Image()
    {
        super();
    }

    /**
     * Constructor used by the xml loader.
     *
     * @param params PaneParams loaded from the xml.
     */
    public Image(PaneParams params)
    {
        super(params);
        String source = params.getStringAttribute("source", null);
        if (source != null)
        {
            resourceLocation = new ResourceLocation(source);
            loadMapDimensions();
        }

        PaneParams.SizePair size = params.getSizePairAttribute("imageoffset", null, null);
        if (size != null)
        {
            imageOffsetX = size.getX();
            imageOffsetY = size.getY();
        }

        size = params.getSizePairAttribute("imagesize", null, null);
        if (size != null)
        {
            imageWidth = size.getX();
            imageHeight = size.getY();
        }
    }

    /**
     * Set the image.
     *
     * @param source String path.
     */
    public void setImage(String source)
    {
        setImage(source, 0, 0, 0, 0);
    }

    /**
     * Set the image.
     *
     * @param source  String path.
     * @param offsetX image x offset.
     * @param offsetY image y offset.
     * @param w       image width.
     * @param h       image height.
     */
    public void setImage(String source, int offsetX, int offsetY, int w, int h)
    {
        setImage((source != null) ? new ResourceLocation(source) : null, offsetX, offsetY, w, h);
    }

    /**
     * Set the image.
     *
     * @param loc ResourceLocation for the image.
     */
    public void setImage(ResourceLocation loc)
    {
        setImage(loc, 0, 0, 0, 0);
    }

    /**
     * Set the image.
     *
     * @param loc     ResourceLocation for the image.
     * @param offsetX image x offset.
     * @param offsetY image y offset.
     * @param w       image width.
     * @param h       image height.
     */
    public void setImage(ResourceLocation loc, int offsetX, int offsetY, int w, int h)
    {
        resourceLocation = loc;
        imageOffsetX = offsetX;
        imageOffsetY = offsetY;
        imageWidth = w;
        imageHeight = h;

        loadMapDimensions();
    }

    /**
     * Draw this image on the GUI.
     *
     * @param mx Mouse x (relative to parent)
     * @param my Mouse y (relative to parent)
     */
    @Override
    protected void drawSelf(int mx, int my)
    {
        // Some other texture must need to be ticked, I tried ticking the current one.
        // This fixes the problem, even if you put it after the draw call. So I guess I'll keep it.
        this.mc.getTextureManager().bindTexture(resourceLocation);

        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        //Draw
        drawModalRectWithCustomSizedTexture(x, y,
                imageOffsetX, imageOffsetY,
                imageWidth != 0 ? imageWidth : getWidth(),
                imageHeight != 0 ? imageHeight : getHeight(),
                mapWidth, mapHeight);
    }

    private void loadMapDimensions()
    {
        Tuple<Integer, Integer> dimensions = getImageDimensions(resourceLocation);
        mapWidth = dimensions.getFirst();
        mapHeight = dimensions.getSecond();
    }

    /**
     * Load and image from a {@link ResourceLocation} and return a {@link Tuple} containing its width and height.
     *
     * @param resourceLocation The {@link ResourceLocation} pointing to the image.
     * @return Width and height.
     */
    public static Tuple<Integer, Integer> getImageDimensions(ResourceLocation resourceLocation)
    {
        int width = 0;
        int height = 0;

        Iterator<ImageReader> it = ImageIO.getImageReadersBySuffix("png");
        if (it.hasNext())
        {
            ImageReader reader = it.next();
            try (ImageInputStream stream = ImageIO.createImageInputStream(Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream()))
            {
                reader.setInput(stream);
                width = reader.getWidth(reader.getMinIndex());
                height = reader.getHeight(reader.getMinIndex());
            }
            catch (IOException e)
            {
                Log.logger.error(e);
            }
            finally
            {
                reader.dispose();
            }
        }

        return new Tuple<>(width, height);
    }
}

 

which extends from a pane.

 

package com.blockout;

import com.blockout.views.Window;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

import java.nio.FloatBuffer;
import java.util.Deque;
import java.util.concurrent.ConcurrentLinkedDeque;

/**
* A Pane is the root of all UI objects
*/
public class Pane extends Gui
{
    protected Minecraft mc = Minecraft.getMinecraft();

    //  Attributes
    protected String    id = "";
    protected int       x  = 0;
    protected int       y  = 0;

    protected int       width  = 0;
    protected int       height = 0;

    protected Alignment alignment = Alignment.TopLeft;
    protected boolean   visible   = true;
    protected boolean   enabled   = true;

    //  Runtime
    protected        Window window;
    protected        View   parent;
    protected static Pane   lastClickedPane;
    protected static Pane   focus;

    protected static boolean debugging = false;

    private static Deque<ScissorsInfo> scissorsInfoStack = new ConcurrentLinkedDeque<>();

    /**
     * Default constructor
     */
    public Pane()
    {
        //Required for panes.
    }

    /**
     * Constructs a Pane from PaneParams
     *
     * @param params Params for the Pane
     */
    public Pane(PaneParams params)
    {
        id = params.getStringAttribute("id", id);

        PaneParams.SizePair parentSizePair = new PaneParams.SizePair(params.getParentWidth(), params.getParentHeight());
        PaneParams.SizePair sizePair = params.getSizePairAttribute("size", null, parentSizePair);
        if (sizePair != null)
        {
            width = sizePair.getX();
            height = sizePair.getY();
        }
        else
        {
            width = params.getScalableIntegerAttribute("width", width, parentSizePair.getX());
            height = params.getScalableIntegerAttribute("height", height, parentSizePair.getY());
        }

        sizePair = params.getSizePairAttribute("pos", null, parentSizePair);
        if (sizePair != null)
        {
            x = sizePair.getX();
            y = sizePair.getY();
        }
        else
        {
            x = params.getScalableIntegerAttribute("x", x, parentSizePair.getX());
            y = params.getScalableIntegerAttribute("y", y, parentSizePair.getY());
        }

        alignment = params.getEnumAttribute("align", Alignment.class, alignment);
        visible   = params.getBooleanAttribute("visible", visible);
        enabled   = params.getBooleanAttribute("enabled", enabled);
    }

    public void parseChildren(PaneParams params)
    {
        // Can be overloaded
    }

    //  ID
    public final String getID()
    {
        return id;
    }

    public final void setID(String id)
    {
        this.id = id;
    }

    //  Dimensions
    public int getWidth()
    {
        return width;
    }

    public int getHeight()
    {
        return height;
    }

    public void setSize(int w, int h)
    {
        width = w;
        height = h;
    }

    //  Position
    public int getX()
    {
        return x;
    }

    public int getY()
    {
        return y;
    }
    public void setPosition(int newX, int newY)
    {
        x = newX;
        y = newY;
    }

    public void moveBy(int dx, int dy)
    {
        x += dx;
        y += dy;
    }

    public Alignment getAlignment()
    {
        return alignment;
    }

    public void setAlignment(Alignment alignment)
    {
        this.alignment = alignment;
    }

    //  Visibility
    public boolean isVisible()
    {
        return visible;
    }

    public void setVisible(boolean v)
    {
        visible = v;
    }

    public void show()
    {
        setVisible(true);
    }

    public void hide()
    {
        setVisible(false);
    }

    //  Enabling
    public boolean isEnabled()
    {
        return enabled;
    }

    public void setEnabled(boolean e)
    {
        enabled = e;
    }

    public void enable()
    {
        setEnabled(true);
    }

    public void disable()
    {
        setEnabled(false);
    }


    //  Focus

    /**
     * Returns the currently focused Pane
     * @return the currently focused Pane
     */
    public static synchronized Pane getFocus()
    {
        return focus;
    }

    /**
     * Set the currently focused Pane
     *
     * @param f Pane to focus, or nil
     */
    public static synchronized void setFocus(Pane f)
    {
        if (focus != null)
        {
            focus.onFocusLost();
        }

        focus = f;

        if (focus != null)
        {
            focus.onFocus();
        }
    }

    /**
     * Clear the currently focused Pane.
     */
    public static void clearFocus()
    {
        setFocus(null);
    }

    /**
     * Set Focus to this Pane.
     */
    public final void setFocus()
    {
        setFocus(this);
    }

    /**
     * Return <tt>true</tt> if this Pane is the current focus.
     *
     * @return <tt>true</tt> if this Pane is the current focus
     */
    public final synchronized boolean isFocus()
    {
        return focus == this;
    }

    /**
     * Override to respond to the Pane losing focus
     */
    public void onFocusLost()
    {
        // Can be overloaded
    }

    /**
     * Override to respond to the Pane becoming the current focus
     */
    public void onFocus()
    {
        // Can be overloaded
    }

    //  Drawing

    /**
     * Draw the current Pane if visible.
     *
     * @param mx mouse x
     * @param my mouse y
     */
    public final void draw(int mx, int my)
    {
        if (visible)
        {
            GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
            drawSelf(mx, my);
            GL11.glPopAttrib();

            if (debugging)
            {
                GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);

                boolean isMouseOver = isPointInPane(mx, my);
                int color = isMouseOver ? 0xFF00FF00 : 0xFF0000FF;

                Render.drawOutlineRect(x, y, x+getWidth(), y+getHeight(), color);

                if (isMouseOver && !id.isEmpty())
                {
                    int stringWidth = mc.fontRendererObj.getStringWidth(id);
                    mc.fontRendererObj.drawString(id, x + getWidth() - stringWidth, y + getHeight() - mc.fontRendererObj.FONT_HEIGHT, color);
                }

                GL11.glPopAttrib();
            }
        }
    }

    /**
     * Draw self.  The graphics port is already relative to the appropriate location
     *
     * Override this to actually draw.
     *
     * @param mx Mouse x (relative to parent)
     * @param my Mouse y (relative to parent)
     */
    protected void drawSelf(int mx, int my)
    {
        // Can be overloaded
    }

    //  Subpanes

    /**
     * Returns the first Pane of a given ID
     * Performs a depth-first search on the hierarchy of Panes and Views
     *
     * @param id ID of Pane to find
     * @return a Pane of the given ID
     */
    public Pane findPaneByID(String id)
    {
        return this.id.equals(id) ? this : null;
    }

    /**
     * Returns the first Pane (depth-first search) of a given ID,
     * if it matches the specified type.
     * Performs a depth-first search on the hierarchy of Panes and Views.
     *
     * @param id ID of Pane to find
     * @param type Class of the desired Pane type
     * @param <T> The type of pane returned
     * @return a Pane of the given ID, if it matches the specified type
     */
    public final <T extends Pane> T findPaneOfTypeByID(String id, Class<T> type)
    {
        Pane p = findPaneByID(id);
        try
        {
            return type.cast(p);
        }
        catch (ClassCastException e)
        {
            throw new IllegalArgumentException(String.format("No pane with id %s and type %s was found.", id, type), e);
        }
    }

    /**
     * Return the Pane that contains this one.
     *
     * @return the Pane that contains this one
     */
    public final View getParent()
    {
        return parent;
    }

    /**
     * Return the Window that this Pane ultimately belongs to.
     *
     * @return the Window that this Pane belongs to.
     */
    public final Window getWindow()
    {
        return window;
    }

    protected void setWindow(Window w)
    {
        window = w;
    }

    /**
     * Put this Pane inside a View.  Only Views and subclasses can contain Panes
     *
     * @param newParent the View to put this Pane into, or null to remove from Parents
     */
    public void putInside(View newParent)
    {
        if (parent != null)
        {
            parent.removeChild(this);
        }

        parent = newParent;

        if (parent != null)
        {
            parent.addChild(this);
        }
    }

    //  Mouse

    /**
     * Is a point relative to the parent's origin within the pane?
     *
     * @param mx point x
     * @param my point y
     * @return true if the point is in the pane
     */
    protected boolean isPointInPane(int mx, int my)
    {
        return mx >= x && mx < (x + width) &&
               my >= y && my < (y + height);
    }

    public boolean isClickable()
    {
        return visible && enabled;
    }

    /**
     * Process a click on the Pane
     *
     * Override this to process the actual click
     *
     * @param mx mouse X coordinate, relative to Pane's top-left
     * @param my mouse Y coordinate, relative to Pane's top-left
     */
    public void handleClick(int mx, int my)
    {
        // Can be overloaded
    }

    /**
     * Process a mouse down on the Pane.
     *
     * It is advised that only containers of other panes override this method
     *
     * @param mx mouse X coordinate, relative to parent's top-left
     * @param my mouse Y coordinate, relative to parent's top-left
     */
    public void click(int mx, int my)
    {
        setLastClickedPane(this);
        handleClick(mx - x, my - y);
    }

    private static synchronized void setLastClickedPane(Pane pane)
    {
        lastClickedPane = pane;
    }

    public boolean canHandleClick(int mx, int my)
    {
        return visible && enabled && isPointInPane(mx, my);
    }

    public boolean onKeyTyped(char ch, int key)
    {
        return false;
    }

    public void onUpdate()
    {
        // Can be overloaded
    }

    private static class ScissorsInfo
    {
        private int x;
        private int y;
        private int width;
        private int height;

        ScissorsInfo(int x, int y, int w, int h)
        {
            this.x = x;
            this.y = y;
            this.width = w;
            this.height = h;
        }
    }

    protected synchronized void scissorsStart()
    {
        FloatBuffer fb = BufferUtils.createFloatBuffer(16 * 4);
        GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, fb);

        int scissorsX = (int) fb.get(12) + getX();
        int scissorsY = (int) fb.get(13) + getY();
        int h = getHeight();
        int w = getWidth();

        if (!scissorsInfoStack.isEmpty())
        {
            ScissorsInfo parentInfo = scissorsInfoStack.peek();
            int right = scissorsX + w;
            int bottom = scissorsY + h;
            int parentRight = parentInfo.x + parentInfo.width;
            int parentBottom = parentInfo.y + parentInfo.height;

            scissorsX = Math.max(scissorsX, parentInfo.x);
            scissorsY = Math.max(scissorsY, parentInfo.y);

            w = Math.max(0, Math.min(right, parentRight) - scissorsX);
            h = Math.max(0, Math.min(bottom, parentBottom) - scissorsY);
        }

        GL11.glEnable(GL11.GL_SCISSOR_TEST);

        ScissorsInfo info = new ScissorsInfo(scissorsX, scissorsY, w, h);
        scissorsInfoStack.push(info);

        int scale = Screen.getScale();
        GL11.glScissor(info.x * scale, mc.displayHeight - ((info.y + info.height) * scale), info.width * scale, info.height * scale);
    }

    protected synchronized void scissorsEnd()
    {
        scissorsInfoStack.pop();

        GL11.glDisable(GL11.GL_SCISSOR_TEST);

        if (!scissorsInfoStack.isEmpty())
        {
            GL11.glEnable(GL11.GL_SCISSOR_TEST);

            ScissorsInfo info = scissorsInfoStack.peek();
            int scale = Screen.getScale();
            GL11.glScissor(info.x * scale, mc.displayHeight - ((info.y + info.height) * scale), info.width * scale, info.height * scale);
        }

    }
}

 

 

and we call that image class por example.

 

 Image xpBar = new Image();
        xpBar.setImage(GUI_ICONS_LOCATION, XP_BAR_ICON_COLUMN, XP_BAR_EMPTY_ROW, XP_BAR_WIDTH, XP_HEIGHT);
        xpBar.setPosition(LEFT_BORDER_X, LEFT_BORDER_Y);

 

and then draw it.

Link to comment
Share on other sites

drawself is being called from

public final void draw(int mx, int my)

in Pane

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.