Skip to content

Commit

Permalink
Merge pull request #347 from Thunderblade73/pr/DavidArthurCole/PetDis…
Browse files Browse the repository at this point in the history
…playV2
  • Loading branch information
DavidArthurCole authored Feb 22, 2025
2 parents ee76a0d + 9abd715 commit 48c5086
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 70 deletions.
29 changes: 29 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/shader/CircleShader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package at.hannibal2.skyhanni.shader

import at.hannibal2.skyhanni.utils.shader.Shader
import at.hannibal2.skyhanni.utils.shader.Uniform
import net.minecraft.client.Minecraft

object CircleShader : Shader("circle", "circle") {

val INSTANCE get() = this

var scaleFactor: Float = 0f
var radius: Float = 0f
var smoothness: Float = 0f
var centerPos: FloatArray = floatArrayOf(0f, 0f)
set(value) {
field = floatArrayOf(value[0], Minecraft.getMinecraft().displayHeight - value[1])
}
var angle1: Float = 0f
var angle2: Float = 0f

override fun registerUniforms() {
registerUniform(Uniform.UniformType.FLOAT, "scaleFactor") { scaleFactor }
registerUniform(Uniform.UniformType.FLOAT, "radius") { radius }
registerUniform(Uniform.UniformType.FLOAT, "smoothness") { smoothness }
registerUniform(Uniform.UniformType.FLOAT, "angle1") { angle1 }
registerUniform(Uniform.UniformType.FLOAT, "angle2") { angle2 }
registerUniform(Uniform.UniformType.VEC2, "centerPos") { centerPos }
}
}
39 changes: 39 additions & 0 deletions src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import at.hannibal2.skyhanni.features.misc.PatcherFixes
import at.hannibal2.skyhanni.features.misc.RoundedRectangleOutlineShader
import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader
import at.hannibal2.skyhanni.features.misc.RoundedTextureShader
import at.hannibal2.skyhanni.shader.CircleShader
import at.hannibal2.skyhanni.utils.CollectionUtils.zipWithNext3
import at.hannibal2.skyhanni.utils.ColorUtils.getFirstColorCode
import at.hannibal2.skyhanni.utils.LocationUtils.calculateEdges
import at.hannibal2.skyhanni.utils.LorenzColor.Companion.toLorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils.getCorners
import at.hannibal2.skyhanni.utils.RenderUtils.drawRoundRect
import at.hannibal2.skyhanni.utils.compat.GuiScreenUtils
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned
Expand Down Expand Up @@ -1934,6 +1936,43 @@ object RenderUtils {
GlStateManager.popMatrix()
}

/**
* Method to draw a circle.
*
* **NOTE:** If you are using [GlStateManager.translate] or [GlStateManager.scale]
* with this method, ensure they are invoked in the correct order if you use both. That is, [GlStateManager.translate]
* is called **BEFORE** [GlStateManager.scale], otherwise the rectangle will not be rendered correctly
*
* @param x The x-coordinate of the circle's center.
* @param y The y-coordinate of the circle's center.
* @param radius The circle's radius.
* @param color The fill color.
* @param angle1 defines the start of the semicircle (Default value makes it a full circle). Must be in range [0,2*pi] (0 is on the left and increases counterclockwise)
* @param angle2 defines the end of the semicircle (Default value makes it a full circle). Must be in range [0,2*pi] (0 is on the left and increases counterclockwise)
* @param smoothness smooths out the edge. (In amount of blurred pixels)
*/
fun drawFilledCircle(x: Int, y: Int, radius: Int, color: Color, smoothness: Float = 2.5f, angle1: Float = 7.0f, angle2: Float = 7.0f) {
val scaleFactor = ScaledResolution(Minecraft.getMinecraft()).scaleFactor
val radiusIn = radius * scaleFactor
val xIn = x * scaleFactor
val yIn = y * scaleFactor

CircleShader.scaleFactor = scaleFactor.toFloat()
CircleShader.radius = radiusIn.toFloat()
CircleShader.smoothness = smoothness.toFloat()
CircleShader.centerPos = floatArrayOf((xIn + radiusIn).toFloat(), (yIn + radiusIn).toFloat())
CircleShader.angle1 = angle1 - Math.PI.toFloat()
CircleShader.angle2 = angle2 - Math.PI.toFloat()

GlStateManager.pushMatrix()
ShaderManager.enableShader(ShaderManager.Shaders.CIRCLE)

Gui.drawRect(x - 5, y - 5, x + radius * 2 + 5, y + radius * 2 + 5, color.rgb)

ShaderManager.disableShader()
GlStateManager.popMatrix()
}

