nice circle :)

This commit is contained in:
Ronja 2021-11-11 21:49:18 +01:00
parent dc2b06f051
commit 3bc442f8c7
8 changed files with 285 additions and 33 deletions

View file

@ -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){

View file

@ -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

View 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,
}
}
}

View 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
View 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;
}

View file

@ -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"]
}
}
}

View file

@ -15,5 +15,5 @@ engine = {
depth = 24
}
ui.debug_vis = true
//ui.debug_vis = true
}

View file

@ -1,3 +1,3 @@
modules = {
luxe = "2021.0.2"
luxe = "dev"
} //modules