nice circle :)
This commit is contained in:
parent
dc2b06f051
commit
3bc442f8c7
8 changed files with 285 additions and 33 deletions
120
colorpicker.wren
120
colorpicker.wren
|
|
@ -1,7 +1,9 @@
|
||||||
import "luxe: world" for Entity, UIClear
|
import "luxe: world" for Entity, UIClear, UILayoutMode, UIBehave, UIContain, Assets, Material, UI, UIEvent
|
||||||
import "luxe: ui/control" for Control
|
import "luxe: ui" for Control, UIList, UIWindow, UIButton, UIPanel, UIImage
|
||||||
import "luxe: ui/list" for UIList
|
import "luxe: id" for ID
|
||||||
import "luxe: ui/button" for UIButton
|
import "luxe: draw" for PathStyle
|
||||||
|
import "luxe: math" for Math
|
||||||
|
import "luxe: color" for Color
|
||||||
|
|
||||||
var Color_spaces = [
|
var Color_spaces = [
|
||||||
{
|
{
|
||||||
|
|
@ -38,15 +40,117 @@ var Modes = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Circle",
|
"name": "Circle",
|
||||||
"icon": "round" //●
|
"icon": "round", //●
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
class ColorPicker{
|
class ColorPicker{
|
||||||
static create(ui: Entity) : Control{
|
static create(ui: Entity) : Control{
|
||||||
//setup root
|
//setup root
|
||||||
var root = Control.create(ui)
|
var panel = UIWindow.create(ui)
|
||||||
Control.set_size(root, 350, 400)
|
Control.set_size(panel, 350, 400)
|
||||||
|
Control.set_id(panel, "panel.%(ID.unique())")
|
||||||
|
Control.set_state_data(panel, [1, 0, 0, 1])
|
||||||
|
|
||||||
|
var color_view = Control.create(ui)
|
||||||
|
Control.set_behave(color_view, UIBehave.fill)
|
||||||
|
Control.set_margin(color_view, 0, 40, 0, 0)
|
||||||
|
Control.child_add(panel, color_view)
|
||||||
|
Control.set_id(panel, "color_view.%(ID.unique())")
|
||||||
|
|
||||||
|
var color_wheel = Control.create(ui)
|
||||||
|
Control.set_size(color_wheel, 200, 200)
|
||||||
|
Control.child_add(color_view, color_wheel)
|
||||||
|
Control.set_state_data(color_wheel, {"ring":null, "triangle":null, "hue": 0})
|
||||||
|
Control.set_process(color_wheel){|control, state, event, x,y,w,h|
|
||||||
|
if(event.control != control) return
|
||||||
|
if(event.type == UIEvent.move){
|
||||||
|
x = Control.get_pos_x_abs(control)
|
||||||
|
y = Control.get_pos_y_abs(control)
|
||||||
|
var center = [x + w/2, y + h/2]
|
||||||
|
if(state["ring"] == "captured"){
|
||||||
|
var diff = [event.x - center.x, event.y - center.y]
|
||||||
|
var angle = Math.atan2(-diff.x, diff.y) + Num.pi
|
||||||
|
var hue = angle / Num.tau
|
||||||
|
|
||||||
|
var color = Control.get_state_data(panel)
|
||||||
|
var hsv = Color.rgb2hsv(color)
|
||||||
|
hsv[0] = hue
|
||||||
|
state["hue"] = hue
|
||||||
|
color = Color.hsv2rgb(hsv)
|
||||||
|
Control.set_state_data(panel, color)
|
||||||
|
UI.events_emit(control, UIEvent.change, state)
|
||||||
|
UI.events_emit(panel, UIEvent.change, color)
|
||||||
|
} else {
|
||||||
|
var distance = Math.dist2D(center, event)
|
||||||
|
if(distance > 70 && distance < 100){
|
||||||
|
state["ring"] = "hover"
|
||||||
|
} else {
|
||||||
|
state["ring"] = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(event.type == UIEvent.press && event.button == 1) {
|
||||||
|
if(!state["ring"]) return
|
||||||
|
state["ring"] = "captured"
|
||||||
|
UI.capture(control)
|
||||||
|
} else if(event.type == UIEvent.release && event.button == 1) {
|
||||||
|
state["ring"] = null
|
||||||
|
UI.uncapture(control)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Control.set_allow_input(color_wheel, true)
|
||||||
|
|
||||||
|
var color_ring = UIImage.create(ui)
|
||||||
|
Control.set_size(color_ring, 200, 200)
|
||||||
|
Control.set_contain(color_ring, UIContain.justify)
|
||||||
|
var color_ring_mat = Material.create("materials/color_ring")
|
||||||
|
UIImage.set_material(color_ring, color_ring_mat)
|
||||||
|
Control.child_add(color_wheel, color_ring)
|
||||||
|
|
||||||
|
var color_triangle = UIImage.create(ui)
|
||||||
|
Control.set_margin(color_triangle, 30, 30, 0, 0)
|
||||||
|
Control.set_size(color_triangle, 140, 140)
|
||||||
|
Control.set_contain(color_triangle, UIContain.justify)
|
||||||
|
var color_tri_mat = Material.create("materials/color_triangle")
|
||||||
|
UIImage.set_material(color_triangle, color_tri_mat)
|
||||||
|
Control.child_add(color_wheel, color_triangle)
|
||||||
|
Control.set_events(color_wheel) {|event|
|
||||||
|
if(event.type == UIEvent.change){
|
||||||
|
var hue = event.change["hue"]
|
||||||
|
UIImage.set_angle(color_triangle, hue * -360)
|
||||||
|
Material.set_input(color_tri_mat, "triangle.hue", hue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var color_wheel_overlay = Control.create(ui)
|
||||||
|
Control.set_behave(color_wheel_overlay, UIBehave.fill)
|
||||||
|
Control.set_margin(color_wheel_overlay, 0, 0, 0, 0)
|
||||||
|
Control.set_render(color_wheel_overlay){|control, state, x, y, w, h|
|
||||||
|
var depth = UI.draw_depth_of(control, 0)
|
||||||
|
var center = [x + w/2, y + h/2]
|
||||||
|
var style: PathStyle = PathStyle.new()
|
||||||
|
var wheel_state = Control.get_state_data(color_wheel)
|
||||||
|
var hover = wheel_state["ring"]
|
||||||
|
|
||||||
|
var hue = wheel_state["hue"]
|
||||||
|
var angle = hue * Num.tau
|
||||||
|
var direction = [angle.sin, -angle.cos]
|
||||||
|
style.thickness = 4
|
||||||
|
style.color = hover ? [0.5,0.5,0.5,1] : [0.22,0.22,0.22,1]
|
||||||
|
var from = [center.x + direction.x * 70, center.y + direction.y * 70]
|
||||||
|
var to = [center.x + direction.x * 100, center.y + direction.y * 100]
|
||||||
|
UI.draw_line(control, from.x, from.y, to.x, to.y, depth, style)
|
||||||
|
|
||||||
|
style.color = [0.22,0.22,0.22,1]
|
||||||
|
style.thickness = 2
|
||||||
|
UI.draw_ring(control, center.x, center.y, depth, w/2, h/2, 0, 360, 8, style)
|
||||||
|
UI.draw_ring(control, center.x, center.y, depth, w/2*0.7, h/2*0.7, 0, 360, 8, style)
|
||||||
|
}
|
||||||
|
Control.child_add(color_wheel, color_wheel_overlay)
|
||||||
|
|
||||||
|
return panel
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
//setup colorspace buttons
|
//setup colorspace buttons
|
||||||
//todo: this should be a dropdown???
|
//todo: this should be a dropdown???
|
||||||
|
|
@ -117,6 +221,8 @@ class ColorPicker{
|
||||||
//todo
|
//todo
|
||||||
|
|
||||||
return root
|
return root
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static build_triangle_editor(ui: Entity, root: Control){
|
static build_triangle_editor(ui: Entity, root: Control){
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import "luxe: game" for Ready
|
import "luxe: game" for Ready
|
||||||
import "luxe: assets" for Assets
|
import "luxe: assets" for Assets
|
||||||
import "luxe: input" for Input, Key
|
import "luxe: input" for Input, Key
|
||||||
import "luxe: world" for World, Entity, Transform, Sprite, Values, Tags, Camera, UI
|
import "luxe: world" for World, Entity, Transform, Sprite, Values, Tags, Camera, UI, UILayoutMode
|
||||||
import "luxe: math" for Math
|
import "luxe: math" for Math
|
||||||
import "luxe: draw" for Draw
|
import "luxe: draw" for Draw
|
||||||
import "luxe: io" for IO
|
import "luxe: io" for IO
|
||||||
|
|
@ -28,6 +28,7 @@ class Game is Ready {
|
||||||
|
|
||||||
var ui = Entity.create(app.ui, "ui")
|
var ui = Entity.create(app.ui, "ui")
|
||||||
UI.create(ui, 0, 0, app.width, app.height, 0, app.ui_camera)
|
UI.create(ui, 0, 0, app.width, app.height, 0, app.ui_camera)
|
||||||
|
UI.set_layout_mode(ui, UILayoutMode.flex)
|
||||||
var picker = ColorPicker.create(ui)
|
var picker = ColorPicker.create(ui)
|
||||||
Control.set_pos(picker, 100, 100)
|
Control.set_pos(picker, 100, 100)
|
||||||
} //ready
|
} //ready
|
||||||
|
|
|
||||||
33
materials/color_ring.material_basis.lx
Normal file
33
materials/color_ring.material_basis.lx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
material_basis = {
|
||||||
|
vertex_format = "luxe.textured"
|
||||||
|
shaders = {
|
||||||
|
vertex = { library="materials/shaders" function="vert" }
|
||||||
|
fragment = { library="materials/shaders" function="frag_color_ring" }
|
||||||
|
}
|
||||||
|
depth_test = true
|
||||||
|
depth_write = true
|
||||||
|
depth_compare = "less_equal"
|
||||||
|
stencil_test = false
|
||||||
|
write_mask = { red=true green=true blue=true alpha=true }
|
||||||
|
blending = true
|
||||||
|
alpha_blend = "add"
|
||||||
|
rgb_blend = "add"
|
||||||
|
src_alpha = "source_alpha"
|
||||||
|
src_rgb = "source_alpha"
|
||||||
|
dest_alpha = "one_minus_source_alpha"
|
||||||
|
dest_rgb = "one_minus_source_alpha"
|
||||||
|
blend_color = [0 0 0 0]
|
||||||
|
cull = "none"
|
||||||
|
winding = "counter_clockwise"
|
||||||
|
layers = ["default"]
|
||||||
|
inputs = {
|
||||||
|
wheel.outer_distance = {
|
||||||
|
type = "float",
|
||||||
|
value = 0.5,
|
||||||
|
},
|
||||||
|
wheel.inner_distance = {
|
||||||
|
type = "float",
|
||||||
|
value = 0.35,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
materials/color_triangle.material_basis.lx
Normal file
33
materials/color_triangle.material_basis.lx
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
material_basis = {
|
||||||
|
vertex_format = "luxe.textured"
|
||||||
|
shaders = {
|
||||||
|
vertex = { library="materials/shaders" function="vert" }
|
||||||
|
fragment = { library="materials/shaders" function="frag_color_triangle" }
|
||||||
|
}
|
||||||
|
depth_test = true
|
||||||
|
depth_write = true
|
||||||
|
depth_compare = "less_equal"
|
||||||
|
stencil_test = false
|
||||||
|
write_mask = { red=true green=true blue=true alpha=true }
|
||||||
|
blending = true
|
||||||
|
alpha_blend = "add"
|
||||||
|
rgb_blend = "add"
|
||||||
|
src_alpha = "source_alpha"
|
||||||
|
src_rgb = "source_alpha"
|
||||||
|
dest_alpha = "one_minus_source_alpha"
|
||||||
|
dest_rgb = "one_minus_source_alpha"
|
||||||
|
blend_color = [0 0 0 0]
|
||||||
|
cull = "none"
|
||||||
|
winding = "counter_clockwise"
|
||||||
|
layers = ["default"]
|
||||||
|
inputs = {
|
||||||
|
triangle.hue = {
|
||||||
|
type = "float",
|
||||||
|
value = 0.5,
|
||||||
|
},
|
||||||
|
triangle.size = {
|
||||||
|
type = "float",
|
||||||
|
value = 0.25,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
102
materials/shaders.emsl
Normal file
102
materials/shaders.emsl
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
input View {
|
||||||
|
mat4 mvp,
|
||||||
|
mat4 proj,
|
||||||
|
mat4 proj_inverse,
|
||||||
|
mat4 view,
|
||||||
|
mat4 world, //geometry.world atm
|
||||||
|
float2 fov, //fov.x, fov.y
|
||||||
|
float2 resolution,
|
||||||
|
float4 target_region,
|
||||||
|
float4 target_region_size
|
||||||
|
}
|
||||||
|
|
||||||
|
input ColorWheel {
|
||||||
|
float outer_distance,
|
||||||
|
float inner_distance
|
||||||
|
}
|
||||||
|
|
||||||
|
input ColorTriangle {
|
||||||
|
float hue,
|
||||||
|
float size
|
||||||
|
}
|
||||||
|
|
||||||
|
stage vertex vert(
|
||||||
|
input { View view },
|
||||||
|
vertex in { #0 float4 pos, #1 float4 color, #2 float2 uv },
|
||||||
|
fragment out { float4 color, float2 uv})
|
||||||
|
{
|
||||||
|
out.color = in.color;
|
||||||
|
out.uv = in.uv;
|
||||||
|
|
||||||
|
stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
stage fragment frag_color_ring(
|
||||||
|
input { ColorWheel wheel },
|
||||||
|
fragment in { float4 color, float2 uv })
|
||||||
|
{
|
||||||
|
float TAU = 6.2831853071795864769252867665590057683943387987502116419498891846;
|
||||||
|
|
||||||
|
float2 centered_coords = in.uv - 0.5;
|
||||||
|
float center_dist = length(centered_coords);
|
||||||
|
|
||||||
|
float change = dFdx(in.uv.x); //this assumes the object is unrotated and uniformly scaled
|
||||||
|
float alpha = clamp(min(center_dist - input.wheel.inner_distance, -center_dist + input.wheel.outer_distance - change) / change, 0.0, 1.0);
|
||||||
|
|
||||||
|
float angle = atan(centered_coords.y, centered_coords.x);
|
||||||
|
float normalized_angle = mod(angle / TAU + 0.25, 1.0);
|
||||||
|
float3 hue = hue2rgb(normalized_angle);
|
||||||
|
|
||||||
|
float4 color = float4(float3(hue), alpha);
|
||||||
|
|
||||||
|
if(color.a <= 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.color[0] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
stage fragment frag_color_triangle(
|
||||||
|
input { ColorTriangle triangle },
|
||||||
|
fragment in { float4 color, float2 uv })
|
||||||
|
{
|
||||||
|
float TAU = 6.2831853071795864769252867665590057683943387987502116419498891846;
|
||||||
|
float cos30 = 0.866025403784438; //cos(30°)
|
||||||
|
|
||||||
|
float2 centered_coords = in.uv - 0.5;
|
||||||
|
|
||||||
|
float2 down = float2(0.0, -1.0);
|
||||||
|
float2 top_right = float2(cos30, 0.5);
|
||||||
|
float2 top_left = float2(-cos30, 0.5);
|
||||||
|
|
||||||
|
float down_dist = dot(down, centered_coords);
|
||||||
|
float top_right_dist = dot(top_right, centered_coords);
|
||||||
|
float top_left_dist = dot(top_left, centered_coords);
|
||||||
|
float dist = min(min(top_right_dist, top_left_dist), down_dist);
|
||||||
|
dist += input.triangle.size;
|
||||||
|
|
||||||
|
float change = length(float2(dFdx(in.uv.x), dFdy(in.uv.y))); //this assumes the object is uniformly scaled
|
||||||
|
float alpha = clamp(dist/change, 0.0, 1.0);
|
||||||
|
|
||||||
|
float3 hue = hue2rgb(input.triangle.hue);
|
||||||
|
|
||||||
|
float4 color = float4(float3(hue), alpha);
|
||||||
|
|
||||||
|
if(color.a <= 0.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stage.color[0] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 hue2rgb(float hue) {
|
||||||
|
hue = fract(hue); //only use fractional part
|
||||||
|
float r = abs(hue * 6.0 - 3.0) - 1.0; //red
|
||||||
|
float g = 2.0 - abs(hue * 6.0 - 2.0); //green
|
||||||
|
float b = 2.0 - abs(hue * 6.0 - 4.0); //blue
|
||||||
|
float3 rgb = float3(r,g,b); //combine components
|
||||||
|
rgb = clamp(rgb, 0.0, 1.0); //clamp between 0 and 1
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
input = {
|
|
||||||
nodes = [
|
|
||||||
{ name = "ui" where = "front" channels = ["c01"] }
|
|
||||||
{ name = "game" where = "after: ui" channels = ["c02"] }
|
|
||||||
]
|
|
||||||
|
|
||||||
map = {
|
|
||||||
left = { keys = ["key_a", "left"] }
|
|
||||||
right = { keys = ["key_d", "right"] }
|
|
||||||
up = { keys = ["key_w", "up"] }
|
|
||||||
down = { keys = ["key_s", "down"] }
|
|
||||||
jump = {
|
|
||||||
keys = ["key_x", "up", "key_w", "space"]
|
|
||||||
mouse = ["left"]
|
|
||||||
gamepad = [0]
|
|
||||||
}
|
|
||||||
|
|
||||||
next = {
|
|
||||||
keys = ["key_x", "up", "key_w", "space", "enter", "escape"]
|
|
||||||
mouse = ["left", "right"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,5 +15,5 @@ engine = {
|
||||||
depth = 24
|
depth = 24
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.debug_vis = true
|
//ui.debug_vis = true
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
modules = {
|
modules = {
|
||||||
luxe = "2021.0.2"
|
luxe = "dev"
|
||||||
} //modules
|
} //modules
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue