177 lines
No EOL
6.2 KiB
Text
177 lines
No EOL
6.2 KiB
Text
import "luxe: ui/control" for Control
|
|
import "luxe: ui" for UIContain, UIBehave
|
|
import "luxe: world" for UI, World, UIEvent
|
|
import "luxe: draw" for PathStyle
|
|
import "luxe: assets" for Assets
|
|
import "luxe: render" for Image
|
|
import "luxe: math" for Math
|
|
import "luxe: game" for Frame
|
|
|
|
import "globals" for Globals
|
|
import "math/rect" for AABB
|
|
import "math/math" for M
|
|
import "blocks/debug" for DrawDebug
|
|
import "blocks/ui/slider" for UiSlider
|
|
import "math/util" for Util
|
|
|
|
class UiScrollBox{
|
|
|
|
static create(ent){
|
|
var box = Control.create(ent)
|
|
var style = PathStyle.new()
|
|
style.color = [1,1,1,1]
|
|
style.thickness = 1
|
|
Control.set_allow_input(box, true)
|
|
var state = {"style": style, "pressed": false, "position": 0, "scrollSpeed": 4, "ent": ent, "spring": 32, "contentHeight": 0, "drag_cancelled":true}
|
|
Control.set_state_data(box, state)
|
|
|
|
var slider = UiSlider.create(ent)
|
|
Control.child_add(box, slider)
|
|
UiSlider.set_line(slider, false)
|
|
UiSlider.set_direction(slider, UiSlider.vertical)
|
|
UiSlider.set_handle(slider, Assets.image("assets/wip/Knob3"))
|
|
UiSlider.set_value(slider, 0)
|
|
Control.set_size(slider, 7, -1)
|
|
Control.set_behave(slider, UIBehave.right | UIBehave.vfill) //|
|
|
Control.set_margin(slider, 0, 0, 0, 0)
|
|
Control.set_events(slider){|event|
|
|
if(event.type == UIEvent.change){
|
|
var position = 0
|
|
var max_height = (Control.get_height(state["childContainer"]) + 1) - state["contentHeight"]
|
|
if(max_height < 0){
|
|
position = M.lerp(0, max_height, event.change)
|
|
}
|
|
set_position(box, position)
|
|
}
|
|
}
|
|
state["slider"] = slider
|
|
|
|
var childContainer = Control.create(ent)
|
|
Control.child_add(box, childContainer)
|
|
Control.set_behave(childContainer, UIBehave.fill)
|
|
Control.set_margin(childContainer, 1, 1, 7, 2) //don't include border, fix bottom bug, freedom to side slider
|
|
Control.set_clip(childContainer, true)
|
|
Control.set_contain(childContainer, UIContain.column | UIContain.start) //|
|
|
Control.set_allow_input(childContainer, true)
|
|
Control.set_events(childContainer){ |event|
|
|
if(!Util.valid_event(event, state["drag_cancelled"])) return
|
|
if(event.type == UIEvent.press) {
|
|
Control.set_state_data(childContainer, true)
|
|
UI.capture(childContainer)
|
|
}
|
|
if(event.type == UIEvent.release) {
|
|
Control.set_state_data(childContainer, false)
|
|
UI.uncapture(childContainer)
|
|
}
|
|
if(event.type == UIEvent.move && Control.get_state_data(childContainer)){
|
|
var state = Control.get_state_data(box)
|
|
var scrollPos = state["position"]
|
|
scrollPos = scrollPos + event.y_rel / 5
|
|
set_position(box, scrollPos)
|
|
}
|
|
}
|
|
state["childContainer"] = childContainer
|
|
|
|
var alignmentChild = Control.create(ent)
|
|
Control.child_add(childContainer, alignmentChild)
|
|
Control.set_size(alignmentChild, -1, 0)
|
|
Control.set_behave(alignmentChild, UIBehave.hfill | UIBehave.top) //| //make it wide
|
|
Control.set_margin(alignmentChild, 0, state["position"], 0, 0) //pos will always be 0 here, but writing it explicitly makes intent clearer
|
|
state["alignmentChild"] = alignmentChild
|
|
|
|
Control.set_render(box) {|control, state, x, y, w, h|
|
|
var scrollPos = state["position"]
|
|
if(scrollPos >= 0.5){
|
|
scrollPos = M.lerp(scrollPos, 0, M.pow2(-state["spring"] * Globals["Delta"]))
|
|
set_position(control, scrollPos, true)
|
|
}
|
|
var container_height = Control.get_height(childContainer) + 1 //+1 is here to fix clip bug
|
|
var max_pos = Math.min(container_height - state["contentHeight"], 0)
|
|
if(scrollPos <= max_pos - 0.5){
|
|
scrollPos = M.lerp(scrollPos, max_pos, M.pow2(-state["spring"] * Globals["Delta"]))
|
|
set_position(control, scrollPos, true)
|
|
}
|
|
|
|
var depth = UI.draw_depth_of(control, 0)
|
|
UI.draw_rect(control, x+0.5, y+0.5, depth, w-1, h-1, 0, state["style"])
|
|
}
|
|
|
|
Control.set_process(box){|control, state, event, x, y, w, h|
|
|
if(event.control != control) return
|
|
|
|
if(event.type == UIEvent.scroll){
|
|
var scrollPos = state["position"]
|
|
scrollPos = scrollPos + event.y * state["scrollSpeed"] * -1
|
|
set_position(control, scrollPos)
|
|
}
|
|
}
|
|
|
|
return box
|
|
}
|
|
|
|
static add(box, child){
|
|
var state = Control.get_state_data(box)
|
|
Control.child_add(state["childContainer"], child)
|
|
var ent = state["ent"]
|
|
|
|
UI.commit(ent)
|
|
update_content(box)
|
|
}
|
|
|
|
static remove(box, child){
|
|
var state = Control.get_state_data(box)
|
|
Control.child_remove(state["childContainer"], child)
|
|
var ent = state["ent"]
|
|
|
|
UI.commit(ent)
|
|
update_content(box)
|
|
}
|
|
|
|
|
|
static update_content(box){
|
|
var state = Control.get_state_data(box)
|
|
var container = state["childContainer"]
|
|
var child_count = Control.child_count(container)
|
|
|
|
//if only the alignmentChild exists
|
|
if(child_count <= 1){
|
|
state["contentHeight"] = 0
|
|
return
|
|
}
|
|
|
|
var first_child = Control.child_get(container, 1)
|
|
var upper_bound = Control.get_pos_y_abs(first_child)
|
|
var last_child = Control.child_get(container, child_count - 1)
|
|
var lower_bound = Control.get_pos_y_abs(last_child) + Control.get_height(last_child)
|
|
state["contentHeight"] = lower_bound - upper_bound //its lower - upper because of the y-negative coordinates
|
|
}
|
|
|
|
static set_position(box, position) {
|
|
set_position(box, position, false)
|
|
}
|
|
|
|
static set_drag_cancelled(box, drag_cancelled){
|
|
var state = Control.get_state_data(box)
|
|
state["drag_cancelled"] = drag_cancelled
|
|
}
|
|
|
|
static set_position(box, position, delay_commit){
|
|
var state = Control.get_state_data(box)
|
|
state["position"] = position
|
|
var ent = state["ent"]
|
|
Control.set_margin(state["alignmentChild"], 0, position, 0, 0)
|
|
if(!delay_commit){
|
|
|
|
} else {
|
|
Frame.end{
|
|
|
|
}
|
|
}
|
|
var rel_pos = 0
|
|
var max_height = (Control.get_height(state["childContainer"]) + 1) - state["contentHeight"]
|
|
if(max_height < 0){
|
|
rel_pos = M.clamp(M.inv_lerp(0, max_height, position), 0, 1)
|
|
}
|
|
UiSlider.set_value(state["slider"], rel_pos)
|
|
}
|
|
} |