layout and pixel font shaders
This commit is contained in:
parent
6e1db30a8b
commit
c4ebdf3055
7 changed files with 314 additions and 20 deletions
|
|
@ -14,7 +14,7 @@ class Tooltip{
|
|||
|
||||
construct new(app){
|
||||
_text = Entity.create(app.ui)
|
||||
var mat = Assets.material("luxe: material/font")
|
||||
var mat = Material.create("shaders/pixel_text")
|
||||
Text.create(_text, mat, 8, "assets/fonts/BabyBlocks", color)
|
||||
|
||||
Transform.create(_text)
|
||||
|
|
@ -24,7 +24,7 @@ class Tooltip{
|
|||
_shadows = []
|
||||
for(i in offsets){
|
||||
var shadow = Entity.create(app.ui)
|
||||
Text.create(shadow, Material.clone(mat), 8, "assets/fonts/BabyBlocks", background)
|
||||
Text.create(shadow, mat, 8, "assets/fonts/BabyBlocks", background)
|
||||
Transform.create(shadow)
|
||||
Transform.set_snap(shadow, 1, 1, 0)
|
||||
_shadows.add(shadow)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import "luxe: draw" for Draw, PathStyle
|
||||
import "luxe: world" for Entity, Transform, UI, UIRenderMode
|
||||
import "luxe: world" for UILayout, UILayoutBehave, UILayoutContain
|
||||
import "luxe: ui/control" for Control
|
||||
import "luxe: ui/panel" for UIPanel
|
||||
import "luxe: ui/list" for UIList
|
||||
|
|
@ -7,6 +8,7 @@ import "luxe: ui/button" for UIButton
|
|||
import "luxe: ui/image" for UIImage
|
||||
import "luxe: assets" for Assets
|
||||
import "luxe: ui/text" for UIText
|
||||
import "luxe: render" for Material
|
||||
|
||||
import "globals" for Globals
|
||||
import "blocks/ui/image_button" for ImageButton
|
||||
|
|
@ -32,6 +34,12 @@ class Ui{
|
|||
|
||||
UI.create(_ui, ui_rect.x, ui_rect.y, ui_rect.width, ui_rect.height, 0, app.ui_camera)
|
||||
UI.set_render_mode(_ui, UIRenderMode.world)
|
||||
var solid_mat = Material.create("luxe: material_basis/ui_solid")
|
||||
var text_mat = Material.create("luxe: material_basis/ui_font")
|
||||
//var text_mat = Material.create("shaders/pixel_text_ui")
|
||||
UI.set_material_basis(_ui, "luxe: material_basis/ui_solid", "shaders/pixel_text_ui")
|
||||
|
||||
UILayout.create(_ui)
|
||||
|
||||
_info = setup_info()
|
||||
_planning = setup_planning()
|
||||
|
|
@ -47,13 +55,16 @@ class Ui{
|
|||
}
|
||||
|
||||
UI.commit(_ui)
|
||||
UILayout.commit(_ui)
|
||||
}
|
||||
|
||||
setup_info(){
|
||||
var ui_rect = Globals["UiRect"]
|
||||
|
||||
var root = Control.create(_ui)
|
||||
Control.set_size(root, ui_rect.width, ui_rect.height)
|
||||
UILayout.set_behave(_ui, root, UILayoutBehave.fill)
|
||||
UILayout.set_margin(_ui, root, 0, 0, 0, 0)
|
||||
|
||||
setup_info_toolbar(root)
|
||||
setup_info_human(root)
|
||||
return root
|
||||
|
|
@ -66,9 +77,11 @@ class Ui{
|
|||
var list = Control.create(_ui)
|
||||
Control.set_id(list, "info list")
|
||||
Control.child_add(root, list)
|
||||
//todo: make list horizontal?
|
||||
Control.set_pos(list, 0, ui_rect.height-16)
|
||||
Control.set_size(list, ui_rect.width, 16)
|
||||
//make list span bottom area
|
||||
UILayout.set_behave(_ui, list, UILayoutBehave.left | UILayoutBehave.right | UILayoutBehave.bottom)
|
||||
UILayout.set_margin(_ui, list, 0, 0, 0, 0)
|
||||
UILayout.set_contain(_ui, list, UILayoutContain.row | UILayoutContain.start)
|
||||
Control.set_size(list, 16, 16)
|
||||
|
||||
var adventureButtons = Assets.image("assets/AdventureButtons")
|
||||
var tiles = [10, 1]
|
||||
|
|
@ -76,12 +89,10 @@ class Ui{
|
|||
|
||||
//plan adventure
|
||||
button = list_button(list)
|
||||
Control.set_id(button, "info button %(0)")
|
||||
UIImage.set_image(button, adventureButtons)
|
||||
ImageButton.set_tooltip(button, "Adventure!")
|
||||
ImageButton.set_tile_uv(button, tiles, [1, 0])
|
||||
ImageButton.set_state_change(button) { |data|
|
||||
System.print("adventure button: %(data)")
|
||||
if(data["press"]){
|
||||
ui_mode = Ui.Planning
|
||||
}
|
||||
|
|
@ -112,13 +123,15 @@ class Ui{
|
|||
Control.set_size(portrait, 30, 46)
|
||||
Control.set_id(portrait, "person info portrait")
|
||||
Control.child_add(root, portrait)
|
||||
UILayout.set_behave(_ui, portrait, UILayoutBehave.left | UILayoutBehave.top)
|
||||
UILayout.set_margin(_ui, portrait, 1, 1, 0, 0)
|
||||
|
||||
var frame = UIImage.create(_ui)
|
||||
UIImage.set_image(frame, Assets.image("assets/wip/Frame"))
|
||||
Control.set_pos(frame, 1, 1)
|
||||
Control.set_size(frame, 30, 46)
|
||||
Control.set_id(frame, "person info frame")
|
||||
Control.child_add(root, frame)
|
||||
Control.child_add(portrait, frame)
|
||||
|
||||
Globals["Game"].Focus.on_change(true) {|val|
|
||||
//todo: more sophisticated portrait generation
|
||||
|
|
@ -126,9 +139,13 @@ class Ui{
|
|||
UIImage.set_color(portrait, Human.get_color(val) || [0, 0, 0, 1])
|
||||
}
|
||||
|
||||
var statBlock = Control.create(_ui)
|
||||
UILayout.set_behave(_ui, statBlock, UILayoutBehave.fill)
|
||||
UILayout.set_margin(_ui, statBlock, 33, 1, 0, 16)
|
||||
UILayout.set_contain(_ui, statBlock, UILayoutContain.column | UILayoutContain.start)
|
||||
|
||||
var name = UISimpleText.create(_ui)
|
||||
Control.set_pos(name, 33, 1)
|
||||
Control.child_add(root, name)
|
||||
Control.child_add(statBlock, name)
|
||||
Control.set_id(name, "human name info")
|
||||
Globals["Game"].Focus.on_change(true) {|val|
|
||||
var name_string = Human.get_name(val) || "-"
|
||||
|
|
@ -136,8 +153,7 @@ class Ui{
|
|||
}
|
||||
|
||||
var adventures = UISimpleText.create(_ui)
|
||||
Control.set_pos(adventures, 33, 10)
|
||||
Control.child_add(root, adventures)
|
||||
Control.child_add(statBlock, adventures)
|
||||
Control.set_id(name, "human adventure count")
|
||||
Globals["Game"].Focus.on_change(true) {|val|
|
||||
var count = Human.get_adventure_count(val)
|
||||
|
|
@ -156,8 +172,10 @@ class Ui{
|
|||
//list
|
||||
var list = Control.create(_ui)
|
||||
Control.child_add(root, list)
|
||||
Control.set_pos(list, 0, ui_rect.height-16)
|
||||
Control.set_size(list, ui_rect.width, 16)
|
||||
Control.set_size(list, 0, 16)
|
||||
UILayout.set_behave(_ui, list, UILayoutBehave.left | UILayoutBehave.right | UILayoutBehave.bottom)
|
||||
UILayout.set_margin(_ui, list, 0, 0, 0, 0)
|
||||
UILayout.set_contain(_ui, list, UILayoutContain.row | UILayoutContain.start)
|
||||
|
||||
var adventureButtons = Assets.image("assets/AdventureButtons")
|
||||
var tiles = [10, 1]
|
||||
|
|
@ -169,7 +187,6 @@ class Ui{
|
|||
ImageButton.set_tooltip(button, "Info")
|
||||
ImageButton.set_tile_uv(button, tiles, [1, 0])
|
||||
ImageButton.set_state_change(button) { |data|
|
||||
System.print("info button: %(data)")
|
||||
if(data["press"]){
|
||||
ui_mode = Ui.Info
|
||||
}
|
||||
|
|
@ -210,10 +227,8 @@ class Ui{
|
|||
|
||||
list_button(parent){
|
||||
var button = ImageButton.create(_ui)
|
||||
Control.child_add(parent, button)
|
||||
var i = Control.child_index(parent, button)
|
||||
Control.set_size(button, 16, 16)
|
||||
Control.set_pos(button, i*16, 0) //let list handle this in future
|
||||
Control.child_add(parent, button)
|
||||
return button
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ class Game is Ready {
|
|||
|
||||
DrawDebug.commit()
|
||||
|
||||
|
||||
app.tick(delta)
|
||||
_tooltip.tick() //important to tick after systems to not have a 1 frame lag after setting text
|
||||
} //tick
|
||||
|
|
|
|||
50
Luxe/shaders/pixel_text.emsl
Normal file
50
Luxe/shaders/pixel_text.emsl
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
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 Font {
|
||||
image2D pages[8]
|
||||
}
|
||||
|
||||
stage vertex vert(
|
||||
input { View view },
|
||||
vertex in { #0 float4 pos, #1 float4 color, #2 float2 uv },
|
||||
fragment out { float4 color, float2 uv, float page })
|
||||
{
|
||||
out.color = in.color;
|
||||
out.uv = in.uv;
|
||||
out.page = in.pos.w;
|
||||
stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0);
|
||||
}
|
||||
|
||||
stage fragment frag(
|
||||
input { Font font },
|
||||
fragment in { float4 color, float2 uv, float page })
|
||||
{
|
||||
int page = int(in.page);
|
||||
float4 msdf_sample = texture(input.font.pages[0], in.uv.xy);
|
||||
if(page == 1) { msdf_sample = texture(input.font.pages[1], in.uv.xy); }
|
||||
if(page == 2) { msdf_sample = texture(input.font.pages[2], in.uv.xy); }
|
||||
if(page == 3) { msdf_sample = texture(input.font.pages[3], in.uv.xy); }
|
||||
if(page == 4) { msdf_sample = texture(input.font.pages[4], in.uv.xy); }
|
||||
if(page == 5) { msdf_sample = texture(input.font.pages[5], in.uv.xy); }
|
||||
if(page == 6) { msdf_sample = texture(input.font.pages[6], in.uv.xy); }
|
||||
if(page == 7) { msdf_sample = texture(input.font.pages[7], in.uv.xy); }
|
||||
|
||||
float r = msdf_sample.r;
|
||||
float g = msdf_sample.g;
|
||||
float b = msdf_sample.b;
|
||||
float median = max(min(r, g), min(max(r, g), b));
|
||||
float opacity = float(median > 0.5);
|
||||
|
||||
stage.color[0] = float4(in.color.rgb, in.color.a * opacity);
|
||||
}
|
||||
63
Luxe/shaders/pixel_text.material_basis.lx
Normal file
63
Luxe/shaders/pixel_text.material_basis.lx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
material_basis = {
|
||||
vertex_format = "luxe.textured"
|
||||
shaders = {
|
||||
vertex = { library="shaders/pixel_text" function="vert" }
|
||||
fragment = { library="shaders/pixel_text" function="frag" }
|
||||
}
|
||||
depth_test = true
|
||||
depth_write = false
|
||||
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 = {
|
||||
font.pages = {
|
||||
type = "image"
|
||||
count = 8
|
||||
value = [
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
104
Luxe/shaders/pixel_text_ui.emsl
Normal file
104
Luxe/shaders/pixel_text_ui.emsl
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
|
||||
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 Font {
|
||||
image2D pages[8]
|
||||
}
|
||||
|
||||
input FUI {
|
||||
float2 canvas_size,
|
||||
#0 image2D tex_mask
|
||||
}
|
||||
|
||||
stage vertex vert(
|
||||
input { View view },
|
||||
vertex in {
|
||||
#0 float4 pos,
|
||||
#1 float4 color,
|
||||
#2 float2 uv,
|
||||
#3 float4 data
|
||||
},
|
||||
fragment out {
|
||||
float4 color,
|
||||
float2 uv,
|
||||
float2 mask_uv,
|
||||
float clip
|
||||
})
|
||||
{
|
||||
out.uv = in.uv;
|
||||
out.color = in.color;
|
||||
out.clip = in.data.x;
|
||||
out.mask_uv = float2(in.data.y, 1.0 - in.data.z);
|
||||
|
||||
stage.pos = input.view.mvp * float4(in.pos.xyz, 1.0);
|
||||
}
|
||||
|
||||
stage fragment frag(
|
||||
input { FUI ui, Font font },
|
||||
fragment in {
|
||||
float4 color,
|
||||
float2 uv,
|
||||
float2 mask_uv,
|
||||
float clip,
|
||||
float page
|
||||
})
|
||||
{
|
||||
//outside mask uvs?
|
||||
bool outside_mask = in.mask_uv.x < 0.0 ||
|
||||
in.mask_uv.x > 1.0 ||
|
||||
in.mask_uv.y < 0.0 ||
|
||||
in.mask_uv.y > 1.0;
|
||||
|
||||
if(outside_mask) {
|
||||
discard;
|
||||
// stage.color[0] = float4(1,0.2,0.3,1);
|
||||
return;
|
||||
}
|
||||
|
||||
float4 mask = texture(input.ui.tex_mask, in.mask_uv);
|
||||
|
||||
//16 bit mask
|
||||
// float mask_clip = round(mask.r * 65535.0);
|
||||
//8 bit mask
|
||||
int lsb = int(round(mask.r * 255.0));
|
||||
int msb = int(round(mask.g * 255.0)) * 256; //<< 8;
|
||||
int mask_clip = lsb | msb;
|
||||
// int mask_clip = lsb + msb; //webgl1
|
||||
|
||||
//outside our clipping bounds?
|
||||
int my_clip = int(in.clip);
|
||||
if(my_clip != 0 && mask_clip < my_clip) {
|
||||
discard;
|
||||
// stage.color[0] = float4(0,1,1,0.2);
|
||||
return;
|
||||
}
|
||||
|
||||
int page = int(in.page);
|
||||
float4 msdf_sample = texture(input.font.pages[0], in.uv.xy);
|
||||
if(page == 1) { msdf_sample = texture(input.font.pages[1], in.uv.xy); }
|
||||
if(page == 2) { msdf_sample = texture(input.font.pages[2], in.uv.xy); }
|
||||
if(page == 3) { msdf_sample = texture(input.font.pages[3], in.uv.xy); }
|
||||
if(page == 4) { msdf_sample = texture(input.font.pages[4], in.uv.xy); }
|
||||
if(page == 5) { msdf_sample = texture(input.font.pages[5], in.uv.xy); }
|
||||
if(page == 6) { msdf_sample = texture(input.font.pages[6], in.uv.xy); }
|
||||
if(page == 7) { msdf_sample = texture(input.font.pages[7], in.uv.xy); }
|
||||
|
||||
float r = msdf_sample.r;
|
||||
float g = msdf_sample.g;
|
||||
float b = msdf_sample.b;
|
||||
float median = max(min(r, g), min(max(r, g), b));
|
||||
float opacity = float(median > 0.5);
|
||||
|
||||
stage.color[0] = float4(in.color.rgb, in.color.a * opacity * mask.a);
|
||||
|
||||
}
|
||||
63
Luxe/shaders/pixel_text_ui.material_basis.lx
Normal file
63
Luxe/shaders/pixel_text_ui.material_basis.lx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
material_basis = {
|
||||
vertex_format = "luxe.textured"
|
||||
shaders = {
|
||||
vertex = { library="shaders/pixel_text_ui" function="vert" }
|
||||
fragment = { library="shaders/pixel_text_ui" function="frag" }
|
||||
}
|
||||
depth_test = true
|
||||
depth_write = false
|
||||
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 = {
|
||||
font.pages = {
|
||||
type = "image"
|
||||
count = 8
|
||||
value = [
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
{
|
||||
type = "image2D"
|
||||
sampler_state = "linear_repeat"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue