import "luxe: assets" for Assets, Strings import "luxe: color" for Color import "luxe: containers" for Lists import "luxe: draw" for Draw, PathStyle import "luxe: game" for Frame import "luxe: math" for Math import "luxe: render" for Material, TextAlign import "luxe: ui/control" for Control import "luxe: ui/image" for UIImage import "luxe: ui/label" for UILabel import "luxe: world" for Entity, Transform, UI, UIRenderMode, UIEvent import "luxe: world" for UIBehave, UIContain import "blocks/human/human" for Human import "blocks/ui/box" for UIBox import "blocks/ui/clickable" for Clickable import "blocks/ui/compass" for UiCompass import "blocks/ui/image_util" for UiImageUtil import "blocks/ui/info" for UiInfo //this is a cyclic dependency waiting to happen... import "blocks/ui/number_field" for NumberField import "blocks/ui/scroll_box" for UiScrollBox import "blocks/ui/simple_text" for UISimpleText import "blocks/ui/slider" for UiSlider import "blocks/ui/ui" for Ui import "globals" for Globals import "math/event" for MultiListenerToken import "math/math" for M import "math/observable" for Observable import "math/stringUtil" for StringUtil import "math/util" for Util class UiAdventure{ root{_root} static direction{"direction"} static people{"people"} static resources{"resources"} static depart{"depart"} static abort{"abort"} adventure{_game.adventures.planning} //shortcut to get currently planning adventure (observable) construct new(ent, ui){ _ent = ent _ui = ui _game = Globals["Game"] _page = Observable.new(UiAdventure.direction) setup() } setup(){ var ui_rect = Globals["UiRect"] _root = Control.create(_ent) Control.set_allow_input(_root, true) Control.set_size(_root, ui_rect.width, ui_rect.height) //if no adventure is planned anymore, leave adventure planning ui _game.adventures.planning.on_change{|adventure| if(!adventure){ _ui.ui_mode = Ui.Info _page.value = UiAdventure.direction } } toolbar() direction() people() resources() depart() abort() } toolbar(){ //list var list = Control.create(_ent) Control.child_add(_root, list) Control.set_size(list, 0, 16) Control.set_behave(list, UIBehave.left | UIBehave.right | UIBehave.bottom)//| Control.set_margin(list, 0, 0, 0, 0) Control.set_contain(list, UIContain.row | UIContain.start) //| //toolbar icons _ui.list_button(list, [1, 0], "Info") {_ui.ui_mode = Ui.Info} _ui.list_button(list, [3, 0], "Direction") {_page.value = UiAdventure.direction} _ui.list_button(list, [2, 0], "People") {_page.value = UiAdventure.people} _ui.list_button(list, [4, 0], "Stuff") {_page.value = UiAdventure.resources} _ui.list_button(list, [5, 0], "Depart") {_page.value = UiAdventure.depart} _ui.list_button(list, [0, 0], "Abort") {_page.value = UiAdventure.abort} } direction(){ var page = Control.create(_ent) Control.child_add(_root, page) Control.set_behave(page, UIBehave.fill) Control.set_margin(page, 0, 0, 0, 16) Control.set_contain(page, UIContain.row | UIContain.start) //| _page.on_change(true){|val| Control.set_visible(page, val == UiAdventure.direction) } //compass var compass = UiCompass.create(_ent) Control.child_add(page, compass) Control.set_size(compass, 32, 32) Control.set_margin(compass, 8, 0, 0, 0) var steps = 16 //compass steps adventure.on_change(true){|val| if(val == null) return var angle = -val.direction * 360 / steps UiCompass.set_angle(compass, angle) } Control.set_events(compass){|event| if(event.type == UIEvent.change){ var angle = event.change var angleIndex = M.mod(-(steps * angle / 360).round, steps) adventure.value.direction = angleIndex adventure.emit() } } //other parent var colParent = Control.create(_ent) Control.set_id(colParent, "dir col parent") Control.child_add(page, colParent) Control.set_behave(colParent, UIBehave.fill) Control.set_margin(colParent, 8, 0, 0, 0) Control.set_contain(colParent, UIContain.column | UIContain.start) //| //slider var slider = UiSlider.create(_ent) Control.set_id(slider, "dir dist slider") Control.child_add(colParent, slider) Control.set_size(slider, 0, 11) Control.set_behave(slider, UIBehave.left | UIBehave.right) //| Control.set_margin(slider, 4, 4, 4, 0) adventure.on_change(true){|val| if(val == null) return var relative_distance = val.distance / _game.adventures.max_distance UiSlider.set_value(slider, relative_distance) } Control.set_events(slider){|event| if(event.type == UIEvent.change){ var distance = (event.change * _game.adventures.max_distance).round adventure.value.distance = distance adventure.emit() } } //text var text = UILabel.create(_ent) Control.set_id(text, "dir text") Control.child_add(colParent, text) UILabel.set_font(text, _ui.font) UILabel.set_text_size(text, 8) UILabel.set_align_vertical(text, TextAlign.top) Control.set_behave(text, UIBehave.left) //| Control.set_margin(text, 4, 8, 4, 0) adventure.on_change(true) { |val| if(val == null) return //this stuff does bad things var dir = StringUtil.direction(val.direction) var dist = val.distance UILabel.set_text(text, "%(dist)km\n%(dir)") } } people(){ var page = Control.create(_ent) Control.child_add(_root, page) Control.set_behave(page, UIBehave.fill) Control.set_margin(page, 0, 0, 0, 16) _page.on_change(true){|val| Control.set_visible(page, val == UiAdventure.people) } _game.focus.on_change(true) {|val| if(!val) return if(_ui.ui_mode == Ui.Planning && _page.value == UiAdventure.people){ var adventure = adventure if(adventure.value && !adventure.value.adventurers.contains(val)) { adventure.value.adventurers.insert(0, val) adventure.emit() } } } var list = UiScrollBox.create(_ent) Control.child_add(page, list) Control.set_behave(list, UIBehave.fill) Control.set_margin(list, 40, 0, 0, 0) var tiny_head = Assets.image("assets/wip/8Head") var x_image = Assets.image("assets/wip/8Cross") _adventurerListItems = [] adventure.on_change(true) {|planning| //cleanup _adventurerListItems.each{|item| Control.destroy(item) } _adventurerListItems.clear() if(!planning) return //rebuild var i = -1 planning.adventurers.each{ |adventurer| i = i + 1 var item = UIBox.create(_ent) Control.set_behave(item, UIBehave.left | UIBehave.right)//| Control.set_margin(item, 0, 0, 0, 0) Control.set_contain(item, UIContain.row | UIContain.start)//| Control.set_size(item, -1, 12) Control.set_id(item, "Person %(i) : %(adventurer.name)") 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) var head = UIImage.create(_ent) Control.child_add(item, head) Control.set_size(head, 8, 8) UIImage.set_image(head, tiny_head) UIImage.set_color(head, adventurer.color) Control.set_margin(head, 2, 0, 0, 0) var name = UILabel.create(_ent) Control.child_add(item, name) UILabel.set_align_vertical(name, TextAlign.bottom) UILabel.set_font(name, _ui.font) UILabel.set_text_size(name, 8) UILabel.set_text(name, adventurer.name) Control.set_behave(name, UIBehave.hfill | UIBehave.left)//| Control.set_margin(name, 2, 1, 0, 1) 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)) Control.set_margin(remove, 0, 0, 2, 0) Clickable.set_tooltip(remove, "remove") Clickable.set_on_click(remove) { Frame.end{ Globals["Tooltip"].clear(remove) Lists.remove(planning.adventurers, adventurer) adventure.emit() } } _adventurerListItems.add(item) } UI.commit(_ent) } } resources(){ var page = Control.create(_ent) Control.child_add(_root, page) Control.set_behave(page, UIBehave.fill) Control.set_margin(page, 0, 0, 0, 16) _page.on_change(true){|val| Control.set_visible(page, val == UiAdventure.resources) } var list = UiScrollBox.create(_ent) UiScrollBox.set_drag_cancelled(list, false) Control.child_add(page, list) Control.set_behave(list, UIBehave.fill) Control.set_margin(list, 40, 0, 0, 0) var x_image = Assets.image("assets/wip/8Cross") _itemListItems = [] _itemEvents = MultiListenerToken.new() adventure.on_change(true) {|adventure| //cleanup _itemListItems.each{|item| Control.destroy(item) } _itemListItems.clear() _itemEvents.discard() if(!adventure) return //rebuild _game.resources.list().each{ |resource| var item = UIBox.create(_ent) Control.set_behave(item, UIBehave.left | UIBehave.right)//| Control.set_margin(item, 0, 0, 0, 0) Control.set_contain(item, UIContain.row | UIContain.start)//| Control.set_size(item, -1, 12) UiScrollBox.add(list, item) var name = UILabel.create(_ent) Control.child_add(item, name) UILabel.set_align_vertical(name, TextAlign.bottom) UILabel.set_font(name, _ui.font) UILabel.set_text_size(name, 8) UILabel.set_text(name, "%(resource["name"])(%(resource["amount"]))") Control.set_behave(name, UIBehave.hfill | UIBehave.left)//| Control.set_margin(name, 2, 1, 0, 1) var amount = NumberField.create(_ent) NumberField.set_value(amount, adventure.resources.get(resource["name"])) Control.set_margin(amount, 0, 1, 2, 1) Control.child_add(item, amount) //change resource data Control.set_events(amount){|event| if(event.type == UIEvent.change){ var value = Math.clamp(event.change.round, 0, resource["amount"]) adventure.resources.set(resource["base_name"], value) } } //change ui on resource data change var token = adventure.resources.on_change{|value| NumberField.set_value(amount, value.get(resource["base_name"])) } _itemEvents.add(token) _itemListItems.add(item) } UI.commit(_ent) } } depart(){ var page = Control.create(_ent) Control.child_add(_root, page) Control.set_behave(page, UIBehave.fill) Control.set_margin(page, 0, 0, 0, 16) _page.on_change(true){|val| Control.set_visible(page, val == UiAdventure.depart) } var ready = UILabel.create(_ent) Control.child_add(page, ready) Control.set_size(ready, 100, 20) UILabel.set_align_vertical(ready, TextAlign.bottom) UILabel.set_font(ready, _ui.font) UILabel.set_text_size(ready, 16) UILabel.set_text(ready, "READY?") Control.set_behave(ready, UIBehave.left | UIBehave.top) //| Control.set_margin(ready, 56, 8, 0, 0) var go = UILabel.create(_ent) Control.child_add(page, go) Control.set_size(go, 100, 20) UILabel.set_align_vertical(go, TextAlign.bottom) UILabel.set_font(go, _ui.font) UILabel.set_text_size(go, 16) UILabel.set_text(go, "GO") UILabel.set_color(go, [1,1,1,1]) UILabel.set_color_hover(go, [1,1,1,1]) Control.set_behave(go, UIBehave.left | UIBehave.top) //| Control.set_margin(go, 56, 24, 0, 0) Clickable.make_clickable(go) Clickable.set_state_change(go){ |data, button| UILabel.set_text(go, data["hover"]?"GO!":"GO") } Clickable.set_on_click(go){ _game.adventures.dispatch() } } abort(){ var page = Control.create(_ent) Control.child_add(_root, page) Control.set_behave(page, UIBehave.fill) Control.set_margin(page, 0, 0, 0, 16) _page.on_change(true){|val| Control.set_visible(page, val == UiAdventure.abort) } var ready = UILabel.create(_ent) Control.child_add(page, ready) Control.set_size(ready, 100, 10) UILabel.set_align_vertical(ready, TextAlign.bottom) UILabel.set_font(ready, _ui.font) UILabel.set_text_size(ready, 8) UILabel.set_text(ready, "This will discard the adventure") Control.set_behave(ready, UIBehave.left | UIBehave.top) //| Control.set_margin(ready, 12, 0, 0, 0) UILabel.set_color(ready, [0.7, 0.7, 0.7, 1]) var abort = UILabel.create(_ent) Control.child_add(page, abort) Control.set_size(abort, 100, 20) UILabel.set_align_vertical(abort, TextAlign.bottom) UILabel.set_align(abort, TextAlign.right) UILabel.set_font(abort, _ui.font) UILabel.set_text_size(abort, 16) UILabel.set_text(abort, "ABORT") UILabel.set_color(abort, [1,1,1,1]) UILabel.set_color_hover(abort, [1,1,1,1]) Control.set_behave(abort, UIBehave.left | UIBehave.top) //| Control.set_margin(abort, 25, 8, 0, 0) Clickable.make_clickable(abort) Clickable.set_state_change(abort){ |data, button| UILabel.set_text(abort, data["hover"]?"ABORT!":"ABORT") } Clickable.set_on_click(abort){ _game.adventures.discard() } } }