fun getAlpha(): Float {
colorBuffer.clear()
GlStateManager.getFloat(GL11.GL_CURRENT_COLOR, colorBuffer)
Expand Down
82 changes: 13 additions & 69 deletions src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import at.hannibal2.skyhanni.utils.NeuItems.renderOnScreen
import at.hannibal2.skyhanni.utils.RenderUtils
import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment
import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment
import at.hannibal2.skyhanni.utils.RenderUtils.drawFilledCircle
import at.hannibal2.skyhanni.utils.compat.getTooltipCompat
import at.hannibal2.skyhanni.utils.guide.GuideGUI
import at.hannibal2.skyhanni.utils.renderables.Renderable.Companion.shouldAllowLink
Expand All @@ -46,9 +47,7 @@ import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11
import java.awt.Color
import java.util.Collections
import kotlin.math.cos
import kotlin.math.max
import kotlin.math.sin

interface Renderable {

Expand Down Expand Up @@ -1701,90 +1700,35 @@ interface Renderable {
private val unfilledColor: Color = Color.LIGHT_GRAY,
) : Renderable {
private val totalRadius: Int = max(radius, border?.totalRadius ?: 0)
private val diffRadius: Int = totalRadius - radius

companion object {
// How many segments to use when drawing the circle.
private const val SEGMENT_COUNT: Int = 1000
}

override val width: Int = totalRadius * 2
override val height: Int = totalRadius * 2
override val width: Int = radius * 2
override val height: Int = radius * 2
override val horizontalAlign = HorizontalAlignment.LEFT
override val verticalAlign = VerticalAlignment.TOP

override fun render(posX: Int, posY: Int) {
border?.render(posX, posY)

GlStateManager.pushMatrix()
GlStateManager.translate(posX.toFloat(), posY.toFloat(), 0f)
if (filledPercentage < 100.0) {
val baseAngle = Math.PI.toFloat() * 3f / 2f
val endAngle = (baseAngle + ((100.0 - filledPercentage) / 50.0 * Math.PI).toFloat()).mod(2f * Math.PI.toFloat())
drawFilledCircle(diffRadius, diffRadius, radius, backgroundColor, angle1 = baseAngle, angle2 = endAngle)
drawFilledCircle(diffRadius, diffRadius, radius, unfilledColor, angle1 = endAngle, angle2 = baseAngle)
} else {
drawFilledCircle(diffRadius, diffRadius, radius, backgroundColor)
}

drawFilledCircle(totalRadius, totalRadius, radius, backgroundColor)

itemStack?.let { stack ->
val itemWidth = (15.5 * itemScale).toInt()
val itemHeight = (15.5 * itemScale).toInt()
val itemX = totalRadius - itemWidth / 2
val itemY = totalRadius - itemHeight / 2

GL11.glPushMatrix()
// Translate so that (0,0) is where the item should be rendered.
GL11.glTranslatef(itemX.toFloat(), itemY.toFloat(), 0f)
stack.renderOnScreen(0f, 0f, scaleMultiplier = itemScale, rescaleSkulls = true)
GL11.glPopMatrix()
stack.renderOnScreen(itemX.toFloat(), itemY.toFloat(), scaleMultiplier = itemScale, rescaleSkulls = true)
}

GL11.glPopMatrix()
}

/**
* Draws a filled circle using OpenGL.
*
* @param cx The x-coordinate of the circle's center.
* @param cy The y-coordinate of the circle's center.
* @param radius The circle's radius.
* @param color The fill color.
*/
private fun drawFilledCircle(cx: Int, cy: Int, radius: Int, color: Color) {
GlStateManager.disableCull()
GlStateManager.pushMatrix()
GlStateManager.disableTexture2D()
GlStateManager.enableBlend()
GlStateManager.tryBlendFuncSeparate(
GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO
)
GlStateManager.color(
color.red / 255f,
color.green / 255f,
color.blue / 255f,
color.alpha / 255f
)
var doneFilling = false
val fillSegmentCount = (filledPercentage / 100.0 * SEGMENT_COUNT).toInt()
GL11.glEnable(GL11.GL_POLYGON_SMOOTH)
GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_NICEST)
GL11.glBegin(GL11.GL_TRIANGLE_FAN)
GL11.glVertex2f(cx.toFloat(), cy.toFloat())
for (i in 0..SEGMENT_COUNT) {
val angle = (2.0 * Math.PI * i / SEGMENT_COUNT).toFloat()
val x = cx + cos(angle) * radius
val y = cy + sin(angle) * radius
GL11.glVertex2f(x.toFloat(), y.toFloat())
if (i != SEGMENT_COUNT && i == fillSegmentCount && !doneFilling) {
doneFilling = true
GlStateManager.color(
unfilledColor.red / 255f,
unfilledColor.green / 255f,
unfilledColor.blue / 255f,
unfilledColor.alpha / 255f
)
}
}
GL11.glDisable(GL11.GL_POLYGON_SMOOTH)
GL11.glEnd()
GlStateManager.disableBlend()
GlStateManager.enableTexture2D()
GlStateManager.popMatrix()
GlStateManager.enableCull()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import at.hannibal2.skyhanni.features.misc.DarkenShader
import at.hannibal2.skyhanni.features.misc.RoundedRectangleOutlineShader
import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader
import at.hannibal2.skyhanni.features.misc.RoundedTextureShader
import at.hannibal2.skyhanni.shader.CircleShader
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.LorenzUtils
import net.minecraft.client.Minecraft
Expand All @@ -30,7 +31,8 @@ object ShaderManager {
ROUNDED_RECTANGLE(RoundedRectangleShader.INSTANCE),
ROUNDED_RECT_OUTLINE(RoundedRectangleOutlineShader.INSTANCE),
ROUNDED_TEXTURE(RoundedTextureShader.INSTANCE),
DARKEN(DarkenShader.INSTANCE)
DARKEN(DarkenShader.INSTANCE),
CIRCLE(CircleShader.INSTANCE),
;

fun enableShader() = enableShader(this)
Expand Down
43 changes: 43 additions & 0 deletions src/main/resources/assets/skyhanni/shaders/circle.fsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#version 120

const float pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062f;

uniform float scaleFactor;
uniform float radius;
uniform float smoothness;
uniform vec2 centerPos;
uniform float angle1;
uniform float angle2;

varying vec4 color;

void main() {
float xScale = gl_ModelViewMatrix[0][0];
float yScale = gl_ModelViewMatrix[1][1];
float xTranslation = gl_ModelViewMatrix[3][0];
float yTranslation = gl_ModelViewMatrix[3][1];

vec2 cords = vec2(gl_FragCoord.x, gl_FragCoord.y);

vec2 newCenterPos = vec2((centerPos.x + (radius * (xScale - 1.0))) + (xTranslation * scaleFactor), (centerPos.y - (radius * (yScale - 1.0))) - (yTranslation * scaleFactor));

float newRadius = radius * min(xScale,yScale);

vec2 adjusted = cords - newCenterPos;

float smoothed = 1.0 - smoothstep(pow(newRadius - smoothness,2.0), pow(newRadius,2.0), pow(adjusted.x, 2.0) + pow(adjusted.y, 2.0));

float current = atan(adjusted.y,adjusted.x);

float sanity = step(angle1,angle2);

float lim1 = step(current,angle1);
float lim2 = step(angle2,current);

float lim3 = step(angle1,current);
float lim4 = step(current,angle2);

float lim = max(lim1,lim2)*sanity+(1.0-sanity)*(1.0-max(lim3,lim4));

gl_FragColor = color * vec4(1.0, 1.0, 1.0, smoothed*lim);
}
8 changes: 8 additions & 0 deletions src/main/resources/assets/skyhanni/shaders/circle.vsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#version 120

varying vec4 color;

void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
color = gl_Color;
}

0 comments on commit 48c5086

Please sign in to comment.