Jump to content

Overlapping buttons and setting isHovered in a Screen


Spacejet

Recommended Posts

So, generally I have been using 

this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width
				&& mouseY < this.y + this.height;

for setting any of my custom buttons' hover status, but I noticed this won't really work if I have overlapping buttons. In my specific case, this is the issue:

Spoiler

image.png.d88e2ef2c16ec243a1406f0949de2698.png

As you can see, the white keys extend under the black keys, meaning that the aforementioned method of setting a button's isHovered variable would not work, as it would return true for the first key (C) even if its the corresponding black key (C#) that is hovered, as long as it is within the width of the first key

Spoiler

image.png.3f94af2d668f81c2152e62c88096ecf0.png

The green is the area that would return true using the method I mentioned above for the white key, and red for the black, but the blue area esults in both the white and black keys getting their isHovered variable set to true, while the desired behaviour is to only have the black key's isHovered value to be true, and the white key's false.

 

While I know I can use 2 different checks to check the white key in this manner, green first check and yellow second:

Spoiler

image.png.cc10a840444b7960171d8dc9b99c6cce.png

I was wondering if there is a better method to do this, without having to hardcode the checks for every single key, as all have different indentations regarding black keys.

 

Thanks for taking the time to read this, and I am looking forward to see what you guys suggest.

Link to comment
Share on other sites

One option would be to have it check if any black keys are hovered first, and if so, completely skip the check for white keys. You'd probably have to restructure the way you're performing checks whenever the user clicks, but it's certainly doable.

I'm eager to learn and am prone to mistakes. Don't hesitate to tell me how I can improve.

Link to comment
Share on other sites

18 minutes ago, imacatlolol said:

One option would be to have it check if any black keys are hovered first, and if so, completely skip the check for white keys. You'd probably have to restructure the way you're performing checks whenever the user clicks, but it's certainly doable.

It's a nice idea, but how would I go about doing it? The white key in which I would need to check if a black key is being hovered does not have access to the black key, so I can't do that

 

For reference: Button class

Spoiler

package com.spacejet.more_music.client.gui.widget.button;

import com.spacejet.more_music.Main;

import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.client.gui.GuiUtils;
import net.minecraftforge.fml.client.gui.widget.ExtendedButton;

public class PinaoKeyButton extends ExtendedButton
{
	private static final ResourceLocation KEY_TEXTURES = new ResourceLocation(Main.MOD_ID, "textures/gui/keys.png");

	private int type;

	/**
	 * 
	 * @param xPos    : x position of the button
	 * @param yPos    : y position of the button
	 * @param width   : width of the button
	 * @param height  : height of the button
	 * @param type    : determines what key it is supposed to be, so the texture can
	 *                be drawn correctly of a black key
	 * @param handler
	 */
	public PinaoKeyButton(int xPos, int yPos, int width, int height, int type, IPressable handler)
	{
		super(xPos, yPos, width, height, "", handler);
		this.type = type;
	}

	@Override
	public void renderButton(int mouseX, int mouseY, float partial)
	{
		Minecraft mc = Minecraft.getInstance();
//		setHoverStatus(mouseX, mouseY);
		this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width
				&& mouseY < this.y + this.height;
		drawTexture();
		this.renderBg(mc, mouseX, mouseY);
	}

	private void drawTexture()
	{
		int yOffset = 0;

		if (this.isHovered)
			yOffset = 51;

		switch (type)
		{
			case 1:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 0, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 2:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 15, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 3:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 30, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 4:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 45, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 5:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 60, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 6:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 75, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 7:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 90, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset());
				break;
			case 8:
				GuiUtils.drawContinuousTexturedBox(KEY_TEXTURES, this.x, this.y, 105, yOffset, this.width, this.height,
						this.width, this.height, 2, 3, 2, 2, this.getBlitOffset() + 2);
				break;
		}
	}
}

 

Screen class:

Spoiler

package com.spacejet.more_music.client.gui;

import com.mojang.blaze3d.systems.RenderSystem;
import com.spacejet.more_music.Main;
import com.spacejet.more_music.client.gui.widget.button.PinaoKeyButton;
import com.spacejet.more_music.container.AdvancedNoteBlockContainer;

