aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThunderblade73 <85900443+Thunderblade73@users.noreply.github.com>2024-06-23 20:18:45 +0200
committerGitHub <noreply@github.com>2024-06-23 20:18:45 +0200
commit739a48d4679ce05c1f555a04fcdaa4e509d59d5d (patch)
treeb7b21a3548f441db11262f1e90267c9ec4666696
parent6eb085f4e2ba69e98934ffa9489c8679ba23d244 (diff)
downloadskyhanni-739a48d4679ce05c1f555a04fcdaa4e509d59d5d.tar.gz
skyhanni-739a48d4679ce05c1f555a04fcdaa4e509d59d5d.tar.bz2
skyhanni-739a48d4679ce05c1f555a04fcdaa4e509d59d5d.zip
Backend: Drag and Drop for Renderables (#1864)
Co-authored-by: Cal <cwolfson58@gmail.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/GuiContainerEvent.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt47
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/DragNDrop.kt106
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt7
8 files changed, 181 insertions, 7 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/events/GuiContainerEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/GuiContainerEvent.kt
index 9837e1529..34bc2a2a5 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/GuiContainerEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/GuiContainerEvent.kt
@@ -19,7 +19,7 @@ abstract class GuiContainerEvent(open val gui: GuiContainer, open val container:
) : GuiContainerEvent(gui, container)
@Cancelable
- data class BeforeDraw(
+ data class PreDraw(
override val gui: GuiContainer,
override val container: Container,
val mouseX: Int,
@@ -30,6 +30,14 @@ abstract class GuiContainerEvent(open val gui: GuiContainer, open val container:
GuiRenderUtils.drawGradientRect(0, 0, gui.width, gui.height, -1072689136, -804253680, 0.0)
}
+ data class PostDraw(
+ override val gui: GuiContainer,
+ override val container: Container,
+ val mouseX: Int,
+ val mouseY: Int,
+ val partialTicks: Float,
+ ) : GuiContainerEvent(gui, container)
+
@Cancelable
data class CloseWindowEvent(override val gui: GuiContainer, override val container: Container) :
GuiContainerEvent(gui, container)
@@ -78,7 +86,7 @@ abstract class GuiContainerEvent(open val gui: GuiContainer, open val container:
if (this.clickedButton == 2 && this.clickTypeEnum == ClickType.MIDDLE) return
slot?.slotNumber?.let { slotNumber ->
Minecraft.getMinecraft().playerController.windowClick(
- container.windowId, slotNumber, 2, 3, Minecraft.getMinecraft().thePlayer
+ container.windowId, slotNumber, 2, 3, Minecraft.getMinecraft().thePlayer,
)
isCanceled = true
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt
index 1c3f36aeb..08abfa34d 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt
@@ -58,7 +58,7 @@ object CustomWardrobe {
private var guiName = "Custom Wardrobe"
@SubscribeEvent
- fun onGuiRender(event: GuiContainerEvent.BeforeDraw) {
+ fun onGuiRender(event: GuiContainerEvent.PreDraw) {
if (!isEnabled() || editMode) return
val renderable = displayRenderable ?: run {
update()
diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt
index 041457d25..552b16f00 100644
--- a/src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt
+++ b/src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt
@@ -36,7 +36,7 @@ class GuiContainerHook(guiAny: Any) {
ci: CallbackInfo,
) {
if (!SkyHanniDebugsAndTests.globalRender) return
- if (GuiContainerEvent.BeforeDraw(gui, gui.inventorySlots, mouseX, mouseY, partialTicks).postAndCatch()) {
+ if (GuiContainerEvent.PreDraw(gui, gui.inventorySlots, mouseX, mouseY, partialTicks).postAndCatch()) {
NEUApi.setInventoryButtonsToDisabled()
GuiData.preDrawEventCancelled = true
ci.cancel()
@@ -47,6 +47,11 @@ class GuiContainerHook(guiAny: Any) {
}
}
+ fun postDraw(mouseX: Int, mouseY: Int, partialTicks: Float) {
+ if (!SkyHanniDebugsAndTests.globalRender) return
+ GuiContainerEvent.PostDraw(gui, gui.inventorySlots, mouseX, mouseY, partialTicks).postAndCatch()
+ }
+
fun foregroundDrawn(mouseX: Int, mouseY: Int, partialTicks: Float) {
GuiContainerEvent.ForegroundDrawnEvent(gui, gui.inventorySlots, mouseX, mouseY, partialTicks).postAndCatch()
}
diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java
index c92f2ab7c..acec9ffac 100644
--- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java
+++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/MixinGuiContainer.java
@@ -36,6 +36,11 @@ public abstract class MixinGuiContainer extends GuiScreen {
skyHanni$hook.preDraw(mouseX, mouseY, partialTicks, ci);
}
+ @Inject(method = "drawScreen", at = @At("TAIL"))
+ private void postDraw(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
+ skyHanni$hook.postDraw(mouseX, mouseY, partialTicks);
+ }
+
@Inject(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/inventory/GuiContainer;drawGuiContainerForegroundLayer(II)V", shift = At.Shift.AFTER))
private void onForegroundDraw(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
skyHanni$hook.foregroundDrawn(mouseX, mouseY, partialTicks);
diff --git a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt
index f3fe16222..e718593f3 100644
--- a/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt
+++ b/src/main/java/at/hannibal2/skyhanni/test/SkyHanniDebugsAndTests.kt
@@ -56,8 +56,11 @@ import at.hannibal2.skyhanni.utils.RenderUtils.renderString
import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
import at.hannibal2.skyhanni.utils.SimpleTimeMark
import at.hannibal2.skyhanni.utils.SoundUtils
+import at.hannibal2.skyhanni.utils.renderables.DragNDrop
+import at.hannibal2.skyhanni.utils.renderables.Droppable
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.Renderable.Companion.renderBounds
+import at.hannibal2.skyhanni.utils.renderables.toDragItem
import kotlinx.coroutines.launch
import net.minecraft.client.Minecraft
import net.minecraft.init.Blocks
@@ -202,7 +205,7 @@ object SkyHanniDebugsAndTests {
onClick = { resetConfig() },
"§eClick to confirm.",
prefix = false,
- oneTimeClick = true
+ oneTimeClick = true,
)
}
@@ -535,6 +538,45 @@ object SkyHanniDebugsAndTests {
config.debugPos.renderStringsAndItems(displayList, posLabel = "Test Display")
}
+ @SubscribeEvent
+ fun onGuiRenderChestGuiOverlayRender(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
+ @Suppress("ConstantConditionIf")
+ if (false) {
+ dragAbleTest()
+ }
+ }
+
+ private fun dragAbleTest() {
+ val bone = ItemStack(Items.bone, 1).toDragItem()
+ val leaf = ItemStack(Blocks.leaves, 1).toDragItem()
+
+ config.debugItemPos.renderRenderables(
+ listOf(
+ DragNDrop.draggable(Renderable.string("A Bone"), { bone }),
+ Renderable.placeholder(0, 30),
+ DragNDrop.draggable(Renderable.string("A Leaf"), { leaf }),
+ Renderable.placeholder(0, 30),
+ DragNDrop.droppable(
+ Renderable.string("Feed Dog"),
+ object : Droppable {
+ override fun handle(drop: Any?) {
+ val unit = drop as ItemStack
+ if (unit.item == Items.bone) {
+ LorenzDebug.chatAndLog("Oh, a bone!")
+ } else {
+ LorenzDebug.chatAndLog("Disgusting that is not a bone!")
+ }
+ }
+
+ override fun validTarget(item: Any?) = item is ItemStack
+
+ },
+ ),
+ ),
+ posLabel = "Item Debug",
+ )
+ }
+
private fun itemRenderDebug() {
val scale = 0.1
val renderables = listOf(
@@ -547,7 +589,8 @@ object SkyHanniDebugsAndTests {
}.editCopy {
this.add(
0,
- generateSequence(scale) { it + 0.1 }.take(25).map { Renderable.string(it.round(1).toString()) }.toList(),
+ generateSequence(scale) { it + 0.1 }.take(25).map { Renderable.string(it.round(1).toString()) }
+ .toList(),
)
}
config.debugItemPos.renderRenderables(
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/DragNDrop.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/DragNDrop.kt
new file mode 100644
index 000000000..70cab119e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/DragNDrop.kt
@@ -0,0 +1,106 @@
+package at.hannibal2.skyhanni.utils.renderables
+
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraft.init.Blocks
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object DragNDrop {
+
+ private var currentDrag: DragItem<*>? = null
+
+ private var isInvalidDrop = false
+
+ private const val BUTTON = 0
+
+ private const val BUTTON_MAPPED = BUTTON - 100
+
+ private val invalidItem = Renderable.itemStack(ItemStack(Blocks.barrier), 1.0)
+
+ @SubscribeEvent
+ fun onGuiContainerBeforeDraw(event: GuiContainerEvent.PreDraw) {
+ isInvalidDrop = false
+ }
+
+ @SubscribeEvent
+ fun onGuiContainerAfterDraw(event: GuiContainerEvent.PostDraw) {
+ val item = currentDrag ?: return
+ if (!BUTTON_MAPPED.isKeyHeld()) {
+ currentDrag = null
+ return
+ }
+ GlStateManager.translate(event.mouseX.toFloat(), event.mouseY.toFloat(), 0f)
+ if (isInvalidDrop) {
+ invalidItem.render(event.mouseX, event.mouseY)
+ } else {
+ item.onRender(event.mouseX, event.mouseY)
+ }
+ GlStateManager.translate(-event.mouseX.toFloat(), -event.mouseY.toFloat(), 0f)
+ }
+
+ fun draggable(
+ display: Renderable,
+ item: () -> DragItem<*>,
+ bypassChecks: Boolean = false,
+ condition: () -> Boolean = { true },
+ ) = Renderable.clickable(
+ display,
+ onClick = { currentDrag = item() },
+ button = BUTTON,
+ bypassChecks = bypassChecks,
+ condition = condition,
+ )
+
+ fun droppable(
+ display: Renderable,
+ drop: Droppable,
+ bypassChecks: Boolean = false,
+ condition: () -> Boolean = { true },
+ ): Renderable = object : RenderableWrapper(display) {
+ override fun render(posX: Int, posY: Int) {
+ if (isHovered(posX, posY) && condition() && Renderable.shouldAllowLink(true, bypassChecks)) {
+ handelDroppable(drop)
+ }
+ content.render(posX, posY)
+ }
+ }
+
+ private fun handelDroppable(drop: Droppable) {
+ val item = currentDrag ?: return
+ if (drop.validTarget(item.get())) {
+ if (!BUTTON_MAPPED.isKeyHeld()) {
+ drop.handle(item.get())
+ currentDrag = null
+ }
+ } else {
+ isInvalidDrop = true
+ }
+
+ }
+}
+
+fun ItemStack.toDragItem(scale: Double = 1.0) = object : DragItem<ItemStack> {
+
+ val render = Renderable.itemStack(this@toDragItem, scale, 0)
+
+ override fun get(): ItemStack = this@toDragItem
+
+ override fun onRender(mouseX: Int, mouseY: Int) = render.render(mouseX, mouseY)
+}
+
+interface DragItem<T> {
+
+ fun get(): T
+ fun onRender(mouseX: Int, mouseY: Int)
+
+}
+
+interface Droppable {
+
+ fun handle(drop: Any?)
+ fun validTarget(item: Any?): Boolean
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
index f00cba6c5..0ed562152 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
@@ -233,7 +233,7 @@ interface Renderable {
}
}
- private fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean {
+ internal fun shouldAllowLink(debug: Boolean = false, bypassChecks: Boolean): Boolean {
val guiScreen = Minecraft.getMinecraft().currentScreen
val isGuiScreen = guiScreen != null
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt
index d1a8aae02..a78044d72 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt
@@ -73,3 +73,10 @@ internal object RenderableUtils {
return yOffset
}
}
+
+internal abstract class RenderableWrapper internal constructor(protected val content: Renderable) : Renderable {
+ override val width = content.width
+ override val height = content.height
+ override val horizontalAlign = content.horizontalAlign
+ override val verticalAlign = content.verticalAlign
+}