mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
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:
commit
e02e2da58b
72
Cargo.lock
generated
72
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
|
115
voxygen/src/ui/graphic/graphic.rs
Normal file
115
voxygen/src/ui/graphic/graphic.rs
Normal 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
4
voxygen/src/ui/graphic/mod.rs
Normal file
4
voxygen/src/ui/graphic/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
mod graphic;
|
||||
mod renderer;
|
||||
|
||||
pub use graphic::{Graphic, GraphicCache, Id};
|
218
voxygen/src/ui/graphic/renderer.rs
Normal file
218
voxygen/src/ui/graphic/renderer.rs
Normal 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
|
||||
}
|
@ -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,36 +399,32 @@ 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();
|
||||
|
||||
match graphic_cache.get_graphic(*graphic_id) {
|
||||
Some(Graphic::Blank) | None => continue,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// 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 => {
|
||||
if let State::Plain = current_state {
|
||||
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);
|
||||
}
|
||||
current_state = State::Image;
|
||||
}
|
||||
|
||||
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa());
|
||||
let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into());
|
||||
|
||||
// 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 {
|
||||
|
||||
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,
|
||||
@ -413,14 +433,30 @@ impl Ui {
|
||||
(t / image_h) as f32)
|
||||
}
|
||||
None => (0.0, 1.0, 0.0, 1.0),
|
||||
};
|
||||
let uv = Aabr {
|
||||
};*/
|
||||
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()
|
||||
@ -581,15 +620,3 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr<u16> {
|
||||
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
36
voxygen/src/ui/util.rs
Normal 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,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user