diff --git a/core/assets-raw/sprites/ui/alpha-bg-line.png b/core/assets-raw/sprites/ui/alpha-bg-line.png new file mode 100644 index 0000000000..02becdcf15 Binary files /dev/null and b/core/assets-raw/sprites/ui/alpha-bg-line.png differ diff --git a/core/assets-raw/sprites/ui/slider-back.9.png b/core/assets-raw/sprites/ui/slider-back.9.png index 71762a2163..013c6cc7bd 100644 Binary files a/core/assets-raw/sprites/ui/slider-back.9.png and b/core/assets-raw/sprites/ui/slider-back.9.png differ diff --git a/core/src/mindustry/ui/dialogs/ColorPicker.java b/core/src/mindustry/ui/dialogs/ColorPicker.java index 80c042e1eb..7f15970bc8 100644 --- a/core/src/mindustry/ui/dialogs/ColorPicker.java +++ b/core/src/mindustry/ui/dialogs/ColorPicker.java @@ -2,13 +2,21 @@ package mindustry.ui.dialogs; import arc.func.*; import arc.graphics.*; +import arc.graphics.Texture.*; +import arc.graphics.g2d.*; +import arc.scene.*; import arc.scene.ui.*; +import arc.util.*; import mindustry.gen.*; -import mindustry.graphics.*; public class ColorPicker extends BaseDialog{ + private static Texture hueTex; + private Cons cons = c -> {}; Color current = new Color(); + float h, s, v, a; + TextField hexField; + Slider hSlider, sSlider, vSlider, aSlider; public ColorPicker(){ super("@pickcolor"); @@ -23,6 +31,17 @@ public class ColorPicker extends BaseDialog{ this.cons = consumer; show(); + if(hueTex == null){ + hueTex = Pixmaps.hueTexture(128, 1); + hueTex.setFilter(TextureFilter.linear); + } + + float[] values = color.toHsv(new float[3]); + h = values[0]; + s = values[1]; + v = values[2]; + a = color.a; + cont.clear(); cont.pane(t -> { t.table(Tex.pane, i -> { @@ -32,25 +51,113 @@ public class ColorPicker extends BaseDialog{ }}).size(200f); }).colspan(2).padBottom(5); - float w = 150f; - t.row(); - t.defaults().padBottom(4); - t.add("R").color(Pal.remove); - t.slider(0f, 1f, 0.01f, current.r, current::r).width(w); - t.row(); - t.add("G").color(Color.lime); - t.slider(0f, 1f, 0.01f, current.g, current::g).width(w); - t.row(); - t.add("B").color(Color.royal); - t.slider(0f, 1f, 0.01f, current.b, current::b).width(w); - t.row(); + t.defaults().padBottom(6).width(400f).height(44f); + + t.stack(new Image(new TextureRegion(hueTex)), hSlider = new Slider(0f, 360f, 0.3f, false){{ + setValue(h); + moved(value -> { + h = value; + updateColor(); + }); + }}).row(); + + t.stack(new Element(){ + @Override + public void draw(){ + float first = Tmp.c1.set(current).saturation(0f).a(parentAlpha).toFloatBits(); + float second = Tmp.c1.set(current).saturation(1f).a(parentAlpha).toFloatBits(); + + Fill.quad( + x, y, first, + x + width, y, second, + x + width, y + height, second, + x, y + height, first + ); + } + }, sSlider = new Slider(0f, 1f, 0.001f, false){{ + setValue(s); + moved(value -> { + s = value; + updateColor(); + }); + }}).row(); + + t.stack(new Element(){ + @Override + public void draw(){ + float first = Tmp.c1.set(current).value(0f).a(parentAlpha).toFloatBits(); + float second = Tmp.c1.fromHsv(h, s, 1f).a(parentAlpha).toFloatBits(); + + Fill.quad( + x, y, first, + x + width, y, second, + x + width, y + height, second, + x, y + height, first + ); + } + }, vSlider = new Slider(0f, 1f, 0.001f, false){{ + setValue(v); + + moved(value -> { + v = value; + updateColor(); + }); + }}).row(); + if(alpha){ - t.add("A"); - t.slider(0f, 1f, 0.01f, current.a, current::a).width(w); - t.row(); + t.stack(new Image(Tex.alphaBgLine), new Element(){ + @Override + public void draw(){ + float first = Tmp.c1.set(current).a(0f).toFloatBits(); + float second = Tmp.c1.set(current).a(parentAlpha).toFloatBits(); + + Fill.quad( + x, y, first, + x + width, y, second, + x + width, y + height, second, + x, y + height, first + ); + } + }, aSlider = new Slider(0f, 1f, 0.001f, false){{ + setValue(a); + + moved(value -> { + a = value; + updateColor(); + }); + }}).row(); } + + hexField = t.field(current.toString(), value -> { + try{ + current.set(Color.valueOf(value).a(a)); + current.toHsv(values); + h = values[0]; + s = values[1]; + v = values[2]; + a = current.a; + + hSlider.setValue(h); + sSlider.setValue(s); + vSlider.setValue(v); + if(aSlider != null){ + aSlider.setValue(a); + } + + updateColor(false); + }catch(Exception ignored){ + } + }).size(130f, 40f).valid(text -> { + //garbage performance but who cares this runs only every key type anyway + try{ + Color.valueOf(text); + return true; + }catch(Exception e){ + return false; + } + }).get(); }); buttons.clear(); @@ -60,4 +167,21 @@ public class ColorPicker extends BaseDialog{ hide(); }); } + + void updateColor(){ + updateColor(true); + } + + void updateColor(boolean updateField){ + current.fromHsv(h, s, v); + current.a = a; + + if(hexField != null && updateField){ + String val = current.toString(); + if(current.a >= 0.9999f){ + val = val.substring(0, 6); + } + hexField.setText(val); + } + } } diff --git a/gradle.properties b/gradle.properties index 77ed3793fc..b3da1e740d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ org.gradle.caching=true #used for slow jitpack builds; TODO see if this actually works org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 -archash=b1b88883e2 +archash=47925a7b91