Merge branch 'euc_vox' into 'master'

Add ability to use vox files as images for ui elements

See merge request veloren/veloren!52

Former-commit-id: 2f8c48701161311365c752da9293d3cc41ef8957
This commit is contained in:
Dominik Broński 2019-04-20 13:22:34 +00:00
commit e02e2da58b
13 changed files with 655 additions and 216 deletions

72
Cargo.lock generated
View File

@ -414,13 +414,13 @@ dependencies = [
[[package]]
name = "dot_vox"
version = "1.0.1"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -461,6 +461,33 @@ dependencies = [
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "euc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "euclid"
version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "euclid_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure"
version = "0.1.5"
@ -668,6 +695,14 @@ dependencies = [
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "guillotiere"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hibitset"
version = "0.5.4"
@ -862,14 +897,6 @@ dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.2.0"
@ -970,14 +997,6 @@ dependencies = [
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nom"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nom"
version = "4.2.3"
@ -1898,7 +1917,7 @@ name = "veloren-common"
version = "0.2.0"
dependencies = [
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1942,13 +1961,16 @@ dependencies = [
"config 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
"conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
"dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_device_gl 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx_window_glutin 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glsl-include 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
"guillotiere 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2209,12 +2231,15 @@ dependencies = [
"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86"
"checksum derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6073e9676dbebdddeabaeb63e3b7cefd23c86f5c41d381ee1237cc77b1079898"
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
"checksum dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa4d1fc391ef151fff024e8427d206af1adbef4281fcd875090f74697000441"
"checksum dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11afd3251e588f2770226659b2a1d55ec2f8aaf2ca42bdcdbd01ff53b4a81e70"
"checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f"
"checksum draw_state 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651"
"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a"
"checksum euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0151594c4feeeb99ff35ac1b467383a46fcb2705275615bed0a47f25ffe2ccf8"
"checksum euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7a4719a544a67ed3fc33784c2bd2c6581663dfe83b719a6ae05c6dabc3b51c73"
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
@ -2238,6 +2263,7 @@ dependencies = [
"checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5"
"checksum glsl-include 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31c109a006ad24fd612da10d185b51000ef502155578f3634416f102f0d63b6c"
"checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3"
"checksum guillotiere 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e965c66630b3a0369feafb06d945f15a4f59aaecc209eb1c4a2b57bb48ee06"
"checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0"
"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114"
"checksum image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "545f000e8aa4e569e93f49c446987133452e0091c2494ac3efd3606aa3d309f2"
@ -2263,7 +2289,6 @@ dependencies = [
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
@ -2275,7 +2300,6 @@ dependencies = [
"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum noise 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a3a34d4f8a31f95919b7ead9f5b60afb9bda0cae98b9219432ffaa6f00b0141"
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
"checksum nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "02783a0482333b0d3f5f5411b8fb60454a596696da041da0470ac9ef3e6e37d8"
"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db"

View File

@ -10,7 +10,7 @@ sphynx = { git = "https://gitlab.com/veloren/sphynx.git", features = ["serde1"]
specs = { version = "0.14", features = ["serde"] }
shred = { version = "0.7", features = ["nightly"] }
vek = { version = "0.9", features = ["serde"] }
dot_vox = "1.0"
dot_vox = "4.0"
threadpool = "1.7"
mio = "0.6"
mio-extras = "2.0"

View File

@ -22,6 +22,7 @@ glutin = "0.19"
winit = {version = "0.18", features = ["serde"]}
conrod_core = { git = "https://gitlab.com/veloren/conrod.git" }
conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" }
euc = "0.2"
# ECS
specs = "0.14"
@ -35,9 +36,11 @@ failure = "0.1"
lazy_static = "1.1"
log = "0.4"
pretty_env_logger = "0.3"
dot_vox = "1.0"
dot_vox = "4.0"
image = "0.21"
config = "0.9"
serde = "1.0"
serde_derive = "1.0"
toml = "0.4"
guillotiere = "0.4"
fnv = "1.0"

View File

@ -2,7 +2,7 @@ mod chat;
use crate::{
render::Renderer,
ui::{ScaleMode, ToggleButton, Ui},
ui::{self, ScaleMode, ToggleButton, Ui},
window::{Event as WinEvent, Key, Window},
};
use common::assets;
@ -144,7 +144,7 @@ widget_ids! {
pub(self) struct Imgs {
//Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame
//Logo
v_logo: ImgId,
//v_logo: ImgId,
// Bag
bag: ImgId,
bag_hover: ImgId,
@ -249,7 +249,7 @@ pub(self) struct Imgs {
}
impl Imgs {
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
let mut load = |filename| {
let mut load = |filename, ui: &mut Ui| {
let fullpath: String = ["/voxygen/", filename].concat();
let image = image::load_from_memory(
assets::load(fullpath.as_str())
@ -257,117 +257,116 @@ impl Imgs {
.as_slice(),
)
.unwrap();
ui.new_image(renderer, &image).unwrap()
ui.new_graphic(ui::Graphic::Image(image))
};
Imgs {
// Bag
bag: load("element/buttons/bag/closed.png"),
bag_hover: load("element/buttons/bag/closed_hover.png"),
bag_press: load("element/buttons/bag/closed_press.png"),
bag_open: load("element/buttons/bag/open.png"),
bag_open_hover: load("element/buttons/bag/open_hover.png"),
bag_open_press: load("element/buttons/bag/open_press.png"),
bag_contents: load("element/frames/bag.png"),
inv_grid: load("element/frames/inv_grid.png"),
inv_slot: load("element/buttons/inv_slot.png"),
bag: load("element/buttons/bag/closed.png", ui),
bag_hover: load("element/buttons/bag/closed_hover.png", ui),
bag_press: load("element/buttons/bag/closed_press.png", ui),
bag_open: load("element/buttons/bag/open.png", ui),
bag_open_hover: load("element/buttons/bag/open_hover.png", ui),
bag_open_press: load("element/buttons/bag/open_press.png", ui),
bag_contents: load("element/frames/bag.png", ui),
inv_grid: load("element/frames/inv_grid.png", ui),
inv_slot: load("element/buttons/inv_slot.png", ui),
// Close button
close_button: load("element/buttons/x.png"),
close_button_hover: load("element/buttons/x_hover.png"),
close_button_press: load("element/buttons/x_press.png"),
close_button: load("element/buttons/x.png", ui),
close_button_hover: load("element/buttons/x_hover.png", ui),
close_button_press: load("element/buttons/x_press.png", ui),
// Esc-Menu
esc_bg: load("element/frames/menu.png"),
fireplace: load("element/misc_backgrounds/fireplace.png"),
button_dark: load("element/buttons/button_dark.png"),
button_dark_hover: load("element/buttons/button_dark_hover.png"),
button_dark_press: load("element/buttons/button_dark_press.png"),
esc_bg: load("element/frames/menu.png", ui),
fireplace: load("element/misc_backgrounds/fireplace.png", ui),
button_dark: load("element/buttons/button_dark.png", ui),
button_dark_hover: load("element/buttons/button_dark_hover.png", ui),
button_dark_press: load("element/buttons/button_dark_press.png", ui),
// MiniMap
mmap_frame: load("element/frames/mmap.png"),
mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png"),
mmap_icons: load("element/buttons/mmap_icons.png"),
mmap_frame: load("element/frames/mmap.png", ui),
mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png", ui),
mmap_icons: load("element/buttons/mmap_icons.png", ui),
// Settings at Mini-Map
mmap_button: load("element/buttons/border.png"),
mmap_button_hover: load("element/buttons/border_mo.png"),
mmap_button_press: load("element/buttons/border_press.png"),
mmap_button_open: load("element/buttons/border_pressed.png"),
mmap_button: load("element/buttons/border.png", ui),
mmap_button_hover: load("element/buttons/border_mo.png", ui),
mmap_button_press: load("element/buttons/border_press.png", ui),
mmap_button_open: load("element/buttons/border_pressed.png", ui),
// Skillbar Module
sb_grid: load("element/skill_bar/sbar_grid.png"),
sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png"),
l_click: load("element/skill_bar/l.png"),
r_click: load("element/skill_bar/r.png"),
mana_bar: load("element/skill_bar/mana_bar.png"),
health_bar: load("element/skill_bar/health_bar.png"),
xp_bar: load("element/skill_bar/xp_bar.png"),
sb_grid: load("element/skill_bar/sbar_grid.png", ui),
sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png", ui),
l_click: load("element/skill_bar/l.png", ui),
r_click: load("element/skill_bar/r.png", ui),
mana_bar: load("element/skill_bar/mana_bar.png", ui),
health_bar: load("element/skill_bar/health_bar.png", ui),
xp_bar: load("element/skill_bar/xp_bar.png", ui),
//Buff Frame(s)
//buff_frame: load("element/skill_bar/buff_frame.png"),
//buff_frame_bg: load("element/skill_bar/buff_frame_bg.png"),
//buff_frame_red: load("element/skill_bar/buff_frame_red.png"),
//buff_frame_green: load("element/skill_bar/buff_frame_green.png"),
//buff_frame: load("element/skill_bar/buff_frame.png", ui),
//buff_frame_bg: load("element/skill_bar/buff_frame_bg.png", ui),
//buff_frame_red: load("element/skill_bar/buff_frame_red.png", ui),
//buff_frame_green: load("element/skill_bar/buff_frame_green.png", ui),
//Missing: Buff Frame Animation (.gif ?!) (we could do animation in ui.maintain(), or in shader?)
window_frame: load("element/frames/window.png"),
window_frame_2: load("element/frames/window_2.png"),
window_frame: load("element/frames/window.png", ui),
window_frame_2: load("element/frames/window_2.png", ui),
//Settings Window
settings_bg: load("element/frames/settings.png"),
settings_icon: load("element/icons/settings.png"),
settings_button_mo: load("element/buttons/blue_mo.png"),
check: load("element/buttons/check/no.png"),
check_mo: load("element/buttons/check/no_mo.png"),
check_press: load("element/buttons/check/press.png"),
check_checked: load("element/buttons/check/yes.png"),
check_checked_mo: load("element/buttons/check/yes_mo.png"),
slider: load("element/slider/track.png"),
slider_indicator: load("element/slider/indicator.png"),
button_blank: load("element/nothing.png"),
button_blue_mo: load("element/buttons/blue_mo.png"),
button_blue_press: load("element/buttons/blue_press.png"),
settings_bg: load("element/frames/settings.png", ui),
settings_icon: load("element/icons/settings.png", ui),
settings_button_mo: load("element/buttons/blue_mo.png", ui),
check: load("element/buttons/check/no.png", ui),
check_mo: load("element/buttons/check/no_mo.png", ui),
check_press: load("element/buttons/check/press.png", ui),
check_checked: load("element/buttons/check/yes.png", ui),
check_checked_mo: load("element/buttons/check/yes_mo.png", ui),
slider: load("element/slider/track.png", ui),
slider_indicator: load("element/slider/indicator.png", ui),
button_blank: ui.new_graphic(ui::Graphic::Blank),
button_blue_mo: load("element/buttons/blue_mo.png", ui),
button_blue_press: load("element/buttons/blue_press.png", ui),
// Window BG
window_bg: load("element/misc_backgrounds/window_bg.png"),
v_logo: load("element/v_logo.png"),
window_bg: load("element/misc_backgrounds/window_bg.png", ui),
//Social Window
social_bg: load("element/misc_backgrounds/small_bg.png"),
social_icon: load("element/icons/social.png"),
social_bg: load("element/misc_backgrounds/small_bg.png", ui),
social_icon: load("element/icons/social.png", ui),
//Map Window
map_bg: load("element/misc_backgrounds/small_bg.png"),
map_icon: load("element/icons/map.png"),
map_frame: load("element/frames/window_map.png"),
map_bg: load("element/misc_backgrounds/small_bg.png", ui),
map_icon: load("element/icons/map.png", ui),
map_frame: load("element/frames/window_map.png", ui),
// Spell Book Window
spellbook_bg: load("element/misc_backgrounds/small_bg.png"),
spellbook_icon: load("element/icons/spellbook.png"),
spellbook_bg: load("element/misc_backgrounds/small_bg.png", ui),
spellbook_icon: load("element/icons/spellbook.png", ui),
//Char Window
charwindow: load("element/misc_backgrounds/charwindow.png"),
charwindow_icon: load("element/icons/charwindow.png"),
charwindow_tab_bg: load("element/frames/tab.png"),
charwindow_tab: load("element/buttons/tab.png"),
charwindow_expbar: load("element/misc_backgrounds/small_bg.png"),
progress_frame: load("element/frames/progress_bar.png"),
progress: load("element/misc_backgrounds/progress.png"),
charwindow: load("element/misc_backgrounds/charwindow.png", ui),
charwindow_icon: load("element/icons/charwindow.png", ui),
charwindow_tab_bg: load("element/frames/tab.png", ui),
charwindow_tab: load("element/buttons/tab.png", ui),
charwindow_expbar: load("element/misc_backgrounds/small_bg.png", ui),
progress_frame: load("element/frames/progress_bar.png", ui),
progress: load("element/misc_backgrounds/progress.png", ui),
//Quest-Log Window
questlog_bg: load("element/misc_backgrounds/small_bg.png"),
questlog_icon: load("element/icons/questlog.png"),
questlog_bg: load("element/misc_backgrounds/small_bg.png", ui),
questlog_icon: load("element/icons/questlog.png", ui),
// Chat-Arrows
chat_arrow: load("element/buttons/arrow/chat_arrow.png"),
chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png"),
chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png"),
chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png"),
chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png"),
chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png"),
chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png"),
chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png"),
chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png"),
chat_arrow: load("element/buttons/arrow/chat_arrow.png", ui),
chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png", ui),
chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png", ui),
chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png", ui),
chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png", ui),
chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png", ui),
chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png", ui),
chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png", ui),
chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png", ui),
}
}
}

View File

@ -235,7 +235,7 @@ impl Imgs {
.as_slice(),
)
.unwrap();
ui.new_image(renderer, &image).unwrap()
ui.new_graphic(ui::Graphic::Image(image))
};
Imgs {
v_logo: load("element/v_logo.png"),

View File

@ -4,7 +4,10 @@ use crate::{
window::Window,
DEFAULT_PUBLIC_SERVER,
};
use common::assets;
use common::{
assets,
figure::Segment,
};
use conrod_core::{
color,
color::TRANSPARENT,
@ -65,8 +68,7 @@ struct Imgs {
}
impl Imgs {
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
// TODO: update paths
let mut load = |filename| {
let mut load_img = |filename, ui: &mut Ui| {
let fullpath: String = ["/voxygen/", filename].concat();
let image = image::load_from_memory(
assets::load(fullpath.as_str())
@ -74,30 +76,41 @@ impl Imgs {
.as_slice(),
)
.unwrap();
ui.new_image(renderer, &image).unwrap()
ui.new_graphic(ui::Graphic::Image(image))
};
let mut load_vox = |filename, ui: &mut Ui| {
let fullpath: String = ["/voxygen/", filename].concat();
let dot_vox = dot_vox::load_bytes(
assets::load(fullpath.as_str())
.expect("Error loading file")
.as_slice(),
)
.unwrap();
ui.new_graphic(ui::Graphic::Voxel(Segment::from(dot_vox)))
};
Imgs {
bg: load("background/bg_main.png"),
v_logo: load("element/v_logo.png"),
bg: load_img("background/bg_main.png", ui),
v_logo: load_img("element/v_logo.png", ui),
// Input fields
input_bg: load("element/misc_backgrounds/textbox.png"),
input_bg: load_img("element/misc_backgrounds/textbox.png", ui),
// Login button
login_button: load("element/buttons/button_login.png"),
login_button_hover: load("element/buttons/button_login_hover.png"),
login_button_press: load("element/buttons/button_login_press.png"),
login_button: load_img("element/buttons/button_login.png", ui),
login_button_hover: load_img("element/buttons/button_login_hover.png", ui),
login_button_press: load_img("element/buttons/button_login_press.png", ui),
// Servers, settings, and quit buttons
button: load("element/buttons/button.png"),
button_hover: load("element/buttons/button_hover.png"),
button_press: load("element/buttons/button_press.png"),
//button: load_vox("element/buttons/button.vox", ui),
button: load_img("element/buttons/button.png", ui),
button_hover: load_img("element/buttons/button_hover.png", ui),
button_press: load_img("element/buttons/button_press.png", ui),
//Error
error_frame: load("element/frames/window_2.png"),
button_dark: load("element/buttons/button_dark.png"),
button_dark_hover: load("element/buttons/button_dark_hover.png"),
button_dark_press: load("element/buttons/button_dark_press.png"),
error_frame: load_img("element/frames/window_2.png", ui),
button_dark: load_img("element/buttons/button_dark.png", ui),
button_dark_hover: load_img("element/buttons/button_dark_hover.png", ui),
button_dark_press: load_img("element/buttons/button_dark_press.png", ui),
}
}
}

View File

@ -65,13 +65,13 @@ impl Mode {
}
}
pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: [f32; 4], mode: Mode) -> Quad<UiPipeline> {
pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: Rgba<f32>, mode: Mode) -> Quad<UiPipeline> {
let mode_val = mode.value();
let v = |pos, uv| {
Vertex {
pos,
uv,
color,
color: color.into_array(),
mode: mode_val,
}
};
@ -90,13 +90,13 @@ pub fn create_quad(rect: Aabr<f32>, uv_rect: Aabr<f32>, color: [f32; 4], mode: M
)
}
pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: [f32; 4], mode: Mode) -> Tri<UiPipeline> {
pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: Rgba<f32>, mode: Mode) -> Tri<UiPipeline> {
let mode_val = mode.value();
let v = |pos, uv| {
Vertex {
pos,
uv,
color,
color: color.into_array(),
mode: mode_val,
}
};

View File

@ -81,7 +81,7 @@ impl<P: Pipeline> Texture<P> {
tex,
srv,
sampler: factory.create_sampler(gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Bilinear,
gfx::texture::FilterMethod::Scale,
gfx::texture::WrapMode::Clamp,
)),
_phantom: PhantomData,

View File

@ -0,0 +1,115 @@
use common::figure::Segment;
use fnv::FnvHashMap;
use guillotiere::{size2, Allocation, AtlasAllocator};
use image::DynamicImage;
use vek::*;
pub enum Graphic {
Image(DynamicImage),
Voxel(Segment),
Blank,
}
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
pub struct Id(u32);
type Parameters = (Id, Vec2<u16>, Aabr<u64>);
pub struct GraphicCache {
atlas: AtlasAllocator,
graphic_map: FnvHashMap<Id, Graphic>,
rect_map: FnvHashMap<Parameters, Aabr<u16>>,
next_id: u32,
}
impl GraphicCache {
pub fn new(size: Vec2<u16>) -> Self {
Self {
atlas: AtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y))),
graphic_map: FnvHashMap::default(),
rect_map: FnvHashMap::default(),
next_id: 0,
}
}
pub fn new_graphic(&mut self, graphic: Graphic) -> Id {
let id = self.next_id;
self.next_id = id.wrapping_add(1);
let id = Id(id);
self.graphic_map.insert(id, graphic);
id
}
pub fn get_graphic(&self, id: Id) -> Option<&Graphic> {
self.graphic_map.get(&id)
}
pub fn clear_cache(&mut self, new_size: Vec2<u16>) {
self.rect_map.clear();
self.atlas = AtlasAllocator::new(size2(i32::from(new_size.x), i32::from(new_size.y)));
}
pub fn cache_res<F>(
&mut self,
graphic_id: Id,
dims: Vec2<u16>,
source: Aabr<f64>,
mut cacher: F,
) -> Option<Aabr<u16>>
where
F: FnMut(Aabr<u16>, Vec<[u8; 4]>),
{
match self
.rect_map
.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) //<-------- TODO: Replace this with rounded representation of source
{
Some(aabr) => Some(*aabr),
None => match self.graphic_map.get(&graphic_id) {
Some(graphic) => {
// Allocate rectangle
let aabr = match self
.atlas
.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
{
Some(Allocation { id, rectangle }) => {
let (min, max) = (rectangle.min, rectangle.max);
Aabr {
min: Vec2::new(min.x as u16, min.y as u16),
max: Vec2::new(max.x as u16, max.y as u16),
}
}
// Out of room
// TODO: make more room by 1. expanding cache size, 2. removing unused allocations, 3. rearranging rectangles
None => return None,
};
// Render image
// TODO: use source
let data = match graphic {
Graphic::Image(ref image) => image
.resize_exact(
u32::from(aabr.size().w),
u32::from(aabr.size().h),
image::FilterType::Nearest,
)
.to_rgba()
.pixels()
.map(|p| p.data)
.collect::<Vec<[u8; 4]>>(),
Graphic::Voxel(segment) => {
super::renderer::draw_vox(&segment, aabr.size().into())
}
Graphic::Blank => return None,
};
// Draw to allocated area
cacher(aabr, data);
// Insert area into map for retrieval
self.rect_map
.insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr);
// Return area
Some(aabr)
}
None => None,
},
}
}
}

View File

@ -0,0 +1,4 @@
mod graphic;
mod renderer;
pub use graphic::{Graphic, GraphicCache, Id};

View File

@ -0,0 +1,218 @@
use super::super::{linear_to_srgb, srgb_to_linear};
use common::{
figure::Segment,
vol::{ReadVol, SizedVol, Vox},
};
use euc::{buffer::Buffer2d, rasterizer, Pipeline};
use vek::*;
struct Voxel {
mvp: Mat4<f32>,
}
#[derive(Copy, Clone)]
struct Vert {
pos: Vec3<f32>,
col: Rgb<f32>,
norm: Vec3<f32>,
ao_level: u8,
}
impl Vert {
fn new(pos: Vec3<f32>, col: Rgb<f32>, norm: Vec3<f32>, ao_level: u8) -> Self {
Vert {
pos,
col,
norm,
ao_level,
}
}
}
impl<'a> Pipeline for Voxel {
type Vertex = Vert;
type VsOut = Rgba<f32>;
type Pixel = [u8; 4];
#[inline(always)]
fn vert(
&self,
Vert {
pos,
col,
norm,
ao_level,
}: &Self::Vertex,
) -> ([f32; 3], Self::VsOut) {
let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25));
let color = light * srgb_to_linear(Rgba::from_opaque(*col));
let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array();
(position, color)
}
#[inline(always)]
fn frag(&self, color: &Self::VsOut) -> Self::Pixel {
linear_to_srgb(*color)
.map(|e| (e * 255.0) as u8)
.into_array()
}
}
pub fn draw_vox(segment: &Segment, output_size: Vec2<u16>) -> Vec<[u8; 4]> {
let dims = output_size.map(|e| e as usize).into_array();
let mut color = Buffer2d::new(dims, [0; 4]);
let mut depth = Buffer2d::new(dims, 1.0);
let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple();
let mvp = Mat4::<f32>::orthographic_rh_no(FrustumPlanes {
left: -1.0,
right: 1.0,
bottom: -1.0,
top: 1.0,
near: 0.0,
far: 1.0,
}) * Mat4::rotation_x(-std::f32::consts::PI / 2.0)
* Mat4::scaling_3d([2.0 / w, 2.0 / h, 2.0 / d])
* Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]);
Voxel { mvp }.draw::<rasterizer::Triangles<_>, _>(
&generate_mesh(segment, Vec3::from(0.0)),
&mut color,
&mut depth,
);
// TODO: remove this clone
color.as_ref().to_vec()
}
fn ao_level(side1: bool, corner: bool, side2: bool) -> u8 {
if side1 && side2 {
0
} else {
3 - [side1, corner, side2].iter().filter(|e| **e).count() as u8
}
}
// TODO: generalize meshing code....
fn create_quad(
origin: Vec3<f32>,
unit_x: Vec3<f32>,
unit_y: Vec3<f32>,
norm: Vec3<f32>,
col: Rgb<f32>,
occluders: [bool; 8],
) -> [Vert; 6] {
let a_ao = ao_level(occluders[0], occluders[1], occluders[2]);
let b_ao = ao_level(occluders[2], occluders[3], occluders[4]);
let c_ao = ao_level(occluders[4], occluders[5], occluders[6]);
let d_ao = ao_level(occluders[6], occluders[7], occluders[0]);
let a = Vert::new(origin, col, norm, a_ao);
let b = Vert::new(origin + unit_x, col, norm, b_ao);
let c = Vert::new(origin + unit_x + unit_y, col, norm, c_ao);
let d = Vert::new(origin + unit_y, col, norm, d_ao);
// Flip to fix anisotropy
let (a, b, c, d) = if a_ao + c_ao > b_ao + d_ao {
(d, a, b, c)
} else {
(a, b, c, d)
};
[
a, b, c, // Tri 1
c, d, a, // Tri 2
]
}
fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
let mut vertices = Vec::new();
for pos in segment.iter_positions() {
if let Some(col) = segment.get(pos).ok().and_then(|vox| vox.get_color()) {
let col = col.map(|e| e as f32 / 255.0);
let is_empty = |pos| segment.get(pos).map(|v| v.is_empty()).unwrap_or(true);
let occluders = |unit_x, unit_y, dir| {
// would be nice to generate unit_x and unit_y from a given direction
[
!is_empty(pos + dir - unit_x),
!is_empty(pos + dir - unit_x - unit_y),
!is_empty(pos + dir - unit_y),
!is_empty(pos + dir + unit_x - unit_y),
!is_empty(pos + dir + unit_x),
!is_empty(pos + dir + unit_x + unit_y),
!is_empty(pos + dir + unit_y),
!is_empty(pos + dir - unit_x + unit_y),
]
};
// -x
if is_empty(pos - Vec3::unit_x()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32) + Vec3::unit_y(),
-Vec3::unit_y(),
Vec3::unit_z(),
-Vec3::unit_x(),
col,
occluders(-Vec3::unit_y(), Vec3::unit_z(), -Vec3::unit_x()),
));
}
// +x
if is_empty(pos + Vec3::unit_x()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32) + Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
col,
occluders(Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x()),
));
}
// -y
if is_empty(pos - Vec3::unit_y()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32),
Vec3::unit_x(),
Vec3::unit_z(),
-Vec3::unit_y(),
col,
occluders(Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y()),
));
}
// +y
if is_empty(pos + Vec3::unit_y()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32) + Vec3::unit_y(),
Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
col,
occluders(Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y()),
));
}
// -z
if is_empty(pos - Vec3::unit_z()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32),
Vec3::unit_y(),
Vec3::unit_x(),
-Vec3::unit_z(),
col,
occluders(Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z()),
));
}
// +z
if is_empty(pos + Vec3::unit_z()) {
vertices.extend_from_slice(&create_quad(
offs + pos.map(|e| e as f32) + Vec3::unit_z(),
Vec3::unit_x(),
Vec3::unit_y(),
Vec3::unit_z(),
col,
occluders(Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()),
));
}
}
}
vertices
}

