Skip to content

Commit

Permalink
Mouse drag support for SerializedScreen, widget distribution
Browse files Browse the repository at this point in the history
Key event support for SerializedScreen, widget distribution, dropping on SlotWidget

Fix accidental removal of translation in ItemContainerWidget

New mouseGuiX, mouseGuiY in RenderGeneral.kt for GUI scaled mouse reading
  • Loading branch information
ATPStorages committed Aug 29, 2024
1 parent ebd8a5c commit a2c8387
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 31 deletions.
9 changes: 1 addition & 8 deletions src/main/kotlin/breadmod/ClientForgeEventBus.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import breadmod.network.PacketHandler.NETWORK
import breadmod.network.serverbound.tool_gun.ToolGunConfigurationPacket
import breadmod.registry.ModConfiguration
import breadmod.util.gui.IHoldScreen
import breadmod.util.render.modifierMatches
import breadmod.util.render.renderBuffer
import breadmod.util.render.rgMinecraft
import com.mojang.blaze3d.platform.InputConstants
Expand Down Expand Up @@ -79,14 +80,6 @@ object ClientForgeEventBus {
)
}


private fun modifierMatches(modifiers: Int, modifier: KeyModifier) = when (modifier) {
KeyModifier.SHIFT -> modifiers and 0x0001
KeyModifier.CONTROL -> modifiers and 0x0002
KeyModifier.ALT -> modifiers and 0x0004
KeyModifier.NONE -> 1
} != 0

