From 00c3f17dd2e41d61a0ec89c246c85d31f5bce1e1 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Mon, 24 Jul 2023 00:30:33 +0700 Subject: [PATCH] Add text outlining to hud values --- .../dbotthepony/mc/otm/client/MatteryGUI.kt | 6 +- .../dbotthepony/mc/otm/client/render/Ext.kt | 199 ++++++++++++------ .../mc/otm/client/render/RenderGravity.kt | 16 ++ 3 files changed, 155 insertions(+), 66 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt index 8f3529a79..3dc54f4b9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/MatteryGUI.kt @@ -254,8 +254,7 @@ object MatteryGUI { val formattedPower = mattery.androidEnergy.batteryLevel.formatPower() - event.guiGraphics.draw(gui.font, formattedPower, left + CHARGE_BG.width + 2f, top + CHARGE_BG.height / 2f + 1f, scale = 0.5f, gravity = RenderGravity.CENTER_LEFT, color = RGBAColor.BLACK) - event.guiGraphics.draw(gui.font, formattedPower, left + CHARGE_BG.width + 1f, top + CHARGE_BG.height / 2f, scale = 0.5f, gravity = RenderGravity.CENTER_LEFT, color = RGBAColor.YELLOW) + event.guiGraphics.draw(gui.font, formattedPower, left + CHARGE_BG.width + 1f, top + CHARGE_BG.height / 2f, scale = 0.5f, gravity = RenderGravity.CENTER_LEFT, color = RGBAColor.YELLOW, drawOutline = true) } } @@ -331,8 +330,7 @@ object MatteryGUI { if (ply.absorptionAmount > 0) formattedHealth = TextComponent("%d+%d/%d".format(ply.health.toInt(), ply.absorptionAmount.toInt(), ply.maxHealth.toInt())) - event.guiGraphics.draw(minecraft.font, formattedHealth, left - 1f, top + HEALTH_BG.height / 2f + 1f, scale = 0.5f, gravity = RenderGravity.CENTER_RIGHT, color = RGBAColor.BLACK) - event.guiGraphics.draw(minecraft.font, formattedHealth, left - 2f, top + HEALTH_BG.height / 2f, scale = 0.5f, gravity = RenderGravity.CENTER_RIGHT, color = getHealthColorForPlayer(ply)) + event.guiGraphics.draw(minecraft.font, formattedHealth, left - 2f, top + HEALTH_BG.height / 2f, scale = 0.5f, gravity = RenderGravity.CENTER_RIGHT, color = getHealthColorForPlayer(ply), drawOutline = true) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt index 82bd449f4..bea85bca2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/Ext.kt @@ -73,6 +73,59 @@ inline val PoseStack.Pose.pose: Matrix4f get() = pose() private val buffer = DynamicBufferSource(vertexSorting = VertexSorting.ORTHOGRAPHIC_Z) private fun buffer() = buffer +private fun Font.drawInBatch( + text: Any, x: Float, y: Float, color: Int, drawShadow: Boolean, + matrix4f: Matrix4f, buffer: MultiBufferSource, displayMode: Font.DisplayMode, + effectColor: Int, packedLightCoords: Int, gravity: RenderGravity, + rounding: GravityRounding +): Int { + if (text is String) + return drawInBatch( + text, + gravity.x(x, this, text, rounding = rounding), + gravity.y(y, lineHeight.toFloat(), rounding = rounding), + color, + drawShadow, + matrix4f, + buffer, + displayMode, + effectColor, + packedLightCoords) + else if (text is Component) + return drawInBatch( + text, + gravity.x(x, this, text, rounding = rounding), + gravity.y(y, lineHeight.toFloat(), rounding = rounding), + color, + drawShadow, + matrix4f, + buffer, + displayMode, + effectColor, + packedLightCoords) + else if (text is FormattedCharSequence) + return drawInBatch( + text, + gravity.x(x, this, text, rounding = rounding), + gravity.y(y, lineHeight.toFloat(), rounding = rounding), + color, + drawShadow, + matrix4f, + buffer, + displayMode, + effectColor, + packedLightCoords) + else + throw IllegalArgumentException(text::class.qualifiedName) +} + +private val outlinePositions = listOf( + 1 to 0, + -1 to 0, + 0 to 1, + 0 to -1, +) + private fun Font.drawInternal( poseStack: PoseStack, text: Any, @@ -92,9 +145,10 @@ private fun Font.drawInternal( shadowZ: Float, customShadow: Boolean, rounding: GravityRounding, + drawOutline: Boolean, + outlineColor: RGBAColor, + outlineZ: Float, ): Float { - require(!drawShadow && !customShadow || drawShadow != customShadow) { "Can not draw built in shadow and custom shadow at the same time" } - val inv: Float if (scale != 1f) { @@ -115,64 +169,61 @@ private fun Font.drawInternal( poseStack.translate(0f, 0f, shadowZ) } - if (text is String) - drawInBatch( - text, - gravity.x((x + shadowX) * inv, this, text, 1f, rounding), - gravity.y((y + shadowY) * inv, lineHeight.toFloat(), 1f, rounding), - shadowColor.toRGB(), - false, - poseStack.last().pose(), - buffer, - displayMode, - effectColor, - packedLightCoords) - else if (text is Component) - drawInBatch( - text, - gravity.x((x + shadowX) * inv, this, text, 1f, rounding), - gravity.y((y + shadowY) * inv, lineHeight.toFloat(), 1f, rounding), - shadowColor.toRGB(), - false, - poseStack.last().pose(), - buffer, - displayMode, - effectColor, - packedLightCoords) + drawInBatch( + text, + (x + shadowX) * inv, + (y + shadowY) * inv, + shadowColor.toRGB(), + false, + poseStack.last().pose(), + buffer, + displayMode, + effectColor, + packedLightCoords, + gravity, rounding) if (shadowZ != 0f) { poseStack.translate(0f, 0f, -shadowZ) } } - val width: Int + if (drawOutline) { + if (outlineZ != 0f) { + poseStack.translate(0f, 0f, outlineZ) + } - if (text is String) - width = drawInBatch( - text, - gravity.x(x * inv, this, text, 1f, rounding), - gravity.y(y * inv, lineHeight.toFloat(), 1f, rounding), - color.toRGB(), - drawShadow, - poseStack.last().pose(), - buffer, - displayMode, - effectColor, - packedLightCoords) - else if (text is Component) - width = drawInBatch( - text, - gravity.x(x * inv, this, text, 1f, rounding), - gravity.y(y * inv, lineHeight.toFloat(), 1f, rounding), - color.toRGB(), - drawShadow, - poseStack.last().pose(), - buffer, - displayMode, - effectColor, - packedLightCoords) - else - throw IllegalArgumentException(text::class.qualifiedName) + for ((_x, _y) in outlinePositions) { + drawInBatch( + text, + x * inv + _x, + y * inv + _y, + outlineColor.toRGB(), + drawShadow, + poseStack.last().pose(), + buffer, + displayMode, + effectColor, + packedLightCoords, + gravity, rounding) + } + + if (outlineZ != 0f) { + poseStack.translate(0f, 0f, -outlineZ) + } + } + + val width = drawInBatch( + text, + x * inv, + y * inv, + color.toRGB(), + drawShadow, + poseStack.last().pose(), + buffer, + displayMode, + effectColor, + packedLightCoords, + gravity, rounding) if (scale != 1f) { poseStack.popPose() @@ -201,9 +252,12 @@ fun Font.draw( shadowColor: RGBAColor = RGBAColor.BLACK, shadowX: Float = 1f, shadowY: Float = 1f, - shadowZ: Float = 0f, + shadowZ: Float = -0.1f, customShadow: Boolean = false, rounding: GravityRounding = if (scale == 1f) GravityRounding.DEFAULT else GravityRounding.NO, + drawOutline: Boolean = false, + outlineColor: RGBAColor = RGBAColor.BLACK, + outlineZ: Float = -0.1f, ): Float { return drawInternal( poseStack = poseStack, @@ -224,6 +278,9 @@ fun Font.draw( shadowZ = shadowZ, customShadow = customShadow, rounding = rounding, + drawOutline = drawOutline, + outlineColor = outlineColor, + outlineZ = outlineZ, ) } @@ -243,9 +300,12 @@ fun Font.draw( shadowColor: RGBAColor = RGBAColor.BLACK, shadowX: Float = 1f, shadowY: Float = 1f, - shadowZ: Float = 0f, + shadowZ: Float = -0.1f, customShadow: Boolean = false, rounding: GravityRounding = if (scale == 1f) GravityRounding.DEFAULT else GravityRounding.NO, + drawOutline: Boolean = false, + outlineColor: RGBAColor = RGBAColor.BLACK, + outlineZ: Float = -0.1f, ): Float { return drawInternal( poseStack = poseStack, @@ -265,7 +325,10 @@ fun Font.draw( shadowY = shadowY, shadowZ = shadowZ, customShadow = customShadow, - rounding = rounding + rounding = rounding, + drawOutline = drawOutline, + outlineColor = outlineColor, + outlineZ = outlineZ, ) } @@ -282,11 +345,14 @@ fun GuiGraphics.draw( packedLightCoords: Int = 15728880, effectColor: Int = 0, shadowColor: RGBAColor = RGBAColor.BLACK, - shadowX: Float = 0f, - shadowY: Float = 0f, - shadowZ: Float = 0f, + shadowX: Float = 1f, + shadowY: Float = 1f, + shadowZ: Float = -0.1f, customShadow: Boolean = false, rounding: GravityRounding = if (scale == 1f) GravityRounding.DEFAULT else GravityRounding.NO, + drawOutline: Boolean = false, + outlineColor: RGBAColor = RGBAColor.BLACK, + outlineZ: Float = -0.1f, ): Float { val width = font.draw( poseStack = pose(), @@ -307,6 +373,9 @@ fun GuiGraphics.draw( shadowZ = shadowZ, customShadow = customShadow, rounding = rounding, + drawOutline = drawOutline, + outlineColor = outlineColor, + outlineZ = outlineZ, ) flush() @@ -326,11 +395,14 @@ fun GuiGraphics.draw( packedLightCoords: Int = 15728880, effectColor: Int = 0, shadowColor: RGBAColor = RGBAColor.BLACK, - shadowX: Float = 0f, - shadowY: Float = 0f, - shadowZ: Float = 0f, + shadowX: Float = 1f, + shadowY: Float = 1f, + shadowZ: Float = -0.1f, customShadow: Boolean = false, rounding: GravityRounding = if (scale == 1f) GravityRounding.DEFAULT else GravityRounding.NO, + drawOutline: Boolean = false, + outlineColor: RGBAColor = RGBAColor.BLACK, + outlineZ: Float = -0.1f, ): Float { val width = font.draw( poseStack = pose(), @@ -351,6 +423,9 @@ fun GuiGraphics.draw( shadowZ = shadowZ, customShadow = customShadow, rounding = rounding, + drawOutline = drawOutline, + outlineColor = outlineColor, + outlineZ = outlineZ, ) flush() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt index 8a8efb451..fc755570a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/RenderGravity.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.client.render import net.minecraft.client.gui.Font import net.minecraft.network.chat.Component +import net.minecraft.util.FormattedCharSequence import ru.dbotthepony.mc.otm.core.FloatSupplier import kotlin.math.roundToInt @@ -65,6 +66,9 @@ interface IXGravity { fun x(x: Float, font: Font, text: String): Float = x(x, font, text, 1f) fun x(x: Float, font: Font, text: String, scale: Float = 1f, rounding: GravityRounding = GravityRounding.DEFAULT): Float + fun x(x: Float, font: Font, text: FormattedCharSequence): Float = x(x, font, text, 1f) + fun x(x: Float, font: Font, text: FormattedCharSequence, scale: Float = 1f, rounding: GravityRounding = GravityRounding.DEFAULT): Float + fun x(x: Float, width: Int, scale: Float = 1f): Float { return x(x, width.toFloat() * scale).roundToInt().toFloat() } @@ -98,6 +102,10 @@ enum class XGravity : IXGravity { override fun x(x: Float, font: Font, text: String, scale: Float, rounding: GravityRounding): Float { return x } + + override fun x(x: Float, font: Font, text: FormattedCharSequence, scale: Float, rounding: GravityRounding): Float { + return x + } }, CENTER { override fun x(x: Float, width: FloatSupplier, scale: Float, rounding: GravityRounding): Float { @@ -115,6 +123,10 @@ enum class XGravity : IXGravity { override fun x(x: Float, font: Font, text: String, scale: Float, rounding: GravityRounding): Float { return rounding.round(x, font.width(text) / 2f * scale) } + + override fun x(x: Float, font: Font, text: FormattedCharSequence, scale: Float, rounding: GravityRounding): Float { + return rounding.round(x, font.width(text) / 2f * scale) + } }, RIGHT { override fun x(x: Float, width: FloatSupplier, scale: Float, rounding: GravityRounding): Float { @@ -132,6 +144,10 @@ enum class XGravity : IXGravity { override fun x(x: Float, font: Font, text: String, scale: Float, rounding: GravityRounding): Float { return rounding.round(x, font.width(text) * scale) } + + override fun x(x: Float, font: Font, text: FormattedCharSequence, scale: Float, rounding: GravityRounding): Float { + return rounding.round(x, font.width(text) * scale) + } }; }