put click functionality in its own class, allowing many Controls to use it

also bunch of other stuff
This commit is contained in:
Ronja 2020-10-17 19:11:24 +02:00
parent c934369f31
commit d2b3ccb745
13 changed files with 202 additions and 135 deletions

View file

@ -3,6 +3,8 @@
//make groups based on origin culture / meaning
//probably better to do when I have a procgen text engine
"Abyole"
"Afua"
"Amelia"
"Bertine"
"Bob"
@ -14,10 +16,14 @@
"Duck"
"Elliott"
"Freya"
"Gidado"
"Ida"
"Innes"
"Irene"
"Isisa"
"Jess"
"Jules"
"Kabanga"
"Karl"
"Karo"
"Lara"
@ -29,6 +35,7 @@
"Mara"
"Mercedes"
"Merryl"
"Miia"
"Niels"
"Nina"
"Rami"
@ -38,10 +45,12 @@
"Ronja"
"Sandra"
"Simon"
"Sironka"
"Steve"
"Sven"
"Sy"
"Ty"
"Wocky"
"X!abbu"
"Zoe"
]

View file

@ -11,7 +11,8 @@ import "luxe: game" for Frame
import "luxe: containers" for Lists
import "globals" for Globals
import "blocks/ui/image_button" for ImageButton
import "blocks/ui/clickable" for Clickable
import "blocks/ui/image_util" for UiImageUtil
import "math/observable" for Observable
import "blocks/ui/simple_text" for UISimpleText
import "blocks/ui/ui" for Ui
@ -121,7 +122,7 @@ class UiAdventure{
Control.set_events(compass){|event|
if(event.type == UIEvent.change){
var angle = event.change
var angleIndex = M.repeat(-(steps * angle / 360).round, steps)
var angleIndex = M.mod(-(steps * angle / 360).round, steps)
var adventure = _game.adventures.planning
adventure.value.direction = angleIndex
adventure.emit()
@ -226,16 +227,12 @@ class UiAdventure{
UILayout.set_margin(_ent, item, 0, 0, 0, 0)
UILayout.set_contain(_ent, item, UILayoutContain.row | UILayoutContain.start)//|
Control.set_size(item, -1, 12)
Control.set_allow_input(item, true)
Control.set_id(item, "Person %(i) : %(Human.get_name(adventurer))")
Control.set_events(item) {|event|
if(UI.event_cancelled(_ent, event.id)) return
if(!Util.valid_event(event)) return
if(event.type == UIEvent.press){
_ui.ui_mode = Ui.Info
_ui.info.page.value = UiInfo.human
_game.focus.value = adventurer
}
Clickable.make_clickable(item)
Clickable.set_on_click(item) {
_ui.ui_mode = Ui.Info
_ui.info.page.value = UiInfo.human
_game.focus.value = adventurer
}
UiScrollBox.add(list, item)
@ -255,20 +252,19 @@ class UiAdventure{
UILayout.set_behave(_ent, name, UILayoutBehave.hfill | UILayoutBehave.left)//|
UILayout.set_margin(_ent, name, 2, 1, 0, 1)
var remove = ImageButton.create(_ent)
var remove = UIImage.create(_ent)
Clickable.make_clickable(remove)
Control.child_add(item, remove)
Control.set_size(remove, 8, 8)
UIImage.set_image(remove, x_image)
UIImage.set_color(remove, Color.hex(0xec172a))
UILayout.set_margin(_ent, remove, 0, 0, 2, 0)
ImageButton.set_tooltip(remove, "remove")
ImageButton.set_state_change(remove) { |data, button|
if(data["press"]){
Frame.end{
Globals["Tooltip"].clear(button)
Lists.remove(adventure.adventurers, adventurer)
_game.adventures.planning.emit()
}
Clickable.set_tooltip(remove, "remove")
Clickable.set_on_click(remove) {
Frame.end{
Globals["Tooltip"].clear(remove)
Lists.remove(adventure.adventurers, adventurer)
_game.adventures.planning.emit()
}
}
@ -315,14 +311,11 @@ class UiAdventure{
UILayout.set_margin(_ent, item, 0, 0, 0, 0)
UILayout.set_contain(_ent, item, UILayoutContain.row | UILayoutContain.start)//|
Control.set_size(item, -1, 12)
Control.set_allow_input(item, true)
Control.set_events(item) {|event|
if(UI.event_cancelled(_ent, event.id)) return
if(event.type == UIEvent.press){
_ui.ui_mode = Ui.Info
_ui.info.page.value = UiInfo.human
_game.focus.value = adventurer
}
Clickable.make_clickable(item)
Clickable.set_on_click(item) {
_ui.ui_mode = Ui.Info
_ui.info.page.value = UiInfo.human
_game.focus.value = adventurer
}
UiScrollBox.add(list, item)
@ -342,20 +335,19 @@ class UiAdventure{
UILayout.set_behave(_ent, name, UILayoutBehave.hfill | UILayoutBehave.left)//|
UILayout.set_margin(_ent, name, 2, 1, 0, 1)
var remove = ImageButton.create(_ent)
var remove = UIImage.create(_ent)
Clickable.make_clickable(remove)
Control.child_add(item, remove)
Control.set_size(remove, 8, 8)
UIImage.set_image(remove, x_image)
UIImage.set_color(remove, Color.hex(0xec172a))
UILayout.set_margin(_ent, remove, 0, 0, 2, 0)
ImageButton.set_tooltip(remove, "remove")
ImageButton.set_state_change(remove) { |data, button|
if(data["press"]){
Frame.end{
Globals["Tooltip"].clear(button)
Lists.remove(adventure.adventurers, adventurer)
_game.adventures.planning.emit()
}
Clickable.set_tooltip(remove, "remove")
Clickable.set_on_click(remove) {
Frame.end{
Globals["Tooltip"].clear(remove)
Lists.remove(adventure.adventurers, adventurer)
_game.adventures.planning.emit()
}
}

View file

@ -0,0 +1,123 @@
import "luxe: ui/image" for UIImage
import "luxe: world" for UIEvent, UI
import "luxe: ui/control" for Control
import "luxe: settings" for Settings
import "luxe: io" for IO
import "luxe: math" for Math
import "globals" for Globals
import "math/util" for Util
class Clickable{
static make_clickable(button){
var ent = Control.get_entity(button)
var data = Control.get_state_data(button)
if(data == null) data = {}
var newData = {
"hover": false,
"press": false,
"state_change": null,
"tooltip": null,
"allow_cancelled": false,
"click_time": Settings.get("game.ui.button.click_time", 10),
"click_area": Settings.get("game.ui.button.click_area", 2),
"on_click": null,
"press_time": -1,
"press_location": [0, 0],
}
newData.each{|val|
if(data.containsKey(val.key)) System.print("[warning] overriding key %(val.key)")
data[val.key] = val.value
}
Control.set_state_data(button, data)
Control.set_allow_input(button, true)
Control.set_events(button) {|event|
var data = Control.get_state_data(button)
if(!Util.valid_event(event, data["allow_cancelled"])) return
var changed = false
if(event.type == UIEvent.enter){
changed = true
data["hover"] = true
} else if(event.type == UIEvent.exit) {
changed = true
data["hover"] = false
data["press"] = false
} else if(event.type == UIEvent.press) {
changed = true
data["press"] = true
if(data["click_time"] < 0){
if(data["on_click"])data["on_click"].call() //you are valid, you are loved, you have been clicked
} else {
data["press_time"] = IO.timestamp()
data["press_location"] = [event.x, event.y]
}
} else if(event.type == UIEvent.release) {
changed = true
data["press"] = false
var press_time = data["press_time"]
var click_time = data["click_time"]
if(click_time >= 0 && press_time >= 0 &&
press_time + click_time >= IO.timestamp()){
if(data["on_click"])data["on_click"].call()
}
} else if(event.type == UIEvent.move) {
var press_location = data["press_location"]
//if mouse moved too much
if(Math.length(press_location.x - event.x, press_location.y - event.y) > data["click_area"]) {
//abort click
data["press_time"] = -1
}
}
if(changed){
//System.print(UIEvent.name(string_type) + " " + data["tooltip"])
var func = data["state_change"]
if(func){
func.call(data, button)
}
var tooltip = data["tooltip"]
if(tooltip){
if(data["hover"]) {
Globals["Tooltip"].set(tooltip, button)
//this only works when the UI is at the very bottom
//which it is so whatever :)
Globals["Tooltip"].fix_y(Globals["UiRect"].height-Control.get_pos_y_abs(button))
} else {
Globals["Tooltip"].clear(button)
}
}
UI.event_cancel(ent, event.id)
}
}
return button
}
static set_tooltip(control, tooltip){
var data = Control.get_state_data(control)
data["tooltip"] = tooltip
}
static set_allow_cancelled(control, allow){
var data = Control.get_state_data(control)
data["allow_cancelled"] = allow
}
static set_state_change(control, fn){
var data = Control.get_state_data(control)
data["state_change"] = fn
}
static set_on_click(control, fn){
var data = Control.get_state_data(control)
data["on_click"] = fn
}
static get_data(control){
return Control.get_state_data(control)
}
}

View file

@ -1,80 +0,0 @@
import "luxe: ui/image" for UIImage
import "luxe: world" for UIEvent, UI
import "luxe: ui/control" for Control
import "globals" for Globals
import "math/util" for Util
class ImageButton{
static create(ent){
var button = UIImage.create(ent)
var data = {
"hover": false,
"press": false,
"state_change": null,
"tooltip": null
}
Control.set_state_data(button, data)
Control.set_events(button) {|event|
if(!Util.valid_event(event)) return
if(UI.event_cancelled(ent, event.id)) return
var data = null
if(event.type == UIEvent.enter){
data = Control.get_state_data(button)
data["hover"] = true
} else if(event.type == UIEvent.exit) {
data = Control.get_state_data(button)
data["hover"] = false
data["press"] = false
} else if(event.type == UIEvent.press) {
data = Control.get_state_data(button)
data["press"] = true
} else if(event.type == UIEvent.release) {
data = Control.get_state_data(button)
data["press"] = false
}
if(data){
//System.print(UIEvent.name(string_type) + " " + data["tooltip"])
var func = data["state_change"]
if(func){
func.call(data, button)
}
var tooltip = data["tooltip"]
if(tooltip){
if(data["hover"]) {
Globals["Tooltip"].set(tooltip, button)
//this only works when the UI is at the very bottom
//which it is so whatever :)
Globals["Tooltip"].fix_y(Globals["UiRect"].height-Control.get_pos_y_abs(button))
} else {
Globals["Tooltip"].clear(button)
}
}
UI.event_cancel(ent, event.id)
}
}
return button
}
static set_tooltip(control, tooltip){
var data = Control.get_state_data(control)
data["tooltip"] = tooltip
}
static set_state_change(control, fn){
var data = Control.get_state_data(control)
data["state_change"] = fn
}
static get_data(control){
//System.print(Control.get_state_data(control))
}
static set_tile_uv(control, tiles, index){
UIImage.set_uv(control, index.x/tiles.x, index.y/tiles.y, (index.x+1)/tiles.x, (index.y+1)/tiles.y)
}
}

View file

@ -0,0 +1,7 @@
import "luxe: ui/image" for UIImage
class UiImageUtil{
static set_tile_uv(control, tiles, index){
UIImage.set_uv(control, index.x/tiles.x, index.y/tiles.y, (index.x+1)/tiles.x, (index.y+1)/tiles.y)
}
}

View file

@ -11,7 +11,8 @@ import "luxe: ui/text" for UIText
import "luxe: render" for Material
import "globals" for Globals
import "blocks/ui/image_button" for ImageButton
import "blocks/ui/clickable" for Clickable
import "blocks/ui/image_util" for UiImageUtil
import "math/observable" for Observable
import "math/stringUtil" for StringUtil
import "blocks/ui/simple_text" for UISimpleText

View file

@ -53,7 +53,7 @@ class UiScrollBox{
UILayout.set_contain(ent, childContainer, UILayoutContain.column | UILayoutContain.start) //|
Control.set_allow_input(childContainer, true)
Control.set_events(childContainer){ |event|
if(!Util.valid_event(event)) return
if(!Util.valid_event(event, true)) return
if(event.type == UIEvent.press) {
Control.set_state_data(childContainer, true)
UI.capture(childContainer)

View file

@ -11,7 +11,8 @@ import "luxe: ui/text" for UIText
import "luxe: render" for Material
import "globals" for Globals
import "blocks/ui/image_button" for ImageButton
import "blocks/ui/clickable" for Clickable
import "blocks/ui/image_util" for UiImageUtil
import "math/observable" for Observable
import "blocks/ui/simple_text" for UISimpleText
@ -56,7 +57,8 @@ class Ui{
}
list_button(parent){
var button = ImageButton.create(_ent)
var button = UIImage.create(_ent)
Clickable.make_clickable(button)
Control.set_size(button, 16, 16)
Control.child_add(parent, button)
var adventureButtons = Assets.image("assets/wip/AdventureButtons")
@ -68,22 +70,20 @@ class Ui{
var tiles = [10, 1]
var button = list_button(parent)
ImageButton.set_tile_uv(button, tiles, tile)
UiImageUtil.set_tile_uv(button, tiles, tile)
return button
}
list_button(parent, tile, tooltip){
var button = list_button(parent, tile)
ImageButton.set_tooltip(button, tooltip)
Clickable.set_tooltip(button, tooltip)
return button
}
list_button(parent, tile, tooltip, pressFn){
var button = list_button(parent, tile, tooltip)
ImageButton.set_state_change(button) { |data|
if(data["press"]){
pressFn.call()
}
Clickable.set_on_click(button) {
pressFn.call()
}
return button
}

View file

@ -52,11 +52,14 @@ class M{
return result
}
static repeat(number, min, max){
return min + repeat(number, max - min)
//not remainder!!
//this is the cool modulo
//the one that can deal with negative numbers not badly
static mod(number, min, max){
return min + mod(number, max - min)
}
static repeat(number, max){
static mod(number, max){
return max.sign * ((number % max + max) % max)
}

View file

@ -1,4 +1,5 @@
import "math/vector" for Vector
//import M at end of file
class AABB{
x{_x}

View file

@ -69,9 +69,13 @@ class Util{
}
static valid_event(event){
return valid_event(event, false)
}
static valid_event(event, allow_cancelled){
//cancelled events are not valid :V
var entity = Control.get_entity(event.control)
if(UI.event_cancelled(entity, event.id)) return false
if(!allow_cancelled && UI.event_cancelled(entity, event.id)) return false
//events without a position are always valid
if(![UIEvent.press, UIEvent.release, UIEvent.move].contains(event.type)) return true

View file

@ -13,8 +13,15 @@ engine = {
stencil = 0
depth = 0
}
//debug stuff
//ui.debug_vis = true
render.opengl.debug_level = 3
}
//debug stuff
//engine.ui.debug_vis = true
engine.render.opengl.debug_level = 3
game = {
ui = {
button.click_time = 2
}
}

View file

@ -1,3 +1,3 @@
modules = {
luxe = "2020.3.0"
luxe = "2020.3.1"
} //modules