private fun handleToolgunInput(
player: LocalPlayer,
itemHeld: ToolGunItem, stackHeld: ItemStack,
Expand Down
57 changes: 56 additions & 1 deletion src/main/kotlin/breadmod/util/gui/SerializedScreen.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package breadmod.util.gui

import breadmod.util.gui.widget.ContainerWidget
import breadmod.util.render.mouseGuiX
import breadmod.util.render.mouseGuiY
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.gui.screens.inventory.MenuAccess
import net.minecraft.network.chat.Component
Expand Down Expand Up @@ -61,7 +63,9 @@ open class SerializedScreen<T : AbstractContainerMenu>(
* @since 1.0.0
*/
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean =
if (rootWidget.isMouseOver(pMouseX, pMouseY)) rootWidget.mouseClicked(pMouseX, pMouseY, pButton) else false
if (!rootWidget.isMouseOver(pMouseX, pMouseY) || !rootWidget.mouseClicked(pMouseX, pMouseY, pButton))
super.mouseClicked(pMouseX, pMouseY, pButton)
else false

/**
* Pushes mouse movement inputs to the provided [rootWidget].
Expand All @@ -73,5 +77,56 @@ open class SerializedScreen<T : AbstractContainerMenu>(
*/
override fun mouseMoved(pMouseX: Double, pMouseY: Double) {
if (rootWidget.isMouseOver(pMouseX, pMouseY)) rootWidget.mouseMoved(pMouseX, pMouseY)
else super.mouseMoved(pMouseX, pMouseY)
}

/**
* Pushes mouse dragging inputs to the provided [rootWidget].
* @param pMouseX The X position of the mouse.
* @param pMouseY The Y position of the mouse.
* @param pButton The button on the mouse that was clicked.
* @param pDragX The X distance of the mouse drag.
* @param pDragY The Y distance of the mouse drag.
* @return Whether the mouse click was handled by the [rootWidget].
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun mouseDragged(pMouseX: Double, pMouseY: Double, pButton: Int, pDragX: Double, pDragY: Double): Boolean =
if (
!rootWidget.isMouseOver(mouseGuiX, mouseGuiY) ||
!rootWidget.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY)
) super.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY)
else false

/**
* Pushes key presses to the provided [rootWidget].
* @param pKeyCode The key code of the key pressed.
* @param pScanCode The scan code of the key pressed.
* @param pModifiers The bit-mapped modifiers of the key pressed.
* @return Whether the key press was handled by the [rootWidget].
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun keyPressed(pKeyCode: Int, pScanCode: Int, pModifiers: Int): Boolean =
if (
!rootWidget.isMouseOver(mouseGuiX, mouseGuiY) ||
!rootWidget.keyPressed(pKeyCode, pScanCode, pModifiers)
) super.keyPressed(pKeyCode, pScanCode, pModifiers)
else false

/**
* Pushes key releases to the provided [rootWidget].
* @param pKeyCode The key code of the key pressed.
* @param pScanCode The scan code of the key pressed.
* @param pModifiers The bit-mapped modifiers of the key pressed.
* @return Whether the key press was handled by the [rootWidget].
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun keyReleased(pKeyCode: Int, pScanCode: Int, pModifiers: Int): Boolean =
if (
!rootWidget.isMouseOver(mouseGuiX, mouseGuiY) ||
!rootWidget.keyReleased(pKeyCode, pScanCode, pModifiers)
) super.keyReleased(pKeyCode, pScanCode, pModifiers)
else false
}
50 changes: 50 additions & 0 deletions src/main/kotlin/breadmod/util/gui/widget/ContainerWidget.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package breadmod.util.gui.widget

import breadmod.util.gui.widget.marker.IWidgetKeySensitive
import breadmod.util.gui.widget.marker.IWidgetMouseClickSensitive
import breadmod.util.gui.widget.marker.IWidgetMouseDragSensitive
import breadmod.util.gui.widget.marker.IWidgetMouseMovementSensitive
import breadmod.util.json
import breadmod.util.render.mouseGuiX
import breadmod.util.render.mouseGuiY
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
Expand Down Expand Up @@ -172,6 +178,50 @@ open class ContainerWidget(
rx?.first?.mouseMoved(rx.second.first, rx.second.second)
}

/**
* Handles a mouse dragging event, distributing the event to [IWidgetMouseClickSensitive] widgets.
* @param pMouseX The X position of the mouse.
* @param pMouseY The Y position of the mouse.
* @param pButton The button on the mouse that was clicked.
* @param pDragX The X distance of the mouse drag.
* @param pDragY The Y distance of the mouse drag.
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun mouseDragged(pMouseX: Double, pMouseY: Double, pButton: Int, pDragX: Double, pDragY: Double): Boolean {
val rx = this.iterateLowHigh(pMouseX, pMouseY, IWidgetMouseDragSensitive::class)
return rx?.first?.mouseDragged(rx.second.first, rx.second.second, pButton, pDragX, pDragY) ?: false
}

private fun getKeyableWidget() =
this.iterateLowHigh(
mouseGuiX,
mouseGuiY,
IWidgetKeySensitive::class
)

/**
* Handles a key press event, distributing the event to [IWidgetMouseClickSensitive] widgets.
* @param pButton The button on the keyboard that was pressed.
* @param pScanCode The scan code of the key that was pressed.
* @param pModifiers The bit-mapped modifiers that were active when the key was pressed.
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun keyPressed(pButton: Int, pScanCode: Int, pModifiers: Int): Boolean =
getKeyableWidget()?.first?.keyPressed(pButton, pScanCode, pModifiers) ?: false

/**
* Handles a key press event, distributing the event to [IWidgetMouseClickSensitive] widgets.
* @param pButton The button on the keyboard that was pressed.
* @param pScanCode The scan code of the key that was pressed.
* @param pModifiers The bit-mapped modifiers that were active when the key was pressed.
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun keyReleased(pButton: Int, pScanCode: Int, pModifiers: Int): Boolean =
getKeyableWidget()?.first?.keyReleased(pButton, pScanCode, pModifiers) ?: false

/**
* Updates the narration output of this [ContainerWidget]. (By default, nothing is added.)
* @param pNarrationElementOutput The narration output to update.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ open class ItemContainerWidget(
if (!it.isEmpty) {
val pose = pGuiGraphics.pose()
pose.pushPose()
pose.translate(0.0f, 0.0f, 232.0f)
val pMx = pMouseX - 8
val pMy = pMouseY - 8
pGuiGraphics.renderItem(it, pMx, pMy)
Expand Down
55 changes: 35 additions & 20 deletions src/main/kotlin/breadmod/util/gui/widget/SlotWidget.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package breadmod.util.gui.widget

import breadmod.util.gui.widget.marker.IWidgetKeySensitive
import breadmod.util.gui.widget.marker.IWidgetMouseClickSensitive
import breadmod.util.gui.widget.marker.IWidgetMouseDragSensitive
import breadmod.util.render.modifierMatches
import breadmod.util.render.rgMinecraft
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.AbstractWidget
import net.minecraft.client.gui.narration.NarratedElementType
Expand All @@ -9,6 +14,7 @@ import net.minecraft.client.renderer.RenderType
import net.minecraft.network.chat.Component
import net.minecraft.world.Container
import net.minecraft.world.inventory.ClickType
import net.minecraftforge.client.settings.KeyModifier
import java.awt.Color

/**
Expand All @@ -24,14 +30,10 @@ class SlotWidget(
pX: Int, pY: Int,
val pParent: ItemContainerWidget,
val slot: Int
) : AbstractWidget(pX, pY, 16, 16, Component.empty()), IWidgetMouseClickSensitive {
) : AbstractWidget(pX, pY, 16, 16, Component.empty()), IWidgetMouseClickSensitive, IWidgetMouseDragSensitive,
IWidgetKeySensitive {
private val hoverColor = Color(1f, 1f, 1f, 0.5f).rgb

/**
* Renders this [SlotWidget].
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun renderWidget(pGuiGraphics: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTick: Float) {
val stack = pParent.pContainer.getItem(slot)
val notEmpty = !stack.isEmpty
Expand All @@ -49,15 +51,6 @@ class SlotWidget(
}
}

/**
* Handles mouse clicks on this [SlotWidget].
* @param pMouseX The X position of the mouse.
* @param pMouseY The Y position of the mouse.
* @param pButton The button on the mouse that was clicked.
* @return Whether the click was handled by this widget and should be consumed.
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
rgMinecraft.gameMode?.let {
val player = rgMinecraft.player ?: return false
Expand All @@ -66,11 +59,33 @@ class SlotWidget(
return true
}

/**
* Updates the narration output of this [SlotWidget].
* @author Miko Elbrecht
* @since 1.0.0
*/
override fun mouseDragged(pMouseX: Double, pMouseY: Double, pButton: Int, pDragX: Double, pDragY: Double): Boolean {
return if (!pParent.pContainerMenu.carried.isEmpty) {
rgMinecraft.gameMode?.let {
// TODO drag logic
}
true
} else false
}

override fun keyPressed(pKeyCode: Int, pScanCode: Int, pModifiers: Int): Boolean {
val stack = pParent.pContainer.getItem(slot)
return if (!stack.isEmpty) {
val key = InputConstants.getKey(pKeyCode, pScanCode)
if (rgMinecraft.options.keyDrop.isActiveAndMatches(key)) {
rgMinecraft.gameMode?.let {
val player = rgMinecraft.player ?: return false
it.handleInventoryMouseClick(
pParent.pContainerMenu.containerId, slot,
if (modifierMatches(pModifiers, KeyModifier.CONTROL)) 1 else 0,
ClickType.THROW, player
)
}
true
} else false
} else false
}

override fun updateWidgetNarration(pNarrationElementOutput: NarrationElementOutput) {
val stack = pParent.pContainer.getItem(slot)
pNarrationElementOutput.add(NarratedElementType.HINT, stack.hoverName)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package breadmod.util.gui.widget.marker

/**
* A marker interface for widgets that are sensitive to key presses and releases.
* @author Miko Elbrecht
* @since 1.0.0
*/
interface IWidgetKeySensitive
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package breadmod.util.gui.widget
package breadmod.util.gui.widget.marker

/**
* A marker interface for widgets that are sensitive to mouse click events.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package breadmod.util.gui.widget.marker

/**
* A marker interface for widgets that are sensitive to mouse dragging.
* @author Miko Elbrecht
* @since 1.0.0
*/
interface IWidgetMouseDragSensitive
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package breadmod.util.gui.widget
package breadmod.util.gui.widget.marker

/**
* A marker interface for widgets that are sensitive to mouse movement.
Expand Down
15 changes: 15 additions & 0 deletions src/main/kotlin/breadmod/util/render/RenderGeneral.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import net.minecraft.world.level.material.Fluid
import net.minecraftforge.client.RenderTypeHelper
import net.minecraftforge.client.event.RenderLevelStageEvent
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions
import net.minecraftforge.client.settings.KeyModifier
import org.jetbrains.annotations.ApiStatus.Internal
import org.joml.*
import java.awt.Color
Expand All @@ -50,6 +51,20 @@ internal typealias RenderBuffer = MutableList<Pair<MutableList<Float>, (MutableL
internal val shaderPreCompilation =
mutableMapOf<String, (Program.Type, String, InputStream, String, GlslPreprocessor) -> Unit>()

val mouseGuiX: Double
get() = rgMinecraft.mouseHandler.xpos() * rgMinecraft.window.guiScaledWidth.toDouble() /
rgMinecraft.window.screenWidth.toDouble()
val mouseGuiY: Double
get() = rgMinecraft.mouseHandler.ypos() * rgMinecraft.window.guiScaledHeight.toDouble() /
rgMinecraft.window.screenHeight.toDouble()

fun modifierMatches(modifiers: Int, modifier: KeyModifier) = when (modifier) {
KeyModifier.SHIFT -> modifiers and 0x0001
KeyModifier.CONTROL -> modifiers and 0x0002
KeyModifier.ALT -> modifiers and 0x0004
KeyModifier.NONE -> 1
} != 0

/**
* A list of lambdas to call for rendering. If lambdas return true, they will be removed.
* @see breadmod.ClientForgeEventBus.onLevelRender
Expand Down

0 comments on commit a2c8387

Please sign in to comment.