View File

@ -1,8 +1,15 @@
mod widgets;
mod graphic;
mod util;
pub use widgets::toggle_button::ToggleButton;
pub use graphic::Graphic;
pub(self) use util::{srgb_to_linear, linear_to_srgb};
use image::DynamicImage;
use graphic::{
GraphicCache,
Id as GraphicId,
};
use conrod_core::{
Ui as CrUi,
UiBuilder,
@ -16,7 +23,7 @@ use conrod_core::{
widget::{Id as WidgId, id::Generator},
render::Primitive,
event::Input,
input::{touch::Touch, Widget, Motion, Button, MouseButton},
input::{touch::Touch, Widget, Motion, Button},
};
use vek::*;
use crate::{
@ -81,9 +88,10 @@ impl Event {
}
pub struct Cache {
blank_texture: Texture<UiPipeline>,
glyph_cache: GlyphCache<'static>,
glyph_cache_tex: Texture<UiPipeline>,
graphic_cache: graphic::GraphicCache,
graphic_cache_tex: Texture<UiPipeline>,
}
// TODO: Should functions be returning UiError instead of Error?
@ -93,23 +101,31 @@ impl Cache {
const SCALE_TOLERANCE: f32 = 0.1;
const POSITION_TOLERANCE: f32 = 0.1;
let graphic_cache_dims = Vec2::new(w * 4, h * 4);
Ok(Self {
blank_texture: renderer.create_texture(&DynamicImage::new_rgba8(1, 1))?,
glyph_cache: GlyphCache::builder()
.dimensions(w as u32, h as u32)
.scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE)
.build(),
glyph_cache_tex: renderer.create_dynamic_texture((w, h).into())?,
graphic_cache: GraphicCache::new(graphic_cache_dims),
graphic_cache_tex: renderer.create_dynamic_texture(graphic_cache_dims)?,
})
}
pub fn blank_texture(&self) -> &Texture<UiPipeline> { &self.blank_texture }
pub fn glyph_cache_tex(&self) -> &Texture<UiPipeline> { &self.glyph_cache_tex }
pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphCache<'static>, &Texture<UiPipeline>) { (&mut self.glyph_cache, &self.glyph_cache_tex) }
pub fn graphic_cache_tex(&self) -> &Texture<UiPipeline> { &self.graphic_cache_tex }
pub fn graphic_cache_mut_and_tex(&mut self) -> (&mut GraphicCache, &Texture<UiPipeline>) { (&mut self.graphic_cache, &self.graphic_cache_tex) }
pub fn new_graphic(&mut self, graphic: Graphic) -> GraphicId { self.graphic_cache.new_graphic(graphic) }
pub fn clear_graphic_cache(&mut self, renderer: &mut Renderer, new_size: Vec2<u16>) {
self.graphic_cache.clear_cache(new_size);
self.graphic_cache_tex = renderer.create_dynamic_texture(new_size).unwrap();
}
}
enum DrawKind {
Image(ImgId),
Image,
// Text and non-textured geometry
Plain,
}
@ -121,9 +137,9 @@ enum DrawCommand {
Scissor(Aabr<u16>),
}
impl DrawCommand {
fn image(model: Model<UiPipeline>, img_id: ImgId) -> DrawCommand {
fn image(model: Model<UiPipeline>) -> DrawCommand {
DrawCommand::Draw {
kind: DrawKind::Image(img_id),
kind: DrawKind::Image,
model,
}
}
@ -198,7 +214,7 @@ impl Scale {
pub struct Ui {
ui: CrUi,
image_map: Map<Texture<UiPipeline>>,
image_map: Map<GraphicId>,
cache: Cache,
// Draw commands for the next render
draw_commands: Vec<DrawCommand>,
@ -230,8 +246,8 @@ impl Ui {
self.ui.handle_event(Input::Resize(w, h));
}
pub fn new_image(&mut self, renderer: &mut Renderer, image: &DynamicImage) -> Result<ImgId, Error> {
Ok(self.image_map.insert(renderer.create_texture(image)?))
pub fn new_graphic(&mut self, graphic: Graphic) -> ImgId {
self.image_map.insert(self.cache.new_graphic(graphic))
}
pub fn new_font(&mut self, font: Font) -> FontId {
@ -246,7 +262,7 @@ impl Ui {
self.ui.set_widgets()
}
// Accepts option so widget can be unfocused
// Accepts Option so widget can be unfocused
pub fn focus_widget(&mut self, id: Option<WidgId>) {
self.ui.keyboard_capture(match id {
Some(id) => id,
@ -259,7 +275,7 @@ impl Ui {
self.ui.global_input().current.widget_capturing_keyboard
}
// Get whether the a widget besides the window is capturing the mouse
// Get whether a widget besides the window is capturing the mouse
pub fn no_widget_capturing_mouse(&self) -> bool {
self.ui.global_input().current.widget_capturing_mouse.filter(|id| id != &self.ui.window ).is_none()
}
@ -305,7 +321,14 @@ impl Ui {
self.draw_commands.clear();
let mut mesh = Mesh::new();
let mut current_img = None;
// TODO: this could be removed entirely if the draw call just used both textures
// however this allows for flexibility if we want to interleave other draw calls later
enum State {
Image,
Plain,
};
let mut current_state = State::Plain;
let window_scizzor = default_scissor(renderer);
let mut current_scizzor = window_scizzor;
@ -314,9 +337,10 @@ impl Ui {
// `Plain` state.
macro_rules! switch_to_plain_state {
() => {
if let Some(image_id) = current_img.take() {
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id));
if let State::Image = current_state {
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap()));
mesh.clear();
current_state = State::Plain;
}
};
}
@ -324,7 +348,7 @@ impl Ui {
let p_scale_factor = self.scale.scale_factor_physical();
while let Some(prim) = primitives.next() {
let Primitive {kind, scizzor, id, rect} = prim;
let Primitive {kind, scizzor, id: _id, rect} = prim;
// Check for a change in the scizzor
let new_scizzor = {
@ -348,12 +372,12 @@ impl Ui {
};
if new_scizzor != current_scizzor {
// Finish the current command
match current_img.take() {
None =>
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())),
Some(image_id) =>
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)),
}
self.draw_commands.push(match current_state {
State::Plain =>
DrawCommand::plain(renderer.create_model(&mesh).unwrap()),
State::Image =>
DrawCommand::image(renderer.create_model(&mesh).unwrap()),
});
mesh.clear();
// Update the scizzor and produce a command.
@ -375,52 +399,64 @@ impl Ui {
use conrod_core::render::PrimitiveKind;
match kind {
PrimitiveKind::Image { image_id, color, source_rect } => {
let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map");
let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex();
// Switch to the `Image` state for this image if we're not in it already.
let new_image_id = image_id;
match current_img {
// If we're already in the drawing mode for this image, we're done.
Some(image_id) if image_id == new_image_id => (),
// If we were in the `Plain` drawing state, switch to Image drawing state.
None => {
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap()));
mesh.clear();
current_img = Some(new_image_id);
}
// If we were drawing a different image, switch state to draw *this* image.
Some(image_id) => {
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id));
mesh.clear();
current_img = Some(new_image_id);
}
match graphic_cache.get_graphic(*graphic_id) {
Some(Graphic::Blank) | None => continue,
_ => {}
}
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa());
// Switch to the `Image` state for this image if we're not in it already.
if let State::Plain = current_state {
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap()));
mesh.clear();
current_state = State::Image;
}
// Transform the source rectangle into uv coordinates
let (image_w, image_h) = self.image_map
.get(&image_id)
.expect("Image does not exist in image map")
.get_dimensions()
.map(|e| e as f64)
.into_tuple();
let (uv_l, uv_r, uv_t, uv_b) = match source_rect {
Some(src_rect) => {
let (l, r, b, t) = src_rect.l_r_b_t();
((l / image_w) as f32,
(r / image_w) as f32,
(b / image_h) as f32,
(t / image_h) as f32)
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
let resolution = Vec2::new(
(rect.w() * p_scale_factor) as u16,
(rect.h() * p_scale_factor) as u16,
);
// Transform the source rectangle into uv coordinate
// TODO: make sure this is right
let source_aabr = {
let (uv_l, uv_r, uv_b, uv_t) = (0.0, 1.0, 0.0, 1.0);/*match source_rect {
Some(src_rect) => {
let (l, r, b, t) = src_rect.l_r_b_t();
((l / image_w) as f32,
(r / image_w) as f32,
(b / image_h) as f32,
(t / image_h) as f32)
}
None => (0.0, 1.0, 0.0, 1.0),
};*/
Aabr {
min: Vec2::new(uv_l, uv_b),
max: Vec2::new(uv_r, uv_t),
}
None => (0.0, 1.0, 0.0, 1.0),
};
let uv = Aabr {
min: Vec2::new(uv_l, uv_b),
max: Vec2::new(uv_r, uv_t),
let (cache_w, cache_h) = cache_tex.get_dimensions().map(|e| e as f32).into_tuple();
// Cache graphic at particular resolution
let uv_aabr = match graphic_cache.cache_res(*graphic_id, resolution, source_aabr, |aabr, data| {
let offset = aabr.min.into_array();
let size = aabr.size().into_array();
renderer.update_texture(cache_tex, offset, size, &data);
}) {
Some(aabr) => Aabr {
min: Vec2::new(aabr.min.x as f32 / cache_w, aabr.max.y as f32 / cache_h),
max: Vec2::new(aabr.max.x as f32 / cache_w, aabr.min.y as f32 / cache_h),
},
None => continue,
};
mesh.push_quad(create_ui_quad(
gl_aabr(rect),
uv,
uv_aabr,
color,
UiMode::Image,
));
@ -449,7 +485,7 @@ impl Ui {
renderer.update_texture(cache_tex, offset, size, &new_data);
}).unwrap();
let color = srgb_to_linear(color.to_fsa());
let color = srgb_to_linear(color.to_fsa().into());
for g in positioned_glyphs {
if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) {
@ -477,7 +513,7 @@ impl Ui {
}
}
PrimitiveKind::Rectangle { color } => {
let color = srgb_to_linear(color.to_fsa());
let color = srgb_to_linear(color.to_fsa().into());
// Don't draw a transparent rectangle
if color[3] == 0.0 {
continue;
@ -497,7 +533,7 @@ impl Ui {
}
PrimitiveKind::TrianglesSingleColor { color, triangles } => {
// Don't draw transparent triangle or switch state if there are actually no triangles
let color: [f32; 4] = srgb_to_linear(color.into());
let color = srgb_to_linear(Rgba::from(Into::<[f32; 4]>::into(color)));
if triangles.is_empty() || color[3] == 0.0 {
continue;
}
@ -529,24 +565,27 @@ impl Ui {
}
_ => {}
// TODO: Add these
//PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);}
// TODO: Add this
//PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);}
// Other uneeded for now
//PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);}
}
}
// Enter the final command
match current_img {
None =>
self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())),
Some(image_id) =>
self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)),
}
self.draw_commands.push(match current_state {
State::Plain =>
DrawCommand::plain(renderer.create_model(&mesh).unwrap()),
State::Image =>
DrawCommand::image(renderer.create_model(&mesh).unwrap()),
});
// Handle window resizing
if let Some(new_dims) = self.window_resized.take() {
self.scale.window_resized(new_dims, renderer);
let (w, h) = self.scale.scaled_window_size().into_tuple();
self.ui.handle_event(Input::Resize(w, h));
self.cache.clear_graphic_cache(renderer, renderer.get_resolution().map(|e| e * 4));
// TODO: probably need to resize glyph cache, see conrod's gfx backend for reference
}
}
}
@ -560,8 +599,8 @@ impl Ui {
}
DrawCommand::Draw { kind, model } => {
let tex = match kind {
DrawKind::Image(image_id) => {
self.image_map.get(&image_id).expect("Image does not exist in image map")
DrawKind::Image => {
self.cache.graphic_cache_tex()
}
DrawKind::Plain => {
self.cache.glyph_cache_tex()
@ -580,16 +619,4 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr<u16> {
min: Vec2 { x: 0, y: 0 },
max: Vec2 { x: screen_w, y: screen_h }
}
}
fn srgb_to_linear(color: [f32; 4]) -> [f32; 4] {
fn linearize(comp: f32) -> f32 {
if comp <= 0.04045 {
comp / 12.92
} else {
((comp + 0.055) / 1.055).powf(2.4)
}
}
[linearize(color[0]), linearize(color[1]), linearize(color[2]), color[3]]
}
}

36
voxygen/src/ui/util.rs Normal file
View File

@ -0,0 +1,36 @@
use vek::*;
#[inline(always)]
pub fn srgb_to_linear(c: Rgba<f32>) -> Rgba<f32> {
#[inline(always)]
fn to_linear(x: f32) -> f32 {
if x <= 0.04045 {
x / 12.92
} else {
((x + 0.055) / 1.055).powf(2.4)
}
}
Rgba {
r: to_linear(c.r),
g: to_linear(c.g),
b: to_linear(c.b),
a: c.a,
}
}
#[inline(always)]
pub fn linear_to_srgb(c: Rgba<f32>) -> Rgba<f32> {
#[inline(always)]
fn to_srgb(x: f32) -> f32 {
if x <= 0.0031308 {
x * 12.92
} else {
x.powf(1.0 / 2.4) * 1.055 - 0.055
}
}
Rgba {
r: to_srgb(c.r),
g: to_srgb(c.g),
b: to_srgb(c.b),
a: c.a,
}
}