Charts in storage tooltips

This commit is contained in:
DBotThePony 2024-10-04 13:41:55 +07:00
parent 693075d600
commit e7ded02d30
Signed by: DBot
GPG Key ID: DCC23B5715498507
8 changed files with 289 additions and 54 deletions

View File

@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.client.MatteryGUI;
import ru.dbotthepony.mc.otm.client.model.ExosuitModel; import ru.dbotthepony.mc.otm.client.model.ExosuitModel;
import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel; import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel; import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.client.render.ChartTooltipElement;
import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer; import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer;
import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer; import ru.dbotthepony.mc.otm.client.render.blockentity.BatteryBankRenderer;
import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer; import ru.dbotthepony.mc.otm.client.render.blockentity.MatterBatteryBankRenderer;
@ -159,6 +160,8 @@ public final class OverdriveThatMatters {
bus.addListener(EventPriority.NORMAL, BatteryBankRenderer.Companion::onRegisterAdditionalModels); bus.addListener(EventPriority.NORMAL, BatteryBankRenderer.Companion::onRegisterAdditionalModels);
bus.addListener(EventPriority.NORMAL, MatterBatteryBankRenderer.Companion::onRegisterAdditionalModels); bus.addListener(EventPriority.NORMAL, MatterBatteryBankRenderer.Companion::onRegisterAdditionalModels);
bus.addListener(EventPriority.NORMAL, ChartTooltipElement.Companion::register);
MBlockColors.INSTANCE.register(bus); MBlockColors.INSTANCE.register(bus);
} }

View File

