Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Overlapping buttons and setting isHovered in a Screen


Spacejet
 Share

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
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.

 Share



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • Thank you both for the replies. This makes sense. I thought that i may be able to create something server side. I have seen servers that provide new items with the client only needing the resource pack. I mistakenly thought that this was achieved this way. I will keep looking for how this is implemented. There are no errors, for all intensive purposes things are working as expected. It was as if the client did not have the context of the namespace.
    • Is there any error/warning in the console telling something went wrong when trying to load the model? Or reload resources in game (F3 + T) and it will show errors again if there are any.
    • Custom items require the client to have forge and your mod installed.
    • Hi, This is my first foray into Forge and i am confident I am making a silly mistake somewhere, any advice would be appreciated. Objective Have a custom mod; mymod Have a custom item with a custom texture; mymod_item Provision resource pack for lang, model and texture assets for mymod_item Run a dedicated Forge server with the mod installed and requiring the resource pack Expected behaviour Player connects to dedicated server and downloads asset pack Player is given custom item /give @p mymod.mymod_item Player inventory to display item with custom texture and to be visible when dropped Actual behavior When running a Forge client from the IDE tasks, the textures load for singleplayer (via local Forge mod deployment) When running a Forge client from the IDE tasks, the textures load for multiplayer games (via asset pack) When running a vanilla client in singleplayer mode, as expected it does not work as it has no concept of my entities. When running a vanilla client in multiplayer mode, the asset pack is downloaded and an invisible item is granted (I have some logging on the item so that i know I "have" it) Noteworth When giving the item to the player on the vanilla client, the name is displayed correctly implying that the lang/en_us.json is being loaded correctly. My asset pack also overrides the minecraft:item/gold_ingot texture with the exact same one used for mymod:mymod_item and this is loaded fine as a replacement. Asset pack tree assets/minecraft/textures/item/gold_ingot.png assets/mymod/textures/item/mymod_item.png assets/mymod/models/item/mymod_item.json assets/mymod/lang/en_us.json pack.mcmeta   Summary I suspect that i am doing something that i am not supposed to but unfortunately its not jumping out to me quite what that may be! One of the pieces i am struggling to understand is what ties the mymod_item class to the resources? In my code i do net set any explicit ResourceLocations for it, should I be? Thanks
    • This is a terrible idea... And inferior to the actual solution (separate game directories) in every way. There is a good reason why Forge does not do this anymore. If you really want to, you can provide your own IModLocator implementation, which allows you to plug into FMLs mod loading process and provide additional mods to load. It is discovered via the standard Java service loader, see the ModDiscoverer class. The config system is irrelevant here, as this happens before mods are even loaded.
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.