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: ui/control" for Control
|
||||
import "luxe: ui/list" for UIList
|
||||
import "luxe: ui/button" for UIButton
|
||||
import "luxe: world" for Entity, UIClear, UILayoutMode, UIBehave, UIContain, Assets, Material, UI, UIEvent
|
||||
import "luxe: ui" for Control, UIList, UIWindow, UIButton, UIPanel, UIImage
|
||||
import "luxe: id" for ID
|
||||
import "luxe: draw" for PathStyle
|
||||
import "luxe: math" for Math
|
||||
import "luxe: color" for Color
|
||||
|
||||
var Color_spaces = [
|
||||
{
|
||||
|
|
@ -38,15 +40,117 @@ var Modes = [
|
|||
},
|
||||
{
|
||||
"name": "Circle",
|
||||
"icon": "round" //●
|
||||
"icon": "round", //●
|
||||
}
|
||||
]
|
||||
|
||||
class ColorPicker{
|
||||
static create(ui: Entity) : Control{
|
||||
//setup root
|
||||
var root = Control.create(ui)
|
||||
Control.set_size(root, 350, 400)
|
||||
var panel = UIWindow.create(ui)
|
||||
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
|
||||
//todo: this should be a dropdown???
|
||||
|
|
@ -117,6 +221,8 @@ class ColorPicker{
|
|||
//todo
|
||||
|
||||
return root
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
static build_triangle_editor(ui: Entity, root: Control){
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import "luxe: game" for Ready
|
||||
import "luxe: assets" for Assets
|
||||
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: draw" for Draw
|
||||
import "luxe: io" for IO
|
||||
|
|
@ -28,6 +28,7 @@ class Game is Ready {
|
|||
|
||||
var ui = Entity.create(app.ui, "ui")
|
||||
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)
|
||||
Control.set_pos(picker, 100, 100)
|
||||
} //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
|
||||
}
|
||||
|
||||
ui.debug_vis = true
|
||||
//ui.debug_vis = true
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
modules = {
|
||||
luxe = "2021.0.2"
|
||||
luxe = "dev"
|
||||
} //modules
|
||||
|
|
|
|||
Loading…
Reference in a new issue