@ -7,12 +7,16 @@ import com.mojang.blaze3d.vertex.ByteBufferBuilder
import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexFormat import com.mojang.blaze3d.vertex.VertexFormat
import it.unimi.dsi.fastutil.floats.Float2ObjectMap
import net.minecraft.client.gui.Font import net.minecraft.client.gui.Font
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent
import net.minecraft.client.renderer.GameRenderer import net.minecraft.client.renderer.GameRenderer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.inventory.tooltip.TooltipComponent
import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent
import org.lwjgl.opengl.GL11.GL_LESS import org.lwjgl.opengl.GL11.GL_LESS
import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.client.minecraft
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.acos import kotlin.math.acos
import kotlin.math.cos import kotlin.math.cos
@ -40,7 +44,7 @@ data class ChartMouseLabels(
data class ChartLevelLabels( data class ChartLevelLabels(
val labels: Map<Float, Component>, val labels: Map<Float, Component>,
val font: Font, val font: Font? = null,
val lineColor: RGBAColor = RGBAColor.DARK_GREEN, val lineColor: RGBAColor = RGBAColor.DARK_GREEN,
val textColor: RGBAColor = RGBAColor.DARK_GREEN, val textColor: RGBAColor = RGBAColor.DARK_GREEN,
val textGravity: RenderGravity = RenderGravity.TOP_RIGHT, val textGravity: RenderGravity = RenderGravity.TOP_RIGHT,
@ -49,19 +53,44 @@ data class ChartLevelLabels(
private val BYTE_BUFFER_BUILDER = ByteBufferBuilder(786_432) private val BYTE_BUFFER_BUILDER = ByteBufferBuilder(786_432)
class ChartTooltipElement(
private val normalized: List<Pair<FloatArray, RGBAColor>>,
private val width: Float,
private val height: Float,
private val levelLabels: ChartLevelLabels? = null,
) : ClientTooltipComponent, TooltipComponent {
override fun getHeight(): Int {
return this.height.toInt()
}
override fun getWidth(font: Font): Int {
return this.width.toInt()
}
override fun renderImage(font: Font, x: Int, y: Int, graphics: GuiGraphics) {
renderChart(graphics.pose(), normalized, this.width, this.height - 10f, levelLabels = this.levelLabels, x = x.toFloat(), y = y.toFloat() + 10f)
}
companion object {
fun register(event: RegisterClientTooltipComponentFactoriesEvent) {
event.register(ChartTooltipElement::class.java) { it }
}
}
}
fun renderChart( fun renderChart(
poseStack: PoseStack, poseStack: PoseStack,
normalized: FloatArray, charts: List<Pair<FloatArray, RGBAColor>>,
width: Float, width: Float,
height: Float, height: Float,
color: RGBAColor = RGBAColor.WHITE,
labels: ChartMouseLabels? = null, labels: ChartMouseLabels? = null,
levelLabels: ChartLevelLabels? = null, levelLabels: ChartLevelLabels? = null,
x: Float = 0f, x: Float = 0f,
y: Float = 0f, y: Float = 0f,
) { ) {
require(charts.all { it.first.size == charts[0].first.size }) { "Provided chart data is not of same width" }
val builder = BufferBuilder(BYTE_BUFFER_BUILDER, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR) val builder = BufferBuilder(BYTE_BUFFER_BUILDER, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR)
val step = width / normalized.size val step = width / charts[0].first.size
val pose = poseStack.last().pose val pose = poseStack.last().pose
val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width val checkLabels = labels != null && labels.mouseY in 0f .. height && labels.mouseX in 0f .. width
@ -81,40 +110,42 @@ fun renderChart(
} }
} }
for (i in 0 until normalized.size - 1) { for ((normalized, color) in charts) {
val y0 = y + (1f - normalized[i]) * height for (i in 0 until normalized.size - 1) {
val y1 = y + (1f - normalized[i + 1]) * height val y0 = y + (1f - normalized[i]) * height
val y1 = y + (1f - normalized[i + 1]) * height
val x0 = x + width - (i + 0.5f) * step val x0 = x + width - (i + 0.5f) * step
val x1 = x + width - (i + 1.5f) * step val x1 = x + width - (i + 1.5f) * step
val xDiff = x1 - x0 val xDiff = x1 - x0
val yDiff = y1 - y0 val yDiff = y1 - y0
if (yDiff.sign == 0f) { if (yDiff.sign == 0f) {
builder.vertex(pose, x0, y0 + LINE_WIDTH / 2f, 0f).color(color) builder.vertex(pose, x0, y0 + LINE_WIDTH / 2f, 0f).color(color)
builder.vertex(pose, x0, y0 - LINE_WIDTH / 2f, 0f).color(color) builder.vertex(pose, x0, y0 - LINE_WIDTH / 2f, 0f).color(color)
builder.vertex(pose, x1, y1 - LINE_WIDTH / 2f, 0f).color(color) builder.vertex(pose, x1, y1 - LINE_WIDTH / 2f, 0f).color(color)
builder.vertex(pose, x1, y1 + LINE_WIDTH / 2f, 0f).color(color) builder.vertex(pose, x1, y1 + LINE_WIDTH / 2f, 0f).color(color)
} else { } else {
val length = (xDiff.pow(2f) + yDiff.pow(2f)).pow(0.5f) val length = (xDiff.pow(2f) + yDiff.pow(2f)).pow(0.5f)
val angle = acos(xDiff / length) * yDiff.sign - PI / 2f // rotate 90 deg val angle = acos(xDiff / length) * yDiff.sign - PI / 2f // rotate 90 deg
val xDisp = cos(angle).toFloat() * LINE_WIDTH / 2f val xDisp = cos(angle).toFloat() * LINE_WIDTH / 2f
val yDisp = sin(angle).toFloat() * LINE_WIDTH / 2f val yDisp = sin(angle).toFloat() * LINE_WIDTH / 2f
builder.vertex(pose, x0 + xDisp, y0 + yDisp, 0f).color(color) builder.vertex(pose, x0 + xDisp, y0 + yDisp, 0f).color(color)
builder.vertex(pose, x0 - xDisp, y0 - yDisp, 0f).color(color) builder.vertex(pose, x0 - xDisp, y0 - yDisp, 0f).color(color)
builder.vertex(pose, x1 - xDisp, y1 - yDisp, 0f).color(color) builder.vertex(pose, x1 - xDisp, y1 - yDisp, 0f).color(color)
builder.vertex(pose, x1 + xDisp, y1 + yDisp, 0f).color(color) builder.vertex(pose, x1 + xDisp, y1 + yDisp, 0f).color(color)
} }
//graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH) //graphics.renderRect(x0, y0, LINE_WIDTH, LINE_WIDTH)
if (checkLabels && drawLabel == -1 && labels!!.mouseX in x1 .. x0) { if (checkLabels && drawLabel == -1 && labels!!.mouseX in x1 .. x0) {
drawLabel = i drawLabel = i
drawPointX = x0 // linearInterpolation(0.5f, x0, x1) drawPointX = x0 // linearInterpolation(0.5f, x0, x1)
drawPointY = y0 // linearInterpolation(0.5f, y0, y1) drawPointY = y0 // linearInterpolation(0.5f, y0, y1)
}
} }
} }
@ -130,13 +161,14 @@ fun renderChart(
RenderSystem.depthFunc(GL_LESS) RenderSystem.depthFunc(GL_LESS)
if (levelLabels != null && levelLabels.labels.isNotEmpty()) { if (levelLabels != null && levelLabels.labels.isNotEmpty()) {
val font = levelLabels.font ?: minecraft.font
for ((level, label) in levelLabels.labels) { for ((level, label) in levelLabels.labels) {
val y0 = y + (1f - level) * height val y0 = y + (1f - level) * height
val tX = x + levelLabels.textGravity.repositionX(width, levelLabels.font.width(label).toFloat()) - 1f val tX = x + levelLabels.textGravity.repositionX(width, font.width(label).toFloat()) - 1f
val tY = y0 - LINE_WIDTH - 1f - levelLabels.font.lineHeight + levelLabels.textGravity.repositionY(levelLabels.font.lineHeight * 2f + LINE_WIDTH + 2f, levelLabels.font.lineHeight.toFloat()) + 1f val tY = y0 - LINE_WIDTH - 1f - font.lineHeight + levelLabels.textGravity.repositionY(font.lineHeight * 2f + LINE_WIDTH + 2f, font.lineHeight.toFloat()) + 1f
levelLabels.font.draw( font.draw(
poseStack, poseStack,
label, label,
x = tX, x = tX,

View File

@ -1,13 +1,16 @@
package ru.dbotthepony.mc.otm.client.render package ru.dbotthepony.mc.otm.client.render
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.datafixers.util.Either
import net.minecraft.client.gui.Font import net.minecraft.client.gui.Font
import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.renderer.MultiBufferSource import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.FormattedText
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.util.FormattedCharSequence import net.minecraft.util.FormattedCharSequence
import net.minecraft.world.inventory.tooltip.TooltipComponent
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.math.RGBAColor
@ -78,10 +81,15 @@ class MGUIGraphics(val parent: GuiGraphics) {
renderCheckerboard(pose.last().pose(), x, y, width, height, z, color) renderCheckerboard(pose.last().pose(), x, y, width, height, z, color)
} }
fun renderComponentTooltip(font: Font, lines: MutableList<Component>, x: Int, y: Int, itemStack: ItemStack = ItemStack.EMPTY) { fun renderComponentTooltip(font: Font, lines: List<FormattedText>, x: Int, y: Int, itemStack: ItemStack = ItemStack.EMPTY) {
parent.renderComponentTooltip(font, lines, x, y, itemStack) parent.renderComponentTooltip(font, lines, x, y, itemStack)
} }
@JvmName("renderComponentTooltipFromElements")
fun renderComponentTooltip(font: Font, lines: List<Either<FormattedText, TooltipComponent>>, x: Int, y: Int, itemStack: ItemStack = ItemStack.EMPTY) {
parent.renderComponentTooltipFromElements(font, lines, x, y, itemStack)
}
fun flush() { fun flush() {
parent.flush() parent.flush()
} }

View File

@ -58,7 +58,7 @@ open class DecimalHistoryChartPanel<out S : MatteryScreen<*>>(
renderChart( renderChart(
graphics.pose, graphics.pose,
normalized, listOf(normalized to RGBAColor.WHITE),
width, width,
height, height,
labels = ChartMouseLabels( labels = ChartMouseLabels(

View File

@ -4,11 +4,14 @@ import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.BufferUploader import com.mojang.blaze3d.vertex.BufferUploader
import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.VertexFormat import com.mojang.blaze3d.vertex.VertexFormat
import com.mojang.datafixers.util.Either
import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.ints.IntArrayList
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.renderer.GameRenderer import net.minecraft.client.renderer.GameRenderer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.FormattedText
import net.minecraft.world.inventory.tooltip.TooltipComponent
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
import ru.dbotthepony.kommons.util.value import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
@ -52,13 +55,15 @@ open class MatterGaugePanel<out S : Screen> @JvmOverloads constructor(
private var lastDraw = nanoTime private var lastDraw = nanoTime
private var lastLevel = 0f private var lastLevel = 0f
protected open fun makeTooltip(): MutableList<Component> { protected open fun makeTooltip(): MutableList<Either<FormattedText, TooltipComponent>> {
return mutableListOf( return mutableListOf(
TranslatableComponent( Either.left(
"otm.gui.matter.percentage_level", TranslatableComponent(
String.format("%.2f", widget.percentage * 100.0) "otm.gui.matter.percentage_level",
String.format("%.2f", widget.percentage * 100.0)
)
), ),
formatMatterLevel(widget.level, widget.maxLevel, formatAsReadable = ShiftPressedCond) Either.left(formatMatterLevel(widget.level, widget.maxLevel, formatAsReadable = ShiftPressedCond))
) )
} }
@ -145,7 +150,7 @@ open class ProfiledMatterGaugePanel<out S : Screen>(
x: Float = 0f, x: Float = 0f,
y: Float = 0f y: Float = 0f
): MatterGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y) { ): MatterGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y) {
override fun makeTooltip(): MutableList<Component> { override fun makeTooltip(): MutableList<Either<FormattedText, TooltipComponent>> {
return super.makeTooltip().also { return super.makeTooltip().also {
formatHistory( formatHistory(
it, it,

View File

@ -1,7 +1,10 @@
package ru.dbotthepony.mc.otm.client.screen.widget package ru.dbotthepony.mc.otm.client.screen.widget
import com.mojang.datafixers.util.Either
import net.minecraft.client.gui.screens.Screen import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.FormattedText
import net.minecraft.world.inventory.tooltip.TooltipComponent
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.ShiftPressedCond import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
@ -25,10 +28,10 @@ open class PowerGaugePanel<out S : Screen>(
scissor = true scissor = true
} }
protected open fun makeTooltip(): MutableList<Component> { protected open fun makeTooltip(): MutableList<Either<FormattedText, TooltipComponent>> {
return mutableListOf( return mutableListOf(
TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", widget.percentage * 100.0)), Either.left(TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", widget.percentage * 100.0))),
formatPowerLevel(widget.level, widget.maxLevel, formatAsReadable = ShiftPressedCond) Either.left(formatPowerLevel(widget.level, widget.maxLevel, formatAsReadable = ShiftPressedCond))
) )
} }
@ -95,7 +98,7 @@ open class ProfiledPowerGaugePanel<out S : Screen>(
width: Float = GAUGE_BACKGROUND.width, width: Float = GAUGE_BACKGROUND.width,
height: Float = GAUGE_BACKGROUND.height height: Float = GAUGE_BACKGROUND.height
) : PowerGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y, width, height) { ) : PowerGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y, width, height) {
override fun makeTooltip(): MutableList<Component> { override fun makeTooltip(): MutableList<Either<FormattedText, TooltipComponent>> {
return super.makeTooltip().also { return super.makeTooltip().also {
formatHistory( formatHistory(
it, it,

View File

@ -48,6 +48,11 @@ object ClientConfig : AbstractConfig("client", ModConfig.Type.CLIENT) {
.comment("For those who want it.") .comment("For those who want it.")
.define("REDSTONE_CONTROLS_ITEM_ICONS", false) .define("REDSTONE_CONTROLS_ITEM_ICONS", false)
var CHARTS_IN_TOOLTIPS: Boolean by builder
.comment("Draw charts in storage tooltips instead of list of last 20 values.")
.comment("Disable to get EnderIO-like experience")
.define("CHARTS_IN_TOOLTIPS", true)
init { init {
builder.pop() builder.pop()
} }

View File

@ -1,9 +1,17 @@
package ru.dbotthepony.mc.otm.core.util package ru.dbotthepony.mc.otm.core.util
import com.mojang.datafixers.util.Either
import it.unimi.dsi.fastutil.chars.CharArrayList import it.unimi.dsi.fastutil.chars.CharArrayList
import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.FormattedText
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.world.inventory.tooltip.TooltipComponent
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.client.render.ChartLevelLabels
import ru.dbotthepony.mc.otm.client.render.ChartTooltipElement
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
@ -252,8 +260,179 @@ fun formatTickDuration(ticks: Int, longFormat: Boolean = false): String {
} }
} }
/**
* Clientside only function, do not call on shared/server realm.
*/
fun formatHistory( fun formatHistory(
result: MutableList<Component>, result: MutableList<Either<FormattedText, TooltipComponent>>,
widget: ProfiledLevelGaugeWidget<*>,
bias: Int = 0,
decimals: Int = 3,
verbose: BooleanSupplier = never,
suffix: Any = "",
) {
if (!ClientConfig.GUI.CHARTS_IN_TOOLTIPS) {
formatHistoryLines(result, widget, bias, decimals, verbose, suffix)
} else {
formatHistoryChart(result, widget, bias, decimals, verbose, suffix)
}
}
private fun formatHistoryChart(
result: MutableList<Either<FormattedText, TooltipComponent>>,
widget: ProfiledLevelGaugeWidget<*>,
bias: Int = 0,
decimals: Int = 3,
verbose: BooleanSupplier = never,
suffix: Any = "",
) {
val diff = Array(widget.received.width) { widget.received[it] - widget.transferred[it] }
val normalizedDiff: FloatArray
val received: FloatArray
val transferred: FloatArray
val labels: ChartLevelLabels
val hasPositiveInfinity = diff.any { it.isInfinite && it.isPositive }
val hasNegativeInfinity = diff.any { it.isInfinite && it.isNegative }
if (hasPositiveInfinity && hasNegativeInfinity) {
normalizedDiff = FloatArray(diff.size) {
if (widget.received[it].isInfinite && widget.transferred[it].isInfinite)
0.5f
else if (diff[it].isInfinite && diff[it].isNegative)
0.1f
else if (diff[it].isInfinite && diff[it].isPositive)
0.9f
else
0.5f
}
received = FloatArray(diff.size) {
if (widget.received[it].isInfinite) 0.9f else 0.5f
}
transferred = FloatArray(diff.size) {
if (widget.transferred[it].isInfinite) 0.1f else 0.5f
}
labels = ChartLevelLabels(
labels = mapOf(
0.5f to Decimal.ZERO.formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias),
0.1f to TextComponent("-∞"),
0.9f to TextComponent(""),
)
)
} else if (hasPositiveInfinity) {
normalizedDiff = FloatArray(diff.size) {
if (diff[it].isInfinite)
0.9f
else
0.5f
}
received = FloatArray(diff.size) {
if (widget.received[it].isInfinite) 0.9f else 0.5f
}
transferred = FloatArray(diff.size)
transferred.fill(0.5f)
labels = ChartLevelLabels(
labels = mapOf(
0.5f to Decimal.ZERO.formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias),
0.9f to TextComponent(""),
)
)
} else if (hasNegativeInfinity) {
normalizedDiff = FloatArray(diff.size) {
if (diff[it].isInfinite)
0.1f
else
0.5f
}
received = FloatArray(diff.size)
received.fill(0.5f)
transferred = FloatArray(diff.size) {
if (widget.transferred[it].isInfinite) 0.1f else 0.5f
}
labels = ChartLevelLabels(
labels = mapOf(
0.5f to Decimal.ZERO.formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias),
0.9f to TextComponent("-∞"),
)
)
} else {
val max = maxOf(widget.received.max(), widget.transferred.max())
val labelNames = Float2ObjectArrayMap<Component>()
labelNames[0.5f] = Decimal.ZERO.formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias)
if (max.isZero) {
normalizedDiff = FloatArray(diff.size)
normalizedDiff.fill(0.5f)
received = FloatArray(diff.size)
received.fill(0.5f)
transferred = FloatArray(diff.size)
transferred.fill(0.5f)
labelNames[0.1f] = TextComponent("-∞")
labelNames[0.9f] = TextComponent("")
} else {
normalizedDiff = FloatArray(diff.size) {
(diff[it] / max).toFloat() * 0.4f + 0.5f
}
received = FloatArray(diff.size) {
(widget.received[it] / max).toFloat() * 0.4f + 0.5f
}
transferred = FloatArray(diff.size) {
(widget.transferred[it] / max).toFloat() * -0.4f + 0.5f
}
labelNames[0.1f] = (-max).formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias)
if (verbose.asBoolean) labelNames[0.3f] = (-max * Decimal.ONE_HALF).formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias)
labelNames[0.9f] = max.formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias)
if (verbose.asBoolean) labelNames[0.7f] = (max * Decimal.ONE_HALF).formatSiComponent(suffix, decimals, formatAsReadable = verbose, bias = bias)
}
labels = ChartLevelLabels(labels = labelNames)
}
val charts: List<Pair<FloatArray, RGBAColor>>
val receivedActivity = widget.received.any { it.isNotZero }
val transferredActivity = widget.received.any { it.isNotZero }
if (!receivedActivity && transferredActivity) {
charts = listOf(
received to RGBAColor.YELLOW,
normalizedDiff to RGBAColor.WHITE,
transferred to RGBAColor.RED,
)
} else if (!transferredActivity && receivedActivity) {
charts = listOf(
transferred to RGBAColor.RED,
normalizedDiff to RGBAColor.WHITE,
received to RGBAColor.YELLOW,
)
} else {
charts = listOf(
received to RGBAColor.YELLOW,
transferred to RGBAColor.RED,
normalizedDiff to RGBAColor.WHITE,
)
}
result.add(Either.right(ChartTooltipElement(charts, if (verbose.asBoolean) 200f else 100f, if (verbose.asBoolean) 120f else 60f, levelLabels = labels)))
}
private fun formatHistoryLines(
result: MutableList<Either<FormattedText, TooltipComponent>>,
widget: ProfiledLevelGaugeWidget<*>, widget: ProfiledLevelGaugeWidget<*>,
bias: Int = 0, bias: Int = 0,
decimals: Int = 3, decimals: Int = 3,
@ -321,13 +500,13 @@ fun formatHistory(
) )
} }
result.add(TextComponent("")) result.add(Either.left(TextComponent("")))
result.add(lines.removeFirst().format()) result.add(Either.left(lines.removeFirst().format()))
if (verbose.asBoolean) { if (verbose.asBoolean) {
result.add(TextComponent("---")) result.add(Either.left(TextComponent("---")))
result.add(lines.removeFirst().format()) result.add(Either.left(lines.removeFirst().format()))
result.add(TextComponent("---")) result.add(Either.left(TextComponent("---")))
lines.forEach { result.add(it.format()) } lines.forEach { result.add(Either.left(it.format())) }
} }
} }