import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class AdvancedNoteBlockScreen extends ContainerScreen<AdvancedNoteBlockContainer>
{
	private static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation(Main.MOD_ID,
			"textures/gui/container/advanced_note_block.png");

	public AdvancedNoteBlockScreen(AdvancedNoteBlockContainer screenContainer, PlayerInventory inv,
			ITextComponent titleIn)
	{
		super(screenContainer, inv, titleIn);
		this.guiLeft = 0;
		this.guiTop = 0;
		this.xSize = 175;
		this.ySize = 179;
	}

	@Override
	public void render(final int mouseX, final int mouseY, final float partialTicks)
	{
		this.renderBackground();
		super.render(mouseX, mouseY, partialTicks);
		this.renderHoveredToolTip(mouseX, mouseY);
	}

	@Override
	protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
	{
		super.drawGuiContainerForegroundLayer(mouseX, mouseY);
		this.font.drawString(this.title.getFormattedText(), 8.0f, 6.0f, 4210752);
		this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8.0F,
				(float) (this.ySize - 96 + 2), 4210752);
	}

	@Override
	protected void init()
	{
		int x = this.width / 2 - this.xSize / 2;
		int y = this.height / 2 - this.ySize / 2;

		// The flags are 1:C, 2:D, 3:E... (8:any accidental note)
		this.addButton(new PinaoKeyButton(x + 20, y + 18, 8, 34, 8, $ -> {System.out.println("C#");})); // The key of C#/Db
		this.addButton(new PinaoKeyButton(x + 36, y + 18, 8, 34, 8, $ -> {System.out.println("D#");})); // The key of D#/Eb
		this.addButton(new PinaoKeyButton(x + 61, y + 18, 8, 34, 8, $ -> {System.out.println("F#");})); // The key of F#/Gb
		this.addButton(new PinaoKeyButton(x + 77, y + 18, 8, 34, 8, $ -> {System.out.println("G#");})); // The key of G#/Ab
		this.addButton(new PinaoKeyButton(x + 93, y + 18, 8, 34, 8, $ -> {System.out.println("A#");})); // The key of A#/Bb
		this.addButton(new PinaoKeyButton(x + 11, y + 18, 14, 50, 1, $ -> {System.out.println("C");})); // The key of C
		this.addButton(new PinaoKeyButton(x + 25, y + 18, 14, 50, 2, $ -> {System.out.println("D");})); // The key of D
		this.addButton(new PinaoKeyButton(x + 39, y + 18, 14, 50, 3, $ -> {System.out.println("E");})); // The key of E
		this.addButton(new PinaoKeyButton(x + 53, y + 18, 14, 50, 4, $ -> {System.out.println("F");})); // The key of F
		this.addButton(new PinaoKeyButton(x + 67, y + 18, 14, 50, 5, $ -> {System.out.println("G");})); // The key of G
		this.addButton(new PinaoKeyButton(x + 81, y + 18, 14, 50, 6, $ -> {System.out.println("A");})); // The key of A
		this.addButton(new PinaoKeyButton(x + 95, y + 18, 14, 50, 7, $ -> {System.out.println("B");})); // The key of B

		super.init();
	}
	
	@Override
	public boolean isPauseScreen()
	{
		return false; // Don't pause the game when this screen is open
	}

	@Override
	protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
	{
		RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
		this.minecraft.getTextureManager().bindTexture(BACKGROUND_TEXTURE);

		int startX = (this.width - this.xSize) / 2;
		int startY = (this.height - this.ySize) / 2;

		// Screen#blit draws a part of the current texture (assumed to be 256x256) to
		// the screen
		// The parameters are (x, y, u, v, width, height)

		this.blit(startX, startY, 0, 0, this.xSize, this.ySize);
	}

}

 

 

Link to comment
Share on other sites

Well there's a few options, but here's my initial idea. You could make a couple methods for adding black or white keys respectively and then have those methods call addButton and also place the keys in separate lists. Then, you could override the mouseClicked function of your screen and have it first iterate through the black keys and check the result of their mouseClicked function, then the white keys, and then fall back to the default behavior.

I'm eager to learn and am prone to mistakes. Don't hesitate to tell me how I can improve.

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.