Track visible children separately

Fixes #201
This commit is contained in:
DBotThePony 2022-10-26 18:27:35 +07:00
parent a7b09441c5
commit 44da2c4b11
Signed by: DBot
GPG Key ID: DCC23B5715498507
2 changed files with 122 additions and 105 deletions

View File

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import it.unimi.dsi.fastutil.objects.ObjectArraySet import it.unimi.dsi.fastutil.objects.ObjectArraySet
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
import net.minecraft.client.gui.Font import net.minecraft.client.gui.Font
import net.minecraft.client.gui.components.events.GuiEventListener import net.minecraft.client.gui.components.events.GuiEventListener
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
@ -74,7 +75,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (field === value) if (field === value)
return return
val set = ObjectArraySet<EditablePanel<*>>() val set = ReferenceArraySet<EditablePanel<*>>()
set.add(this) set.add(this)
var parent = value var parent = value
@ -169,7 +170,8 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
var dockedHeight: Float = 0f var dockedHeight: Float = 0f
private set private set
protected val children = ArrayList<EditablePanel<*>>() private val children = ArrayList<EditablePanel<*>>()
private val visibleChildren = ArrayList<EditablePanel<*>>()
val childrenView: List<EditablePanel<*>> = Collections.unmodifiableList(children) val childrenView: List<EditablePanel<*>> = Collections.unmodifiableList(children)
var layoutInvalidated = true var layoutInvalidated = true
@ -189,15 +191,24 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (old != new) { if (old != new) {
visibilityChanges(new, old) visibilityChanges(new, old)
parent?.layoutInvalidated = true val visibleChildrenParent = parent?.visibleChildren
layoutInvalidated = true
if (new) { if (new) {
killFocus() killFocus()
}
}
updateVisible() if (visibleChildrenParent?.contains(this) == false) {
visibleChildrenParent.add(this)
parent?.layoutInvalidated = true
}
} else {
if (visibleChildrenParent?.contains(this) == true) {
visibleChildrenParent.remove(this)
parent?.layoutInvalidated = true
}
}
updateVisible()
}
} }
} }
@ -506,8 +517,8 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
result.add(Rect2f(absoluteX, absoluteY, width, height)) result.add(Rect2f(absoluteX, absoluteY, width, height))
} }
for (children in children) { for (children in visibleChildren) {
if ((children.isOutsideOfParent || !isObstructing) && children.isVisible()) { if (children.isOutsideOfParent || !isObstructing) {
result.addAll(children.calculateAbsoluteObstructingRectangles()) result.addAll(children.calculateAbsoluteObstructingRectangles())
} }
} }
@ -585,16 +596,30 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
private fun onParent(child: EditablePanel<*>) { private fun onParent(child: EditablePanel<*>) {
if (children.contains(child)) throw IllegalStateException("Already containing $child") if (children.contains(child)) throw IllegalStateException("Already containing $child")
children.add(child) children.add(child)
layoutInvalidated = true
updateVisible() if (child.visible) {
visibleChildren.add(child)
layoutInvalidated = true
}
if (child.isVisible() != isVisible()) {
updateVisible()
}
} }
private fun onUnParent(child: EditablePanel<*>) { private fun onUnParent(child: EditablePanel<*>) {
val indexOf = children.indexOf(child) val indexOf = children.indexOf(child)
if (indexOf == -1) throw IllegalStateException("Already not containing $child") if (indexOf == -1) throw IllegalStateException("Already not containing $child")
children.removeAt(indexOf) children.removeAt(indexOf)
layoutInvalidated = true
updateVisible() if (child.visible) {
visibleChildren.remove(child)
layoutInvalidated = true
}
if (child.isVisible() != isVisible()) {
updateVisible()
}
} }
protected open fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {} protected open fun innerRender(stack: PoseStack, mouseX: Float, mouseY: Float, partialTick: Float) {}
@ -634,13 +659,11 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
absoluteY = y absoluteY = y
} }
for (child in children) { for (child in visibleChildren) {
if (child.isVisible()) { child.absoluteX = absoluteX + child.x + xOffset
child.absoluteX = absoluteX + child.x + xOffset child.absoluteY = absoluteY + child.y + yOffset
child.absoluteY = absoluteY + child.y + yOffset
child.updateAbsoluteCoordinates() child.updateAbsoluteCoordinates()
}
} }
} }
@ -696,13 +719,11 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
poseStack.popPose() poseStack.popPose()
} }
for (child in children) { for (child in visibleChildren) {
if (child.isVisible()) { child.absoluteX = absoluteX + child.x + xOffset
child.absoluteX = absoluteX + child.x + xOffset child.absoluteY = absoluteY + child.y + yOffset
child.absoluteY = absoluteY + child.y + yOffset
child.render(poseStack, mouseX, mouseY, partialTick) child.render(poseStack, mouseX, mouseY, partialTick)
}
} }
if (scissor) { if (scissor) {
@ -757,7 +778,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
return true to this.slot return true to this.slot
} }
for (child in children) { for (child in visibleChildren) {
val (status, slot) = child.findSlot(mouseX, mouseY) val (status, slot) = child.findSlot(mouseX, mouseY)
if (status) { if (status) {
@ -797,7 +818,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
return true to this.itemStack return true to this.itemStack
} }
for (child in children) { for (child in visibleChildren) {
val (status, itemStack) = child.findItemStack(mouseX, mouseY, ignoreMouseInputLock) val (status, itemStack) = child.findItemStack(mouseX, mouseY, ignoreMouseInputLock)
if (status) { if (status) {
@ -832,8 +853,8 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
return false return false
} }
for (child in children) { for (child in visibleChildren) {
if (child.isVisible() && child.renderTooltips(stack, mouseX, mouseY, partialTick)) { if (child.renderTooltips(stack, mouseX, mouseY, partialTick)) {
return true return true
} }
} }
@ -929,73 +950,71 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
var top = dockPadding.top var top = dockPadding.top
var bottom = dockPadding.bottom var bottom = dockPadding.bottom
for (child in children) { for (child in visibleChildren) {
if (child.isVisible()) { when (child.dock) {
when (child.dock) { Dock.NONE -> {}
Dock.NONE -> {} Dock.FILL -> {}
Dock.FILL -> {}
Dock.LEFT -> { Dock.LEFT -> {
child.x = left + child.dockMargin.left child.x = left + child.dockMargin.left
child.y = top + child.dockMargin.top child.y = top + child.dockMargin.top
left += child.width + child.dockMargin.left + child.dockMargin.right left += child.width + child.dockMargin.left + child.dockMargin.right
child.dockedHeight = 1f.coerceAtLeast(height - top - bottom - child.dockMargin.top - child.dockMargin.bottom) child.dockedHeight = 1f.coerceAtLeast(height - top - bottom - child.dockMargin.top - child.dockMargin.bottom)
if (child.dockResize.changeHeight) if (child.dockResize.changeHeight)
child.height = child.dockedHeight child.height = child.dockedHeight
else if (child.height != child.dockedHeight) else if (child.height != child.dockedHeight)
child.y += child.dockedHeight / 2f - child.height / 2f child.y += child.dockedHeight / 2f - child.height / 2f
} }
Dock.RIGHT -> { Dock.RIGHT -> {
child.x = width - right - child.width - child.dockMargin.right child.x = width - right - child.width - child.dockMargin.right
child.y = top + child.dockMargin.top child.y = top + child.dockMargin.top
right += child.width + child.dockMargin.left + child.dockMargin.right right += child.width + child.dockMargin.left + child.dockMargin.right
child.dockedHeight = 1f.coerceAtLeast(height - top - bottom - child.dockMargin.top - child.dockMargin.bottom) child.dockedHeight = 1f.coerceAtLeast(height - top - bottom - child.dockMargin.top - child.dockMargin.bottom)
if (child.dockResize.changeHeight) if (child.dockResize.changeHeight)
child.height = child.dockedHeight child.height = child.dockedHeight
else if (child.height != child.dockedHeight) else if (child.height != child.dockedHeight)
child.y += child.dockedHeight / 2f - child.height / 2f child.y += child.dockedHeight / 2f - child.height / 2f
} }
Dock.TOP -> { Dock.TOP -> {
child.x = left + child.dockMargin.left child.x = left + child.dockMargin.left
child.y = top + child.dockMargin.top child.y = top + child.dockMargin.top
top += child.height + child.dockMargin.top + child.dockMargin.bottom top += child.height + child.dockMargin.top + child.dockMargin.bottom
child.dockedWidth = 1f.coerceAtLeast(width - left - right - child.dockMargin.left - child.dockMargin.right) child.dockedWidth = 1f.coerceAtLeast(width - left - right - child.dockMargin.left - child.dockMargin.right)
if (child.dockResize.changeWidth) if (child.dockResize.changeWidth)
child.width = child.dockedWidth child.width = child.dockedWidth
else if (child.width != child.dockedWidth) else if (child.width != child.dockedWidth)
child.x += child.dockedWidth / 2f - child.width / 2f child.x += child.dockedWidth / 2f - child.width / 2f
} }
Dock.BOTTOM -> { Dock.BOTTOM -> {
child.x = left + child.dockMargin.left child.x = left + child.dockMargin.left
child.y = height - bottom - child.height - child.dockMargin.bottom child.y = height - bottom - child.height - child.dockMargin.bottom
bottom += child.height + child.dockMargin.top + child.dockMargin.bottom bottom += child.height + child.dockMargin.top + child.dockMargin.bottom
child.dockedWidth = 1f.coerceAtLeast(width - left - right - child.dockMargin.left - child.dockMargin.right) child.dockedWidth = 1f.coerceAtLeast(width - left - right - child.dockMargin.left - child.dockMargin.right)
if (child.dockResize.changeWidth) if (child.dockResize.changeWidth)
child.width = child.dockedWidth child.width = child.dockedWidth
else if (child.width != child.dockedWidth) else if (child.width != child.dockedWidth)
child.x += child.dockedWidth / 2f - child.width / 2f child.x += child.dockedWidth / 2f - child.width / 2f
}
} }
} }
} }
for (child in children) { for (child in visibleChildren) {
if (child.isVisible() && child.dock == Dock.FILL) { if (child.dock == Dock.FILL) {
val w = width - child.dockMargin.left - child.dockMargin.right - right - left val w = width - child.dockMargin.left - child.dockMargin.right - right - left
val h = height - child.dockMargin.bottom - child.dockMargin.top - bottom - top val h = height - child.dockMargin.bottom - child.dockMargin.top - bottom - top
@ -1032,13 +1051,11 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
childrenRectWidth = 0f childrenRectWidth = 0f
childrenRectHeight = 0f childrenRectHeight = 0f
for (child in children) { for (child in visibleChildren) {
if (child.isVisible()) { childrenRectX = childrenRectX.coerceAtMost(child.x)
childrenRectX = childrenRectX.coerceAtMost(child.x) childrenRectY = childrenRectY.coerceAtMost(child.y)
childrenRectY = childrenRectY.coerceAtMost(child.y) childrenRectWidth = childrenRectWidth.coerceAtLeast(child.x + child.width)
childrenRectWidth = childrenRectWidth.coerceAtLeast(child.x + child.width) childrenRectHeight = childrenRectHeight.coerceAtLeast(child.y + child.height)
childrenRectHeight = childrenRectHeight.coerceAtLeast(child.y + child.height)
}
} }
childrenRectX = childrenRectX.coerceAtMost(childrenRectWidth) childrenRectX = childrenRectX.coerceAtMost(childrenRectWidth)
@ -1060,11 +1077,9 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
var width = 1f var width = 1f
var height = 1f var height = 1f
for (child in children) { for (child in visibleChildren) {
if (child.isVisible()) { width = width.coerceAtLeast(child.x + child.width)
width = width.coerceAtLeast(child.x + child.width) height = height.coerceAtLeast(child.y + child.height)
height = height.coerceAtLeast(child.y + child.height)
}
} }
this.width = width this.width = width
@ -1080,9 +1095,11 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
} }
private fun updateVisible() { private fun updateVisible() {
val isVisible = isVisible()
for (child in children) { for (child in children) {
val old = child.isVisible() val old = child.isVisible()
child.visibleAsChildren = isVisible() child.visibleAsChildren = isVisible
val new = child.isVisible() val new = child.isVisible()
if (old != new) { if (old != new) {
@ -1290,14 +1307,14 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (grabMouseInput) return mouseClickedInner(x, y, button) if (grabMouseInput) return mouseClickedInner(x, y, button)
for (child in children) { for (child in visibleChildren) {
if (child.isGrabbingMouseInput() && child.mouseClickedChecked(x, y, button)) { if (child.isGrabbingMouseInput() && child.mouseClickedChecked(x, y, button)) {
killFocusForEverythingExcept(child) killFocusForEverythingExcept(child)
return true return true
} }
} }
for (child in children) { for (child in visibleChildren) {
if (child.mouseClickedChecked(x, y, button)) { if (child.mouseClickedChecked(x, y, button)) {
killFocusForEverythingExcept(child) killFocusForEverythingExcept(child)
return true return true
@ -1314,7 +1331,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (acceptMouseInput && parent == null) popup() if (acceptMouseInput && parent == null) popup()
return mouseClicked(x, y, button) return mouseClicked(x, y, button)
} else if (withinExtendedBounds(x, y)) { } else if (withinExtendedBounds(x, y)) {
for (child in children) { for (child in visibleChildren) {
if (child.mouseClickedChecked(x, y, button)) { if (child.mouseClickedChecked(x, y, button)) {
killFocusForEverythingExcept(child) killFocusForEverythingExcept(child)
return true return true
@ -1342,13 +1359,13 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (grabMouseInput) return mouseReleasedInner(x, y, button) if (grabMouseInput) return mouseReleasedInner(x, y, button)
for (child in children) { for (child in visibleChildren) {
if (child.isGrabbingMouseInput() && child.mouseReleasedChecked(x, y, button)) { if (child.isGrabbingMouseInput() && child.mouseReleasedChecked(x, y, button)) {
return true return true
} }
} }
for (child in children) { for (child in visibleChildren) {
if (child.mouseReleasedChecked(x, y, button)) { if (child.mouseReleasedChecked(x, y, button)) {
return true return true
} }
@ -1363,7 +1380,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isGrabbingMouseInput() || withinBounds(x, y)) { if (isGrabbingMouseInput() || withinBounds(x, y)) {
return mouseReleased(x, y, button) return mouseReleased(x, y, button)
} else if (withinExtendedBounds(x, y)) { } else if (withinExtendedBounds(x, y)) {
for (child in children) { for (child in visibleChildren) {
if (child.mouseReleasedChecked(x, y, button)) { if (child.mouseReleasedChecked(x, y, button)) {
return true return true
} }
@ -1386,13 +1403,13 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (grabMouseInput) return mouseDraggedInner(x, y, button, xDelta, yDelta) if (grabMouseInput) return mouseDraggedInner(x, y, button, xDelta, yDelta)
for (child in children) { for (child in visibleChildren) {
if (child.isGrabbingMouseInput() && child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) { if (child.isGrabbingMouseInput() && child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) {
return true return true
} }
} }
for (child in children) { for (child in visibleChildren) {
if (child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) { if (child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) {
return true return true
} }
@ -1407,7 +1424,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isGrabbingMouseInput() || withinBounds(x, y)) { if (isGrabbingMouseInput() || withinBounds(x, y)) {
return mouseDragged(x, y, button, xDelta, yDelta) return mouseDragged(x, y, button, xDelta, yDelta)
} else if (withinExtendedBounds(x, y)) { } else if (withinExtendedBounds(x, y)) {
for (child in children) { for (child in visibleChildren) {
if (child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) { if (child.mouseDraggedChecked(x, y, button, xDelta, yDelta)) {
return true return true
} }
@ -1431,13 +1448,13 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (grabMouseInput) return mouseScrolledInner(x, y, scroll) if (grabMouseInput) return mouseScrolledInner(x, y, scroll)
for (child in children) { for (child in visibleChildren) {
if (child.isGrabbingMouseInput() && child.mouseScrolledChecked(x, y, scroll)) { if (child.isGrabbingMouseInput() && child.mouseScrolledChecked(x, y, scroll)) {
return true return true
} }
} }
for (child in children) { for (child in visibleChildren) {
if (child.mouseScrolledChecked(x, y, scroll)) { if (child.mouseScrolledChecked(x, y, scroll)) {
return true return true
} }
@ -1452,7 +1469,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isGrabbingMouseInput() || withinBounds(x, y)) { if (isGrabbingMouseInput() || withinBounds(x, y)) {
return mouseScrolled(x, y, scroll) return mouseScrolled(x, y, scroll)
} else if (withinExtendedBounds(x, y)) { } else if (withinExtendedBounds(x, y)) {
for (child in children) { for (child in visibleChildren) {
if (child.mouseScrolledChecked(x, y, scroll)) { if (child.mouseScrolledChecked(x, y, scroll)) {
return true return true
} }
@ -1476,7 +1493,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isFocused) return keyPressedInternal(key, scancode, mods) if (isFocused) return keyPressedInternal(key, scancode, mods)
for (child in children) { for (child in visibleChildren) {
if (child.keyPressed(key, scancode, mods)) { if (child.keyPressed(key, scancode, mods)) {
return true return true
} }
@ -1499,7 +1516,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isFocused) return keyReleasedInternal(key, scancode, mods) if (isFocused) return keyReleasedInternal(key, scancode, mods)
for (child in children) { for (child in visibleChildren) {
if (child.keyReleased(key, scancode, mods)) { if (child.keyReleased(key, scancode, mods)) {
return true return true
} }
@ -1522,7 +1539,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
if (isFocused) return charTypedInternal(codepoint, mods) if (isFocused) return charTypedInternal(codepoint, mods)
for (child in children) { for (child in visibleChildren) {
if (child.charTyped(codepoint, mods)) { if (child.charTyped(codepoint, mods)) {
return true return true
} }

View File

@ -180,7 +180,7 @@ open class EffectListPanel<out S : Screen> @JvmOverloads constructor(
override fun performLayout() { override fun performLayout() {
super.performLayout() super.performLayout()
val sorted = children.stream().filter { it is EffectSquare }.collect(Collectors.toList()) as MutableList<EffectListPanel<S>.EffectSquare> val sorted = childrenView.stream().filter { it is EffectSquare }.collect(Collectors.toList()) as MutableList<EffectListPanel<S>.EffectSquare>
sorted.sortWith { a, b -> sorted.sortWith { a, b ->
a.effect.duration.compareTo(b.effect.duration) a.effect.duration.compareTo(b.effect.duration)