Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package coffee.injected.latte.view.engine
- import coffee.injected.latte.util.Color
- import coffee.injected.latte.util.Corners
- import coffee.injected.latte.view.engine.texture.Texture
- import coffee.injected.latte.view.engine.texture.TextureStitcher
- import coffee.injected.latte.view.engine.texture.TexturedRectRenderer
- import coffee.injected.latte.view.engine.texture.VertexTessellator
- import coffee.injected.latte.view.part.RectAttributes
- import coffee.injected.latte.view.part.RectViewPart
- import java.lang.Float.min
- import kotlin.math.cos
- import kotlin.math.max
- import kotlin.math.sin
- class TessellatingRectRenderer(val tessellator: VertexTessellator) : ViewPartRenderer<RectViewPart, RectAttributes> {
- override fun render(part: RectViewPart, attributes: RectAttributes, context: ViewRenderContext) {
- val x = context.translateX + part.contentRegion.x
- val y = context.translateY + part.contentRegion.y
- val w = part.contentRegion.width
- val h = part.contentRegion.height
- val color = attributes.color.value
- val texture = attributes.texture.value
- val stitcher = if (texture != null) attributes.textureStitcher.value else TextureStitcher.ATTACH
- val corners = attributes.cornerRadius.value
- if (color.alpha > 0) {
- tessellator.setup(texture)
- val renderer = Renderer(tessellator, x, y, color, corners, texture)
- stitcher.draw(renderer, w, h, texture?.width ?: w, texture?.height ?: h)
- tessellator.end()
- }
- }
- private class Renderer(
- val tessellator: VertexTessellator,
- val rootX: Float,
- val rootY: Float,
- val color: Color,
- val corners: Corners<Float>,
- val texture: Texture?
- ) : TexturedRectRenderer {
- override fun drawRect(
- x: Float, y: Float, width: Float, height: Float, tx: Float, ty: Float, tw: Float, th: Float,
- radius1: Boolean, radius2: Boolean, radius3: Boolean, radius4: Boolean
- ) {
- val red = color.red
- val green = color.green
- val blue = color.blue
- val alpha = color.alpha
- fun vertex(cx: Float, cy: Float) {
- val u = texture?.u(tx + tw * (cx - x) / width) ?: 0f
- val v = texture?.u(ty + th * (cy - y) / height) ?: 0f
- tessellator.vertex(rootX + cx, rootY + cy, red, green, blue, alpha, u, v)
- }
- fun rect(x1: Float, y1: Float, x2: Float, y2: Float) {
- vertex(x1, y1)
- vertex(x2, y1)
- vertex(x1, y2)
- vertex(x2, y1)
- vertex(x1, y2)
- vertex(x2, y2)
- }
- fun angle(x: Float, y: Float, radius: Float, start: Int, steps: Int = 5) {
- val step = 90f / steps
- val stepRad = Math.toRadians(step.toDouble())
- var angle = Math.toRadians(start.toDouble())
- for (i in 0..steps) {
- val x1 = x + radius * cos(angle).toFloat()
- val y1 = y + radius * sin(angle).toFloat()
- vertex(x1, y1)
- if (i < steps) {
- vertex(x, y)
- if (i != 0) vertex(x1, y1)
- }
- angle += stepRad
- }
- }
- val x1 = x
- val y1 = y
- val x2 = x + width
- val y2 = y + height
- val maxRadius = min(width / 2, height / 2)
- val r1 = if (radius1) corners.topLeft.coerceAtMost(maxRadius) else 0f
- val r2 = if (radius2) corners.topRight.coerceAtMost(maxRadius) else 0f
- val r3 = if (radius3) corners.bottomRight.coerceAtMost(maxRadius) else 0f
- val r4 = if (radius4) corners.bottomLeft.coerceAtMost(maxRadius) else 0f
- val cy1 = y1 + max(r1, r2)
- val cy2 = y2 - max(r3, r4)
- // render top plate and corners
- if (r1 != 0f || r2 != 0f) {
- val cx1 = x1 + r1
- val cx2 = x2 - r2
- rect(cx1, y1, cx2, cy1)
- if (r1 != r2) {
- if (r1 > r2) rect(cx2, y1 + r2, x2, cy1)
- else rect(x1, y1 + r1, cx1, cy1)
- }
- if (r1 != 0f) angle(cx1, y1 + r1, r1, 180)
- if (r2 != 0f) angle(cx2, y1 + r2, r2, 270)
- }
- // render bottom plate and corners
- if (r3 != 0f || r4 != 0f) {
- val cx1 = x1 + r4
- val cx2 = x2 - r3
- rect(cx1, cy2, cx2, y2)
- if (r3 != r4) {
- if (r4 > r3) rect(cx2, cy2, x2, y2 - r3)
- else rect(x1, cy2, cx1, y2 - r4)
- }
- if (r4 != 0f) angle(cx1, y2 - r4, r4, 90)
- if (r3 != 0f) angle(cx2, y2 - r3, r3, 0)
- }
- //render center plate
- if (cy1 < cy2) {
- rect(x1, cy1, x2, cy2)
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement