Skip to content

Commit c5687fb

Browse files
committed
Color pickle
1 parent 4fd271d commit c5687fb

File tree

15 files changed

+263
-53
lines changed

15 files changed

+263
-53
lines changed

common/src/main/kotlin/com/lambda/graphics/renderer/gui/TextureRenderer.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ import org.lwjgl.glfw.GLFW.glfwGetTime
3333
object TextureRenderer {
3434
private val pipeline = VertexPipeline(VertexMode.TRIANGLES, VertexAttrib.Group.POS_UV)
3535

36-
private val mainShader = shader("renderer/pos_tex")
37-
private val coloredShader = shader("renderer/pos_tex_shady")
36+
private val mainShader = shader("pos_tex")
37+
private val coloredShader = shader("pos_tex_shady")
3838

3939
fun drawTexture(texture: Texture, rect: Rect) {
4040
texture.bind()
@@ -57,7 +57,7 @@ object TextureRenderer {
5757
drawInternal(rect)
5858
}
5959

60-
private fun drawInternal(rect: Rect) {
60+
fun drawInternal(rect: Rect) {
6161
val pos1 = rect.leftTop
6262
val pos2 = rect.rightBottom
6363

@@ -72,8 +72,6 @@ object TextureRenderer {
7272
)
7373
}
7474

75-
pipeline.upload()
76-
pipeline.render()
77-
pipeline.clear()
75+
pipeline.immediateDraw()
7876
}
7977
}

common/src/main/kotlin/com/lambda/graphics/shader/ShaderUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ object ShaderUtils {
4444
.append("Failed to compile ${type.name} shader").appendLine()
4545
.append("Compiler output:").appendLine()
4646
.append(err)
47+
.appendLine().appendLine("CODE:")
48+
.append(text)
4749

4850
throw RuntimeException(builder.toString())
4951
}

common/src/main/kotlin/com/lambda/gui/GuiManager.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ import com.lambda.gui.component.core.UIBuilder
3131
import com.lambda.gui.component.layout.Layout
3232
import com.lambda.gui.impl.clickgui.module.settings.impl.BooleanButton.Companion.booleanSetting
3333
import com.lambda.gui.impl.clickgui.module.settings.impl.ColorPicker.Companion.colorPicker
34-
import com.lambda.gui.impl.clickgui.module.settings.impl.EnumSlider
3534
import com.lambda.gui.impl.clickgui.module.settings.impl.EnumSlider.Companion.enumSetting
3635
import com.lambda.gui.impl.clickgui.module.settings.impl.KeybindPicker.Companion.keybindSetting
37-
import com.lambda.gui.impl.clickgui.module.settings.impl.NumberSlider.Companion.numericSetting
36+
import com.lambda.gui.impl.clickgui.module.settings.impl.NumberSlider.Companion.numberSlider
3837
import com.lambda.gui.impl.clickgui.module.settings.impl.UnitButton.Companion.unitButton
3938
import kotlin.reflect.KClass
40-
import kotlin.reflect.KMutableProperty0
4139

4240
object GuiManager : Loadable {
4341
val typeMap = mutableMapOf<KClass<*>, (owner: Layout, converted: Any) -> Layout>()
@@ -66,7 +64,7 @@ object GuiManager : Loadable {
6664
}
6765

6866
typeAdapter<DoubleSetting> { owner, ref ->
69-
owner.numericSetting(
67+
owner.numberSlider(
7068
ref.name, ref.unit,
7169
ref.range.start, ref.range.endInclusive, ref.step,
7270
ref::value
@@ -76,7 +74,7 @@ object GuiManager : Loadable {
7674
}
7775

7876
typeAdapter<FloatSetting> { owner, ref ->
79-
owner.numericSetting(
77+
owner.numberSlider(
8078
ref.name, ref.unit,
8179
ref.range.start, ref.range.endInclusive, ref.step,
8280
ref::value
@@ -86,7 +84,7 @@ object GuiManager : Loadable {
8684
}
8785

8886
typeAdapter<IntegerSetting> { owner, ref ->
89-
owner.numericSetting(
87+
owner.numberSlider(
9088
ref.name, ref.unit,
9189
ref.range.start, ref.range.endInclusive, ref.step,
9290
ref::value
@@ -96,7 +94,7 @@ object GuiManager : Loadable {
9694
}
9795

9896
typeAdapter<LongSetting> { owner, ref ->
99-
owner.numericSetting(
97+
owner.numberSlider(
10098
ref.name, ref.unit,
10199
ref.range.start, ref.range.endInclusive, ref.step,
102100
ref::value

common/src/main/kotlin/com/lambda/gui/impl/clickgui/core/AnimatedChild.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.lambda.graphics.animation.Animation.Companion.exp
2121
import com.lambda.gui.component.HAlign
2222
import com.lambda.gui.component.layout.Layout
2323
import com.lambda.gui.component.window.Window
24+
import com.lambda.gui.impl.clickgui.module.ModuleLayout
2425
import com.lambda.gui.impl.clickgui.module.settings.SettingLayout
2526
import com.lambda.module.modules.client.ClickGui
2627
import com.lambda.util.math.MathUtils.toInt
@@ -107,6 +108,26 @@ abstract class AnimatedChild(
107108
if (isHovered) lastHover = System.currentTimeMillis()
108109
}
109110

111+
onWindowExpand {
112+
if (ClickGui.multipleSettingWindows) return@onWindowExpand
113+
114+
val close = if (this !is ModuleLayout) {
115+
owner.children.filterIsInstance<AnimatedChild>()
116+
} else {
117+
val base = owner // window content
118+
.owner // window
119+
?.owner // environment with windows
120+
121+
base?.children?.filterIsInstance<Window>()?.flatMap { window ->
122+
window.content.children.filterIsInstance<AnimatedChild>()
123+
} ?: mutableListOf()
124+
}
125+
126+
close.forEach {
127+
if (it != this) it.isMinimized = true
128+
}
129+
}
130+
110131
titleBar.textField.use {
111132
textHAlignment = HAlign.LEFT
112133

common/src/main/kotlin/com/lambda/gui/impl/clickgui/module/ModuleLayout.kt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -137,21 +137,6 @@ class ModuleLayout(
137137
cursorController.setCursor(cursor)
138138
}
139139

140-
onWindowExpand {
141-
if (ClickGui.multipleSettingWindows) return@onWindowExpand
142-
143-
val base = owner // window content
144-
.owner // window
145-
?.owner // environment with windows
146-
?: return@onWindowExpand
147-
148-
base.children.filterIsInstance<ModuleWindow>().forEach { window ->
149-
window.content.children.filterIsInstance<ModuleLayout>().forEach { module ->
150-
if (module != this) module.isMinimized = true
151-
}
152-
}
153-
}
154-
155140
val settings = module.settings.mapNotNull { setting ->
156141
content.layoutOf(setting)
157142
}.map { it as SettingLayout<*> }.onEach {

common/src/main/kotlin/com/lambda/gui/impl/clickgui/module/settings/SettingLayout.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import kotlin.reflect.KMutableProperty0
3131
abstract class SettingLayout <V : Any> (
3232
owner: Layout,
3333
name: String,
34-
field: KMutableProperty0<V>,
34+
private val property: KMutableProperty0<V>,
3535
expandable: Boolean = false
3636
) : AnimatedChild(
3737
owner,
@@ -44,7 +44,14 @@ abstract class SettingLayout <V : Any> (
4444
) {
4545
protected val cursorController = cursorController()
4646

47-
protected var settingDelegate by field
47+
protected var settingDelegate: V
48+
get() = property.get()
49+
set(value) {
50+
if (property.get() == value) return
51+
property.set(value)
52+
onValueSet.forEach { it(value) }
53+
}
54+
4855
private var onValueSet = mutableListOf<(V) -> Unit>()
4956
private var getVisibilityBlock = { true }
5057
val isVisible get() = getVisibilityBlock()
@@ -55,7 +62,7 @@ abstract class SettingLayout <V : Any> (
5562
}
5663

5764
@LayoutBuilder
58-
fun valueSet(action: (V) -> Unit) {
65+
fun onValueSet(action: (V) -> Unit) {
5966
onValueSet += action
6067
}
6168

common/src/main/kotlin/com/lambda/gui/impl/clickgui/module/settings/impl/ColorPicker.kt

Lines changed: 152 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,176 @@
1717

1818
package com.lambda.gui.impl.clickgui.module.settings.impl
1919

20+
import com.lambda.graphics.renderer.gui.TextureRenderer
21+
import com.lambda.graphics.shader.Shader.Companion.shader
22+
import com.lambda.gui.component.core.FilledRect.Companion.rect
23+
import com.lambda.gui.component.core.OutlineRect.Companion.outline
2024
import com.lambda.gui.component.core.UIBuilder
2125
import com.lambda.gui.component.layout.Layout
22-
import com.lambda.gui.component.popup.Popup
2326
import com.lambda.gui.impl.clickgui.module.settings.SettingLayout
27+
import com.lambda.gui.impl.clickgui.module.settings.impl.NumberSlider.Companion.numberSlider
28+
import com.lambda.module.modules.client.ClickGui
2429
import com.lambda.util.Mouse
30+
import com.lambda.util.StringUtils.capitalize
31+
import com.lambda.util.math.MathUtils.toDegree
32+
import com.lambda.util.math.MathUtils.toRadian
33+
import com.lambda.util.math.Vec2d
34+
import com.lambda.util.math.a
35+
import com.lambda.util.math.lerp
36+
import com.lambda.util.math.multAlpha
37+
import com.lambda.util.math.setAlpha
38+
import com.lambda.util.math.transform
39+
import net.minecraft.util.math.Vec3d
2540
import java.awt.Color
41+
import kotlin.math.atan2
42+
import kotlin.math.cos
43+
import kotlin.math.hypot
44+
import kotlin.math.sin
45+
import kotlin.math.sqrt
2646
import kotlin.reflect.KMutableProperty0
2747

2848
class ColorPicker(
2949
owner: Layout,
3050
name: String,
3151
field: KMutableProperty0<Color>,
32-
) : SettingLayout<Color>(owner, name, field) {
33-
private val popup = Popup(this, name).apply {
34-
window.use {
35-
windowWidth = 200.0
36-
windowHeight = 100.0
37-
}
52+
) : SettingLayout<Color>(owner, name, field, true) {
53+
54+
private var hsb get() = Color.RGBtoHSB(settingDelegate.red, settingDelegate.green, settingDelegate.blue, null).let {
55+
Vec3d(it[0].toDouble(), it[1].toDouble(), it[2].toDouble())
56+
}; set(value) {
57+
settingDelegate = Color(Color.HSBtoRGB(value.x.toFloat(), value.y.toFloat(), value.z.toFloat())).setAlpha(alpha)
58+
}
59+
60+
private var hue get() = hsb.x; set(value) {
61+
val cache = hsb
62+
if (cache.x == value) return
63+
hsb = Vec3d(value, cache.y, cache.z)
64+
}
65+
66+
private var saturation get() = hsb.y; set(value) {
67+
val cache = hsb
68+
if (cache.y == value) return
69+
hsb = Vec3d(cache.x, value, cache.z)
70+
}
71+
72+
private var brightness get() = hsb.z; set(value) {
73+
val cache = hsb
74+
if (cache.z == value) return
75+
hsb = Vec3d(cache.x, cache.y, value)
76+
}
77+
78+
private var alpha get() = settingDelegate.a; set(value) {
79+
settingDelegate = settingDelegate.setAlpha(value)
3880
}
3981

4082
init {
41-
onMouseAction(Mouse.Button.Left) {
42-
popup.show()
83+
rect {
84+
val shrink = 3.0
85+
86+
onUpdate {
87+
rect = titleBar.rect
88+
.moveFirst(Vec2d.RIGHT * (titleBar.width - titleBar.height))
89+
.shrink(shrink + (1.0 - showAnimation)) +
90+
Vec2d.RIGHT * lerp(showAnimation, 5.0, -ClickGui.fontOffset + shrink)
91+
92+
setColor(settingDelegate.multAlpha(showAnimation))
93+
setRadius(100.0)
94+
}
95+
}
96+
97+
content.layout {
98+
val getU = { transform(mousePosition.x, positionX, positionX + width, 0.0, 1.0) }
99+
val getV = { transform(mousePosition.y, positionY, positionY + height, 0.0, 1.0) }
100+
101+
onUpdate {
102+
width = content.width * 0.5
103+
positionX = content.positionX + (content.width - width) * 0.5
104+
height = width
105+
}
106+
107+
onRender {
108+
hueCircleShader.use()
109+
TextureRenderer.drawInternal(rect)
110+
}
111+
112+
onMouseMove {
113+
if (pressedButton != Mouse.Button.Left) return@onMouseMove
114+
115+
val (u, v) = getU() to getV()
116+
hue = uvToHue(u, v).div(360.0).coerceIn(0.0, 1.0)
117+
saturation = hypot(u - 0.5, v - 0.5).coerceIn(0.0, 0.5) * 2
118+
}
119+
120+
val circle = this
121+
val knobSize = 2.0
122+
123+
outline {
124+
width = knobSize; height = knobSize
125+
126+
setColor(Color.BLACK)
127+
glowRadius = 1.0
128+
roundRadius = 100.0
129+
130+
onUpdate {
131+
val uv = if (circle.pressedButton == Mouse.Button.Left) clampToCircle(Vec2d(getU(), getV()))
132+
else hueToUv(hue * 360, saturation)
133+
134+
positionX = transform(uv.x, 0.0, 1.0, circle.positionX, circle.positionX + circle.width) - knobSize * 0.5
135+
positionY = transform(uv.y, 0.0, 1.0, circle.positionY, circle.positionY + circle.height) - knobSize * 0.5
136+
}
137+
}
138+
}
139+
140+
listOf(::brightness, ::alpha).map {
141+
content.numberSlider(it.name.capitalize(), "", 0.0, 1.0, 0.01, it).apply {
142+
forceRoundDisplayValue = true
143+
}
144+
}.onEach {
145+
it.onUpdate {
146+
width = this@ColorPicker.content.width
147+
}
43148
}
149+
150+
content.listify()
44151
}
45152

46153
companion object {
154+
private val hueCircleShader = shader("renderer/hue_circle")
155+
156+
private fun uvToHue(u: Double, v: Double): Double {
157+
val x = (u - 0.5) * 2.0
158+
val y = ((1.0 - v) - 0.5) * -2.0
159+
160+
var hue = atan2(y, x).toDegree() + 90.0
161+
if (hue < 0) hue += 360.0
162+
return hue
163+
}
164+
165+
private fun hueToUv(hue: Double, radius: Double): Vec2d {
166+
val angle = (hue - 90.0).toRadian()
167+
168+
val x = cos(angle) * radius
169+
val y = sin(angle) * radius
170+
171+
val u = (x * 0.5f) + 0.5f
172+
val v = (y * -0.5f) + 0.5f
173+
174+
return Vec2d(u, 1.0 - v)
175+
}
176+
177+
private fun clampToCircle(uv: Vec2d): Vec2d {
178+
val center = Vec2d(0.5f, 0.5f)
179+
val radius = 0.5f
180+
val dx = uv.x- center.x
181+
val dy = uv.y - center.y
182+
val dist = sqrt(dx * dx + dy * dy)
183+
184+
return if (dist > radius) {
185+
val scale = radius / dist
186+
Vec2d(center.x + dx * scale, center.y + dy * scale)
187+
} else uv
188+
}
189+
47190
/**
48191
* Creates a [ColorPicker]
49192
*/

common/src/main/kotlin/com/lambda/gui/impl/clickgui/module/settings/impl/NumberSlider.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,15 @@ class NumberSlider <V> (
3333
minV: V, maxV: V, stepV: V,
3434
field: KMutableProperty0<V>
3535
) : SettingSlider<V>(owner, name, field) where V : Number, V : Comparable<V> {
36-
private val min = minV.toDouble()
37-
private val max = maxV.toDouble()
38-
private val step = stepV.toDouble()
36+
var min = minV.toDouble()
37+
var max = maxV.toDouble()
38+
var step = stepV.toDouble()
39+
var forceRoundDisplayValue = false
3940

4041
override val settingValue: String
41-
get() = "${settingDelegate}${unit}"
42+
get() = "${settingDelegate.let {
43+
if (forceRoundDisplayValue) it.roundToStep(step) else it
44+
}}${unit}"
4245

4346
init {
4447
slider.progress {
@@ -61,7 +64,7 @@ class NumberSlider <V> (
6164
* Creates an [NumberSlider] - visual representation of the [NumericSetting]
6265
*/
6366
@UIBuilder
64-
fun <T> Layout.numericSetting(
67+
fun <T> Layout.numberSlider(
6568
name: String, unit: String,
6669
minV: T, maxV: T, stepV: T,
6770
field: KMutableProperty0<T>

0 commit comments

Comments
 (0)