mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
pull from upstream
Former-commit-id: 7907655bdc290e4790034d516d71839c3b45ec6c
This commit is contained in:
commit
0e8a7ecda3
232
.gitlab-ci.yml
Normal file
232
.gitlab-ci.yml
Normal file
@ -0,0 +1,232 @@
|
||||
#cache:
|
||||
# paths:
|
||||
# - target/
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
- post-run
|
||||
|
||||
# our own git fetch command like https://gitlab.com/gitlab-org/gitlab-runner/blob/master/shells/abstract.go
|
||||
# speeds up building because we skip the git clean and dont need any gitlab caches
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
before_script:
|
||||
- if [ -d .git ]; then
|
||||
echo "is git dir";
|
||||
else
|
||||
git clone $CI_REPOSITORY_URL . ;
|
||||
fi;
|
||||
- rm -f .git/index.lock
|
||||
- rm -f .git/shallow.lock
|
||||
- rm -f .git/HEAD.lock
|
||||
- rm -f .git/hocks/post-checkout
|
||||
- git remote set-url origin $CI_REPOSITORY_URL
|
||||
- git fetch origin --prune +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/*
|
||||
- git checkout -f -q $CI_COMMIT_SHA
|
||||
- if [ ! -z "${SOURCE_PROJECT}" -a "${SOURCE_PROJECT}" != " " ]; then
|
||||
echo "THIS SEEMS TO BE A MERGE PIPELINE FROM ${SOURCE_PROJECT}/${SOURCE_BRANCH}";
|
||||
git pull "https://gitlab.com/${SOURCE_PROJECT}/veloren.git" "${SOURCE_BRANCH}";
|
||||
fi;
|
||||
- git submodule update --init --recursive
|
||||
- git status
|
||||
- if [ -d target ]; then
|
||||
ls -la target;
|
||||
fi;
|
||||
# - git submodule update --init --recursive
|
||||
|
||||
clean-code:
|
||||
stage: build
|
||||
script:
|
||||
- rustup component add rustfmt-preview
|
||||
- cargo fmt --all -- --check
|
||||
allow_failure: true
|
||||
|
||||
build-voxygen:
|
||||
stage: build
|
||||
script:
|
||||
- (cd voxygen && cargo build)
|
||||
|
||||
build-server-cli:
|
||||
stage: build
|
||||
script:
|
||||
- (cd server-cli && cargo build)
|
||||
|
||||
unittests:
|
||||
stage: test
|
||||
script:
|
||||
- cargo test
|
||||
|
||||
#benchmarktests:
|
||||
# stage: test
|
||||
# script:
|
||||
# - cargo bench
|
||||
|
||||
nightly-linux-debug:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build)
|
||||
- rm -r -f nightly
|
||||
- mkdir nightly
|
||||
- cp target/debug/veloren-server-cli nightly
|
||||
- cp target/debug/veloren-voxygen nightly
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f nightly-linux-debug.tar.bz2
|
||||
- tar -cvjSf nightly-linux-debug.tar.bz2 nightly
|
||||
when: always
|
||||
artifacts:
|
||||
paths:
|
||||
- nightly-linux-debug.tar.bz2
|
||||
expire_in: 1 week
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
nightly-windows-debug:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build --target=x86_64-pc-windows-gnu)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build --target=x86_64-pc-windows-gnu)
|
||||
- rm -r -f nightly
|
||||
- mkdir nightly
|
||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe nightly
|
||||
- cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe nightly
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f nightly-windows-debug.zip
|
||||
- zip -r nightly-windows-debug.zip nightly
|
||||
artifacts:
|
||||
paths:
|
||||
- nightly-windows-debug.zip
|
||||
expire_in: 1 week
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
nightly-linux-optimized:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build --release)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build --release)
|
||||
- rm -r -f nightly
|
||||
- mkdir nightly
|
||||
- cp target/release/veloren-server-cli nightly
|
||||
- cp target/release/veloren-voxygen nightly
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f nightly-linux-optimized.tar.bz2
|
||||
- tar -cvjSf nightly-linux-optimized.tar.bz2 nightly
|
||||
when: manual
|
||||
artifacts:
|
||||
paths:
|
||||
- nightly-linux-optimized.tar.bz2
|
||||
expire_in: 2 days
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
nightly-windows-optimized:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
- rm -r -f nightly
|
||||
- mkdir nightly
|
||||
- cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe nightly
|
||||
- cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe nightly
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f nightly-windows-optimized.zip
|
||||
- zip -r nightly-windows-optimized.zip nightly
|
||||
when: manual
|
||||
artifacts:
|
||||
paths:
|
||||
- nightly-windows-optimized.zip
|
||||
expire_in: 2 days
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
stable-linux-optimized:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build --release)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build --release)
|
||||
- rm -r -f stable
|
||||
- mkdir stable
|
||||
- cp target/release/veloren-server-cli stable
|
||||
- cp target/release/veloren-voxygen stable
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f stable-linux-optimized.tar.bz2
|
||||
- tar -cvjSf stable-linux-optimized.tar.bz2 stable
|
||||
artifacts:
|
||||
paths:
|
||||
- stable-linux-optimized.tar.bz2
|
||||
expire_in: 30d
|
||||
only:
|
||||
refs:
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+/
|
||||
|
||||
stable-windows-optimized:
|
||||
stage: deploy
|
||||
script:
|
||||
- (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
- (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
- rm -r -f stable
|
||||
- mkdir stable
|
||||
- cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe stable
|
||||
- cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe stable
|
||||
- cp -r assets nightly/
|
||||
- cp -r voxygen/shaders nightly/
|
||||
- rm -f stable-windows-optimized.zip
|
||||
- zip -r stable-windows-optimized.zip stable
|
||||
artifacts:
|
||||
paths:
|
||||
- stable-windows-optimized.zip
|
||||
expire_in: 30d
|
||||
only:
|
||||
refs:
|
||||
- /^v[0-9]+\.[0-9]+\.[0-9]+/
|
||||
|
||||
# nightly-windows-release:
|
||||
# stage: deploy
|
||||
# script:
|
||||
# - (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
# - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu)
|
||||
# - rm -r -f nightly
|
||||
# - mkdir nightly
|
||||
# - cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe nightly
|
||||
# - cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe nightly
|
||||
# - cp -r assets nightly/
|
||||
# - cp -r voxygen/shaders nightly/
|
||||
# - cp -r voxygen/fonts nightly/
|
||||
# - rm -f nightly-windows-release.zip
|
||||
# - zip -r nightly-windows-release.zip nightly
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - nightly-windows-release.zip
|
||||
# expire_in: 1 week
|
||||
# only:
|
||||
# refs:
|
||||
# - master
|
||||
|
||||
coverage:
|
||||
stage: post-run
|
||||
script:
|
||||
- if cargo install --list | grep -i "cargo-tarpaulin"; then
|
||||
echo "tarpaulin already installed";
|
||||
else
|
||||
RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install cargo-tarpaulin;
|
||||
fi
|
||||
- cargo tarpaulin --skip-clean --all || echo "There is a problem in tarpaulin which sometimes fails"
|
||||
|
||||
clippy:
|
||||
stage: post-run
|
||||
script:
|
||||
- rustup component add clippy-preview --toolchain=nightly
|
||||
- cargo clippy --all -- -D clippy || echo "This job is disabled, because we are not activly using it now, so we dont want to see yellow failed partly"
|
||||
allow_failure: true
|
122
Cargo.lock
generated
122
Cargo.lock
generated
@ -71,7 +71,7 @@ version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -219,7 +219,7 @@ source = "git+https://gitlab.com/veloren/conrod.git#93f02e61838b475ff190b3563a0f
|
||||
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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -401,7 +401,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -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]]
|
||||
@ -457,10 +457,37 @@ dependencies = [
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"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.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.5"
|
||||
@ -477,7 +504,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -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"
|
||||
@ -1029,7 +1048,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1089,6 +1108,11 @@ dependencies = [
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.6"
|
||||
@ -1471,7 +1495,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.1.5"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1604,7 +1628,7 @@ dependencies = [
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1615,7 +1639,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1647,7 +1671,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shred"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1664,7 +1688,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1716,7 +1740,7 @@ dependencies = [
|
||||
"nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1725,7 +1749,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sphynx"
|
||||
version = "0.1.0"
|
||||
source = "git+https://gitlab.com/veloren/sphynx.git#b11c95047a1ab282cd790a3488a8b4f7923573e3"
|
||||
source = "git+https://gitlab.com/veloren/sphynx.git#32cfe0602b7876784845a39d5118f5d63dca80ff"
|
||||
dependencies = [
|
||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1758,7 +1782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.31"
|
||||
version = "0.15.32"
|
||||
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)",
|
||||
@ -1773,7 +1797,7 @@ 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)",
|
||||
"syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1787,10 +1811,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
version = "1.5.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)",
|
||||
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1898,14 +1923,14 @@ 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)",
|
||||
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sphynx 0.1.0 (git+https://gitlab.com/veloren/sphynx.git)",
|
||||
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1942,13 +1967,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)",
|
||||
@ -1960,6 +1988,7 @@ dependencies = [
|
||||
"vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"veloren-client 0.2.0",
|
||||
"veloren-common 0.2.0",
|
||||
"veloren-server 0.2.0",
|
||||
"winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -2208,12 +2237,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"
|
||||
@ -2237,6 +2269,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"
|
||||
@ -2262,7 +2295,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"
|
||||
@ -2274,7 +2306,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"
|
||||
@ -2288,6 +2319,7 @@ dependencies = [
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
|
||||
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
|
||||
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
||||
@ -2330,7 +2362,7 @@ dependencies = [
|
||||
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
|
||||
"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0"
|
||||
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
|
||||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
||||
"checksum rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
|
||||
@ -2352,7 +2384,7 @@ dependencies = [
|
||||
"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
|
||||
"checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5"
|
||||
"checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11"
|
||||
"checksum shred 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c75ec29e8d2959ad96a1087fe4cadb926c6fc17cbae9812314fa8efe720aa2a"
|
||||
"checksum shred 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea122e6133568144fcfb5888737d4ac776ebc959f989dd65b907136ac22bfed"
|
||||
"checksum shred-derive 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcf34e5e5302d3024aba7afc291f6d1ca7573ed035d3c0796976ba3f10691a1"
|
||||
"checksum shrev 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec60ed6f60a4b3cdc2ceacf57215db3408fbd8990f66a38686a31558cd9da482"
|
||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
@ -2364,10 +2396,10 @@ dependencies = [
|
||||
"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5"
|
||||
"checksum stb_truetype 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "69b7df505db8e81d54ff8be4693421e5b543e08214bd8d99eb761fcb4d5668ba"
|
||||
"checksum sum_type 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fcaf0ad86cfe6e1a9ccd145baa65fb1856a8a4b7cc1440b3a13f2b1f93a96fa"
|
||||
"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a"
|
||||
"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed"
|
||||
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
|
||||
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
|
||||
"checksum tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4834f28a0330cb9f3f2c87d2649dca723cb33802e2bdcf18da32759fbec7ce"
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e3083ec8e8e634af8c9daed00ea82435da195979
|
||||
Subproject commit 0a176c408946f081850132623a6730d9d2b1e7ed
|
@ -26,7 +26,7 @@ use common::{
|
||||
msg::{ClientMsg, ServerMsg},
|
||||
};
|
||||
|
||||
const SERVER_TIMEOUT: f64 = 5.0; // Seconds
|
||||
const SERVER_TIMEOUT: f64 = 20.0; // Seconds
|
||||
|
||||
pub enum Event {
|
||||
Chat(String),
|
||||
@ -167,9 +167,11 @@ impl Client {
|
||||
_ => {},
|
||||
}
|
||||
|
||||
// Update the server about the player's currently playing animation
|
||||
if let Some(animation) = self.state.read_storage().get(self.player).cloned() {
|
||||
self.postbox.send_message(ClientMsg::PlayerAnimation(animation));
|
||||
// Update the server about the player's currently playing animation and the previous one
|
||||
if let Some(animation_history) = self.state.read_storage::<comp::AnimationHistory>().get(self.player).cloned() {
|
||||
if Some(animation_history.current) != animation_history.last {
|
||||
self.postbox.send_message(ClientMsg::PlayerAnimation(animation_history));
|
||||
}
|
||||
}
|
||||
|
||||
// Request chunks from the server
|
||||
@ -228,9 +230,9 @@ impl Client {
|
||||
},
|
||||
None => {},
|
||||
},
|
||||
ServerMsg::EntityAnimation { entity, animation } => match self.state.ecs().entity_from_uid(entity) {
|
||||
ServerMsg::EntityAnimation { entity, animation_history } => match self.state.ecs().entity_from_uid(entity) {
|
||||
Some(entity) => {
|
||||
self.state.write_component(entity, animation);
|
||||
self.state.write_component(entity, animation_history);
|
||||
},
|
||||
None => {},
|
||||
},
|
||||
|
@ -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"
|
||||
|
@ -19,6 +19,12 @@ pub enum Gender {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AnimationHistory {
|
||||
pub last: Option<Animation>,
|
||||
pub current: Animation,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Animation {
|
||||
Idle,
|
||||
Run,
|
||||
@ -55,6 +61,6 @@ impl Component for Character {
|
||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||
}
|
||||
|
||||
impl Component for Animation {
|
||||
impl Component for AnimationHistory {
|
||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ pub mod phys;
|
||||
pub use agent::{Agent, Control};
|
||||
pub use character::Character;
|
||||
pub use player::Player;
|
||||
pub use character::AnimationHistory;
|
||||
pub use character::Animation;
|
||||
|
@ -11,7 +11,7 @@ pub enum ClientMsg {
|
||||
Ping,
|
||||
Pong,
|
||||
Chat(String),
|
||||
PlayerAnimation(comp::character::Animation),
|
||||
PlayerAnimation(comp::character::AnimationHistory),
|
||||
PlayerPhysics {
|
||||
pos: comp::phys::Pos,
|
||||
vel: comp::phys::Vel,
|
||||
|
@ -25,7 +25,7 @@ pub enum ServerMsg {
|
||||
},
|
||||
EntityAnimation {
|
||||
entity: u64,
|
||||
animation: comp::Animation,
|
||||
animation_history: comp::AnimationHistory,
|
||||
},
|
||||
TerrainChunkUpdate {
|
||||
key: Vec3<i32>,
|
||||
|
@ -97,41 +97,41 @@ impl State {
|
||||
ecs.register_synced::<comp::Player>();
|
||||
|
||||
// Register unsynched (or synced by other means) components
|
||||
ecs.internal_mut().register::<comp::phys::Pos>();
|
||||
ecs.internal_mut().register::<comp::phys::Vel>();
|
||||
ecs.internal_mut().register::<comp::phys::Dir>();
|
||||
ecs.internal_mut().register::<comp::Animation>();
|
||||
ecs.internal_mut().register::<comp::Agent>();
|
||||
ecs.internal_mut().register::<comp::Control>();
|
||||
ecs.register::<comp::phys::Pos>();
|
||||
ecs.register::<comp::phys::Vel>();
|
||||
ecs.register::<comp::phys::Dir>();
|
||||
ecs.register::<comp::AnimationHistory>();
|
||||
ecs.register::<comp::Agent>();
|
||||
ecs.register::<comp::Control>();
|
||||
|
||||
// Register resources used by the ECS
|
||||
ecs.internal_mut().add_resource(TimeOfDay(0.0));
|
||||
ecs.internal_mut().add_resource(Time(0.0));
|
||||
ecs.internal_mut().add_resource(DeltaTime(0.0));
|
||||
ecs.internal_mut().add_resource(TerrainMap::new());
|
||||
ecs.add_resource(TimeOfDay(0.0));
|
||||
ecs.add_resource(Time(0.0));
|
||||
ecs.add_resource(DeltaTime(0.0));
|
||||
ecs.add_resource(TerrainMap::new());
|
||||
}
|
||||
|
||||
/// Register a component with the state's ECS
|
||||
pub fn with_component<T: Component>(mut self) -> Self
|
||||
where <T as Component>::Storage: Default
|
||||
{
|
||||
self.ecs.internal_mut().register::<T>();
|
||||
self.ecs.register::<T>();
|
||||
self
|
||||
}
|
||||
|
||||
/// Write a component attributed to a particular entity
|
||||
pub fn write_component<C: Component>(&mut self, entity: EcsEntity, comp: C) {
|
||||
let _ = self.ecs.internal_mut().write_storage().insert(entity, comp);
|
||||
let _ = self.ecs.write_storage().insert(entity, comp);
|
||||
}
|
||||
|
||||
/// Read a component attributed to a particular entity
|
||||
pub fn read_component_cloned<C: Component + Clone>(&self, entity: EcsEntity) -> Option<C> {
|
||||
self.ecs.internal().read_storage().get(entity).cloned()
|
||||
self.ecs.read_storage().get(entity).cloned()
|
||||
}
|
||||
|
||||
/// Get a read-only reference to the storage of a particular component type
|
||||
pub fn read_storage<C: Component>(&self) -> EcsStorage<C, Fetch<EcsMaskedStorage<C>>> {
|
||||
self.ecs.internal().read_storage::<C>()
|
||||
self.ecs.read_storage::<C>()
|
||||
}
|
||||
|
||||
/// Get a reference to the internal ECS world
|
||||
@ -154,27 +154,25 @@ impl State {
|
||||
///
|
||||
/// Note that this should not be used for physics, animations or other such localised timings.
|
||||
pub fn get_time_of_day(&self) -> f64 {
|
||||
self.ecs.internal().read_resource::<TimeOfDay>().0
|
||||
self.ecs.read_resource::<TimeOfDay>().0
|
||||
}
|
||||
|
||||
/// Get the current in-game time.
|
||||
///
|
||||
/// Note that this does not correspond to the time of day.
|
||||
pub fn get_time(&self) -> f64 {
|
||||
self.ecs.internal().read_resource::<Time>().0
|
||||
self.ecs.read_resource::<Time>().0
|
||||
}
|
||||
|
||||
/// Get a reference to this state's terrain.
|
||||
pub fn terrain(&self) -> Fetch<TerrainMap> {
|
||||
self.ecs
|
||||
.internal()
|
||||
.read_resource::<TerrainMap>()
|
||||
}
|
||||
|
||||
/// Insert the provided chunk into this state's terrain.
|
||||
pub fn insert_chunk(&mut self, key: Vec3<i32>, chunk: TerrainChunk) {
|
||||
if self.ecs
|
||||
.internal_mut()
|
||||
.write_resource::<TerrainMap>()
|
||||
.insert(key, chunk)
|
||||
.is_some()
|
||||
@ -188,19 +186,19 @@ impl State {
|
||||
/// Execute a single tick, simulating the game state by the given duration.
|
||||
pub fn tick(&mut self, dt: Duration) {
|
||||
// Change the time accordingly
|
||||
self.ecs.internal_mut().write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
|
||||
self.ecs.internal_mut().write_resource::<Time>().0 += dt.as_secs_f64();
|
||||
self.ecs.write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
|
||||
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64();
|
||||
|
||||
// Run systems to update the world
|
||||
self.ecs.internal_mut().write_resource::<DeltaTime>().0 = dt.as_secs_f64();
|
||||
self.ecs.write_resource::<DeltaTime>().0 = dt.as_secs_f64();
|
||||
|
||||
// Create and run dispatcher for ecs systems
|
||||
let mut dispatch_builder = DispatcherBuilder::new();
|
||||
sys::add_local_systems(&mut dispatch_builder);
|
||||
// This dispatches all the systems in parallel
|
||||
dispatch_builder.build().dispatch(&self.ecs.internal_mut().res);
|
||||
dispatch_builder.build().dispatch(&self.ecs.res);
|
||||
|
||||
self.ecs.internal_mut().maintain();
|
||||
self.ecs.maintain();
|
||||
}
|
||||
|
||||
/// Clean up the state after a tick
|
||||
|
@ -3,7 +3,7 @@ use specs::{Join, Read, ReadStorage, System, WriteStorage, Entities};
|
||||
use vek::*;
|
||||
|
||||
// Crate
|
||||
use crate::comp::{Control, Animation, phys::{Pos, Vel, Dir}};
|
||||
use crate::comp::{Control, Animation, AnimationHistory, phys::{Pos, Vel, Dir}};
|
||||
|
||||
// Basic ECS AI agent system
|
||||
pub struct Sys;
|
||||
@ -13,7 +13,7 @@ impl<'a> System<'a> for Sys {
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, Vel>,
|
||||
WriteStorage<'a, Dir>,
|
||||
WriteStorage<'a, Animation>,
|
||||
WriteStorage<'a, AnimationHistory>,
|
||||
ReadStorage<'a, Control>,
|
||||
);
|
||||
|
||||
@ -23,12 +23,20 @@ impl<'a> System<'a> for Sys {
|
||||
// Apply physics to the player: acceleration and non-linear decceleration
|
||||
vel.0 += control.move_dir * 2.0 - vel.0.map(|e| e * e.abs() + e) * 0.03;
|
||||
|
||||
if control.move_dir.magnitude() > 0.01 {
|
||||
dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0);
|
||||
anims.insert(entity, Animation::Run);
|
||||
} else {
|
||||
anims.insert(entity, Animation::Idle);
|
||||
}
|
||||
let animation =
|
||||
if control.move_dir.magnitude() > 0.01 {
|
||||
dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0);
|
||||
Animation::Run
|
||||
} else {
|
||||
Animation::Idle
|
||||
};
|
||||
|
||||
let last_animation = anims.get_mut(entity).map(|h| h.current);
|
||||
|
||||
anims.insert(entity, AnimationHistory {
|
||||
last: last_animation,
|
||||
current: animation,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &Chat
|
||||
let opt_alias = scan_fmt!(&args, action.arg_fmt, String);
|
||||
match opt_alias {
|
||||
Some(alias) => {
|
||||
let ecs = server.state.ecs().internal();
|
||||
let ecs = server.state.ecs();
|
||||
let opt_player = (&ecs.entities(), &ecs.read_storage::<comp::player::Player>())
|
||||
.join()
|
||||
.find(|(_, player)| player.alias == alias)
|
||||
|
@ -15,6 +15,7 @@ use common::{
|
||||
net::PostOffice,
|
||||
state::{State, Uid},
|
||||
terrain::TerrainChunk,
|
||||
comp::character::Animation,
|
||||
};
|
||||
use specs::{
|
||||
join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
|
||||
@ -25,7 +26,7 @@ use threadpool::ThreadPool;
|
||||
use vek::*;
|
||||
use world::World;
|
||||
|
||||
const CLIENT_TIMEOUT: f64 = 5.0; // Seconds
|
||||
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
|
||||
|
||||
pub enum Event {
|
||||
ClientConnected { entity: EcsEntity },
|
||||
@ -53,7 +54,7 @@ impl Server {
|
||||
let (chunk_tx, chunk_rx) = mpsc::channel();
|
||||
|
||||
let mut state = State::new();
|
||||
state.ecs_mut().internal_mut().register::<comp::phys::ForceUpdate>();
|
||||
state.ecs_mut().register::<comp::phys::ForceUpdate>();
|
||||
|
||||
let mut this = Self {
|
||||
state,
|
||||
@ -153,12 +154,11 @@ impl Server {
|
||||
for (key, chunk) in self.chunk_rx.try_iter() {
|
||||
// Send the chunk to all nearby players
|
||||
for (entity, player, pos) in (
|
||||
&self.state.ecs().internal().entities(),
|
||||
&self.state.ecs().internal().read_storage::<comp::Player>(),
|
||||
&self.state.ecs().entities(),
|
||||
&self.state.ecs().read_storage::<comp::Player>(),
|
||||
&self
|
||||
.state
|
||||
.ecs()
|
||||
.internal()
|
||||
.read_storage::<comp::phys::Pos>(),
|
||||
)
|
||||
.join()
|
||||
@ -235,28 +235,7 @@ impl Server {
|
||||
match client.state {
|
||||
ClientState::Connecting => match msg {
|
||||
ClientMsg::Connect { player, character } => {
|
||||
|
||||
// Write client components
|
||||
state.write_component(entity, player);
|
||||
state.write_component(entity, comp::phys::Pos(Vec3::zero()));
|
||||
state.write_component(entity, comp::phys::Vel(Vec3::zero()));
|
||||
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
||||
if let Some(character) = character {
|
||||
state.write_component(entity, character);
|
||||
}
|
||||
state.write_component(entity, comp::phys::ForceUpdate);
|
||||
|
||||
client.state = ClientState::Connected;
|
||||
|
||||
// Return a handshake with the state of the current world
|
||||
client.notify(ServerMsg::Handshake {
|
||||
ecs_state: state.ecs().gen_state_package(),
|
||||
player_entity: state
|
||||
.ecs()
|
||||
.uid_from_entity(entity)
|
||||
.unwrap()
|
||||
.into(),
|
||||
});
|
||||
Self::initialize_client(state, entity, client, player, character);
|
||||
}
|
||||
_ => disconnect = true,
|
||||
},
|
||||
@ -266,7 +245,7 @@ impl Server {
|
||||
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
|
||||
ClientMsg::Pong => {}
|
||||
ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)),
|
||||
ClientMsg::PlayerAnimation(animation) => state.write_component(entity, animation),
|
||||
ClientMsg::PlayerAnimation(animation_history) => state.write_component(entity, animation_history),
|
||||
ClientMsg::PlayerPhysics { pos, vel, dir } => {
|
||||
state.write_component(entity, pos);
|
||||
state.write_component(entity, vel);
|
||||
@ -313,7 +292,6 @@ impl Server {
|
||||
match self
|
||||
.state
|
||||
.ecs()
|
||||
.internal()
|
||||
.read_storage::<comp::Player>()
|
||||
.get(entity)
|
||||
{
|
||||
@ -341,6 +319,63 @@ impl Server {
|
||||
Ok(frontend_events)
|
||||
}
|
||||
|
||||
/// Initialize a new client states with important information
|
||||
fn initialize_client(
|
||||
state: &mut State,
|
||||
entity: specs::Entity,
|
||||
client: &mut Client,
|
||||
player: comp::Player,
|
||||
character: Option<comp::Character>,
|
||||
) {
|
||||
// Save player metadata (for example the username)
|
||||
state.write_component(entity, player);
|
||||
|
||||
// Give the player it's character if he wants one
|
||||
// (Chat only clients don't need one for example)
|
||||
if let Some(character) = character {
|
||||
state.write_component(entity, character);
|
||||
|
||||
// Every character has to have these components
|
||||
state.write_component(entity, comp::phys::Pos(Vec3::zero()));
|
||||
state.write_component(entity, comp::phys::Vel(Vec3::zero()));
|
||||
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
||||
// Make sure everything is accepted
|
||||
state.write_component(entity, comp::phys::ForceUpdate);
|
||||
|
||||
// Set initial animation
|
||||
state.write_component(entity, comp::AnimationHistory {
|
||||
last: None,
|
||||
current: Animation::Idle
|
||||
});
|
||||
}
|
||||
|
||||
client.state = ClientState::Connected;
|
||||
|
||||
// Return a handshake with the state of the current world
|
||||
// (All components Sphynx tracks)
|
||||
client.notify(ServerMsg::Handshake {
|
||||
ecs_state: state.ecs().gen_state_package(),
|
||||
player_entity: state
|
||||
.ecs()
|
||||
.uid_from_entity(entity)
|
||||
.unwrap()
|
||||
.into(),
|
||||
});
|
||||
|
||||
// Sync logical information other players have authority over, not the server
|
||||
for (other_entity, &uid, &animation_history) in (
|
||||
&state.ecs().entities(),
|
||||
&state.ecs().read_storage::<common::state::Uid>(),
|
||||
&state.ecs().read_storage::<comp::AnimationHistory>(),
|
||||
).join() {
|
||||
// AnimationHistory
|
||||
client.postbox.send_message(ServerMsg::EntityAnimation {
|
||||
entity: uid.into(),
|
||||
animation_history: animation_history,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync client states with the most up to date information
|
||||
fn sync_clients(&mut self) {
|
||||
// Sync 'logical' state using Sphynx
|
||||
@ -348,12 +383,12 @@ impl Server {
|
||||
|
||||
// Sync 'physical' state
|
||||
for (entity, &uid, &pos, &vel, &dir, force_update) in (
|
||||
&self.state.ecs().internal().entities(),
|
||||
&self.state.ecs().internal().read_storage::<Uid>(),
|
||||
&self.state.ecs().internal().read_storage::<comp::phys::Pos>(),
|
||||
&self.state.ecs().internal().read_storage::<comp::phys::Vel>(),
|
||||
&self.state.ecs().internal().read_storage::<comp::phys::Dir>(),
|
||||
self.state.ecs().internal().read_storage::<comp::phys::ForceUpdate>().maybe(),
|
||||
&self.state.ecs().entities(),
|
||||
&self.state.ecs().read_storage::<Uid>(),
|
||||
&self.state.ecs().read_storage::<comp::phys::Pos>(),
|
||||
&self.state.ecs().read_storage::<comp::phys::Vel>(),
|
||||
&self.state.ecs().read_storage::<comp::phys::Dir>(),
|
||||
self.state.ecs().read_storage::<comp::phys::ForceUpdate>().maybe(),
|
||||
).join() {
|
||||
let msg = ServerMsg::EntityPhysics {
|
||||
entity: uid.into(),
|
||||
@ -369,19 +404,32 @@ impl Server {
|
||||
}
|
||||
|
||||
// Sync animation states
|
||||
for (entity, &uid, &animation) in (
|
||||
&self.state.ecs().internal().entities(),
|
||||
&self.state.ecs().internal().read_storage::<Uid>(),
|
||||
&self.state.ecs().internal().read_storage::<comp::Animation>(),
|
||||
for (entity, &uid, &animation_history) in (
|
||||
&self.state.ecs().entities(),
|
||||
&self.state.ecs().read_storage::<Uid>(),
|
||||
&self.state.ecs().read_storage::<comp::AnimationHistory>(),
|
||||
).join() {
|
||||
// Check if we need to sync
|
||||
if Some(animation_history.current) == animation_history.last {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation {
|
||||
entity: uid.into(),
|
||||
animation,
|
||||
animation_history,
|
||||
});
|
||||
}
|
||||
|
||||
// Update animation last/current state
|
||||
for (entity, mut animation_history) in (
|
||||
&self.state.ecs().entities(),
|
||||
&mut self.state.ecs().write_storage::<comp::AnimationHistory>()
|
||||
).join() {
|
||||
animation_history.last = Some(animation_history.current);
|
||||
}
|
||||
|
||||
// Remove all force flags
|
||||
self.state.ecs_mut().internal_mut().write_storage::<comp::phys::ForceUpdate>().clear();
|
||||
self.state.ecs_mut().write_storage::<comp::phys::ForceUpdate>().clear();
|
||||
}
|
||||
|
||||
pub fn generate_chunk(&mut self, key: Vec3<i32>) {
|
||||
|
1
voxygen/.gitignore
vendored
1
voxygen/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
settings.toml
|
||||
|
@ -12,6 +12,7 @@ default = ["gl"]
|
||||
[dependencies]
|
||||
common = { package = "veloren-common", path = "../common" }
|
||||
client = { package = "veloren-client", path = "../client" }
|
||||
server = { package = "veloren-server", path = "../server" }
|
||||
|
||||
# Graphics
|
||||
gfx = "0.17"
|
||||
@ -21,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"
|
||||
@ -34,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"
|
||||
|
@ -8,6 +8,7 @@ use vek::*;
|
||||
use super::{
|
||||
CharacterSkeleton,
|
||||
super::Animation,
|
||||
SCALE,
|
||||
};
|
||||
|
||||
pub struct IdleAnimation;
|
||||
@ -22,28 +23,39 @@ impl Animation for IdleAnimation {
|
||||
time: f64,
|
||||
) -> Self::Skeleton {
|
||||
let mut next = (*skeleton).clone();
|
||||
next.head.offset = Vec3::unit_z() * 13.0 / 11.0;
|
||||
next.head.ori = Quaternion::rotation_z(0.0);
|
||||
|
||||
next.chest.offset = Vec3::unit_z() * 9.0 / 11.0;
|
||||
next.chest.ori = Quaternion::rotation_z(0.0);
|
||||
let wave = (time as f32 * 12.0).sin();
|
||||
let wavecos = (time as f32 * 12.0).cos();
|
||||
let wave_slow = (time as f32 * 6.0 + PI).sin();
|
||||
let wavecos_slow = (time as f32 * 6.0 + PI).cos();
|
||||
let waveultra_slow = (time as f32 * 1.0 + PI).sin();
|
||||
let waveultracos_slow = (time as f32 * 1.0 + PI).cos();
|
||||
let wave_dip = (wave_slow.abs() - 0.5).abs();
|
||||
|
||||
next.belt.offset = Vec3::unit_z() * 7.0 / 11.0;
|
||||
next.belt.ori = Quaternion::rotation_z(0.0);
|
||||
next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE;
|
||||
next.head.ori = Quaternion::rotation_y(waveultra_slow * 0.05);
|
||||
|
||||
next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0;
|
||||
next.shorts.ori = Quaternion::rotation_z(0.0);
|
||||
next.chest.offset = Vec3::new(0.0, 0.0, 8.0 + waveultra_slow * 0.4) / SCALE;
|
||||
next.chest.ori = Quaternion::rotation_y(0.0);
|
||||
|
||||
next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / 11.0;
|
||||
next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / 11.0;
|
||||
next.belt.offset = Vec3::new(0.0, 0.0, 6.0 + waveultra_slow * 0.4) / SCALE;
|
||||
next.belt.ori = Quaternion::rotation_y(0.0);
|
||||
|
||||
next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / 11.0;
|
||||
next.l_foot.ori = Quaternion::rotation_x(0.0);
|
||||
next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / 11.0;
|
||||
next.r_foot.ori = Quaternion::rotation_x(0.0);
|
||||
next.shorts.offset = Vec3::new(0.0, 0.0, 3.0 + waveultra_slow * 0.4) / SCALE;
|
||||
next.shorts.ori = Quaternion::rotation_y(0.0);
|
||||
|
||||
next.back.offset = Vec3::new(-9.0, 5.0, 18.0);
|
||||
next.back.ori = Quaternion::rotation_y(2.5);
|
||||
next.l_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3, 7.5, 11.0 + waveultra_slow * 1.1) / SCALE;
|
||||
next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
|
||||
next.r_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3 , - 7.5, 11.0 + waveultra_slow * 1.1) / SCALE;
|
||||
next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
|
||||
|
||||
next.l_foot.offset = Vec3::new(2.5, 3.4, 6.0) / SCALE;
|
||||
next.l_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04);
|
||||
next.r_foot.offset = Vec3::new(2.5, -3.4, 6.0) / SCALE;
|
||||
next.r_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04);
|
||||
|
||||
next.back.offset = Vec3::new(-6.5, 16.0, 15.0);
|
||||
next.back.ori = Quaternion::rotation_x(2.5);
|
||||
next.back.scale = Vec3::one();
|
||||
|
||||
next
|
||||
|
@ -14,6 +14,8 @@ use super::{
|
||||
Bone,
|
||||
};
|
||||
|
||||
const SCALE: f32 = 11.0;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CharacterSkeleton {
|
||||
head: Bone,
|
||||
|
@ -8,6 +8,7 @@ use vek::*;
|
||||
use super::{
|
||||
CharacterSkeleton,
|
||||
super::Animation,
|
||||
SCALE
|
||||
};
|
||||
|
||||
pub struct RunAnimation;
|
||||
@ -22,34 +23,40 @@ impl Animation for RunAnimation {
|
||||
) -> Self::Skeleton {
|
||||
let mut next = (*skeleton).clone();
|
||||
|
||||
let wave = (time as f32 * 12.0).sin();
|
||||
let wave_slow = (time as f32 * 6.0 + PI).sin();
|
||||
let wave = (time as f32 * 14.0).sin();
|
||||
let fuzzwave = (time as f32 * 12.0).sin();
|
||||
let wavecos = (time as f32 * 14.0).cos();
|
||||
let wave_slow = (time as f32 * 8.0 + PI).sin();
|
||||
let wavecos_slow = (time as f32 * 8.0 + PI).cos();
|
||||
let wave_dip = (wave_slow.abs() - 0.5).abs();
|
||||
|
||||
next.head.offset = Vec3::unit_z() * 13.0 / 11.0;
|
||||
next.head.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ SCALE;
|
||||
|
||||
next.chest.offset = Vec3::unit_z() * 9.0 / 11.0;
|
||||
next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / SCALE;
|
||||
next.chest.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
next.belt.offset = Vec3::unit_z() * 7.0 / 11.0;
|
||||
next.belt.ori = Quaternion::rotation_z(wave * 0.2);
|
||||
next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8) / SCALE;
|
||||
next.belt.ori = Quaternion::rotation_z(wave * 0.3);
|
||||
|
||||
next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0;
|
||||
next.shorts.ori = Quaternion::rotation_z(wave * 0.1);
|
||||
next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / SCALE;
|
||||
next.shorts.ori = Quaternion::rotation_z(wave * 0.2);
|
||||
|
||||
next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0;
|
||||
next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0;
|
||||
next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE;
|
||||
next.l_hand.ori = Quaternion::rotation_y(wave * -1.8);
|
||||
next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE;
|
||||
next.r_hand.ori = Quaternion::rotation_y(wave * 1.8);
|
||||
|
||||
next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0;
|
||||
next.l_foot.ori = Quaternion::rotation_x(-wave + 1.0);
|
||||
next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0;
|
||||
next.r_foot.ori = Quaternion::rotation_x(wave + 1.0);
|
||||
next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / SCALE;
|
||||
next.l_foot.ori = Quaternion::rotation_y(wave * -1.0);
|
||||
next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / SCALE;
|
||||
|
||||
next.back.offset = Vec3::new(-9.0, 5.0, 18.0);
|
||||
next.back.ori = Quaternion::rotation_y(2.5);
|
||||
next.r_foot.ori = Quaternion::rotation_y(wave * 1.0);
|
||||
|
||||
next.back.offset = Vec3::new(-6.0, 16.0, 15.0);
|
||||
next.back.ori = Quaternion::rotation_x(2.5);
|
||||
next.back.scale = Vec3::one();
|
||||
|
||||
next
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -83,34 +83,42 @@ impl Chat {
|
||||
self.new_messages = false;
|
||||
}
|
||||
|
||||
// Only show if it has the keyboard captured
|
||||
// Chat input with rectangle as background
|
||||
let text_edit = TextEdit::new(&self.input)
|
||||
.w(460.0)
|
||||
.restrict_to_height(false)
|
||||
.line_spacing(2.0)
|
||||
.font_size(15)
|
||||
.font_id(font);
|
||||
let y = match text_edit.get_y_dimension(ui_widgets) {
|
||||
Dimension::Absolute(y) => y + 6.0,
|
||||
_ => 0.0,
|
||||
};
|
||||
Rectangle::fill([470.0, y])
|
||||
.rgba(0.0, 0.0, 0.0, 0.8)
|
||||
.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
|
||||
.w(470.0)
|
||||
.set(self.ids.input_bg, ui_widgets);
|
||||
if let Some(str) = text_edit
|
||||
.top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0)
|
||||
.set(self.ids.input, ui_widgets)
|
||||
{
|
||||
self.input = str.to_string();
|
||||
self.input.retain(|c| c != '\n');
|
||||
let keyboard_captured = ui_widgets.global_input().current.widget_capturing_keyboard.map_or(false, |id| id == self.ids.input);
|
||||
if keyboard_captured {
|
||||
let text_edit = TextEdit::new(&self.input)
|
||||
.w(460.0)
|
||||
.restrict_to_height(false)
|
||||
.line_spacing(2.0)
|
||||
.font_size(15)
|
||||
.font_id(font);
|
||||
let y = match text_edit.get_y_dimension(ui_widgets) {
|
||||
Dimension::Absolute(y) => y + 6.0,
|
||||
_ => 0.0,
|
||||
};
|
||||
Rectangle::fill([470.0, y])
|
||||
.rgba(0.0, 0.0, 0.0, 0.8)
|
||||
.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
|
||||
.w(470.0)
|
||||
.set(self.ids.input_bg, ui_widgets);
|
||||
if let Some(str) = text_edit
|
||||
.top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0)
|
||||
.set(self.ids.input, ui_widgets)
|
||||
{
|
||||
self.input = str.to_string();
|
||||
self.input.retain(|c| c != '\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Message box
|
||||
Rectangle::fill([470.0, 174.0])
|
||||
.rgba(0.0, 0.0, 0.0, 0.4)
|
||||
.up_from(self.ids.input_bg, 0.0)
|
||||
.and(|r| if keyboard_captured {
|
||||
r.up_from(self.ids.input_bg, 0.0)
|
||||
} else {
|
||||
r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0)
|
||||
})
|
||||
.set(self.ids.message_box_bg, ui_widgets);
|
||||
let (mut items, _) = List::flow_down(self.messages.len() + 1)
|
||||
.top_left_of(self.ids.message_box_bg)
|
||||
@ -154,13 +162,13 @@ impl Chat {
|
||||
}
|
||||
}
|
||||
|
||||
// If enter is pressed send the current message
|
||||
// If enter is pressed and the input box is not empty send the current message
|
||||
if ui_widgets
|
||||
.widget_input(self.ids.input)
|
||||
.presses()
|
||||
.key()
|
||||
.any(|key_press| match key_press.key {
|
||||
Key::Return => true,
|
||||
Key::Return if !self.input.is_empty() => true,
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,14 @@ pub mod session;
|
||||
pub mod ui;
|
||||
pub mod window;
|
||||
pub mod settings;
|
||||
pub mod singleplayer;
|
||||
|
||||
// Reexports
|
||||
pub use crate::error::Error;
|
||||
|
||||
// Standard
|
||||
use std::mem;
|
||||
use std::thread;
|
||||
|
||||
// Library
|
||||
use log;
|
||||
@ -28,13 +30,18 @@ use pretty_env_logger;
|
||||
use crate::{
|
||||
menu::main::MainMenuState,
|
||||
window::Window,
|
||||
settings::Settings
|
||||
settings::Settings,
|
||||
singleplayer::Singleplayer,
|
||||
};
|
||||
|
||||
/// The URL of the default public server that Voxygen will connect to
|
||||
const DEFAULT_PUBLIC_SERVER: &'static str = "server.veloren.net";
|
||||
|
||||
/// A type used to store state that is shared between all play states
|
||||
pub struct GlobalState {
|
||||
settings: Settings,
|
||||
window: Window,
|
||||
singleplayer: Option<Singleplayer>,
|
||||
}
|
||||
|
||||
impl GlobalState {
|
||||
@ -88,6 +95,7 @@ fn main() {
|
||||
let mut global_state = GlobalState {
|
||||
settings,
|
||||
window,
|
||||
singleplayer: None,
|
||||
};
|
||||
|
||||
// Set up the initial play state
|
||||
|
@ -45,7 +45,10 @@ impl PlayState for CharSelectionState {
|
||||
// Handle window events
|
||||
for event in global_state.window.fetch_events() {
|
||||
match event {
|
||||
Event::Close => return PlayStateResult::Shutdown,
|
||||
Event::Close => {
|
||||
global_state.singleplayer = None;
|
||||
return PlayStateResult::Shutdown;
|
||||
},
|
||||
// Pass events to ui
|
||||
Event::Ui(event) => {
|
||||
self.char_selection_ui.handle_event(event);
|
||||
@ -60,8 +63,11 @@ impl PlayState for CharSelectionState {
|
||||
// Maintain the UI
|
||||
for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) {
|
||||
match event {
|
||||
ui::Event::Logout => return PlayStateResult::Pop,
|
||||
ui::Event::Play => return PlayStateResult::Push(
|
||||
ui::Event::Logout => {
|
||||
global_state.singleplayer = None;
|
||||
return PlayStateResult::Pop;
|
||||
},
|
||||
ui::Event::Play => return PlayStateResult::Switch(
|
||||
Box::new(SessionState::new(&mut global_state.window, self.client.clone()))
|
||||
),
|
||||
}
|
||||
|
@ -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"),
|
||||
@ -377,20 +377,16 @@ impl CharSelectionUi {
|
||||
// Load images
|
||||
let imgs = Imgs::new(&mut ui, window.renderer_mut());
|
||||
// Load fonts
|
||||
let font_opensans = ui.new_font(
|
||||
conrod_core::text::font::from_file(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../assets/voxygen/font/OpenSans-Regular.ttf"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let font_metamorph = ui.new_font(
|
||||
conrod_core::text::font::from_file(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../assets/voxygen/font/Metamorphous-Regular.ttf"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let load_font = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/font", filename].concat();
|
||||
ui.new_font(conrod_core::text::Font::from_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
).unwrap())
|
||||
};
|
||||
let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui);
|
||||
let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui);
|
||||
|
||||
Self {
|
||||
ui,
|
||||
imgs,
|
||||
@ -411,6 +407,7 @@ impl CharSelectionUi {
|
||||
fn update_layout(&mut self) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
let ref mut ui_widgets = self.ui.set_widgets();
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
|
||||
// Character Selection /////////////////
|
||||
// Supposed functionality:
|
||||
@ -475,7 +472,7 @@ impl CharSelectionUi {
|
||||
Button::image(self.imgs.v_logo)
|
||||
.w_h(346.0, 111.0)
|
||||
.top_left_with_margins_on(self.ids.bg_selection, 30.0, 40.0)
|
||||
.label("Alpha 0.1")
|
||||
.label(version)
|
||||
.label_rgba(1.0, 1.0, 1.0, 1.0)
|
||||
.label_font_size(10)
|
||||
.label_y(conrod_core::position::Relative::Scalar(-40.0))
|
||||
|
@ -22,10 +22,10 @@ pub struct ClientInit {
|
||||
impl ClientInit {
|
||||
pub fn new(
|
||||
connection_args: (String, u16, bool),
|
||||
client_args: (comp::Player, Option<comp::Character>, Option<comp::Animation>, u64),
|
||||
client_args: (comp::Player, Option<comp::Character>, u64),
|
||||
) -> Self {
|
||||
let (server_address, default_port, prefer_ipv6) = connection_args;
|
||||
let (player, character, animation, view_distance) = client_args;
|
||||
let (player, character, view_distance) = client_args;
|
||||
|
||||
let (tx, rx) = channel();
|
||||
|
||||
|
@ -5,6 +5,7 @@ use super::char_selection::CharSelectionState;
|
||||
use crate::{
|
||||
window::{Event, Window},
|
||||
GlobalState, PlayState, PlayStateResult,
|
||||
singleplayer::Singleplayer,
|
||||
};
|
||||
use client_init::{ClientInit, Error as InitError};
|
||||
use common::{clock::Clock, comp};
|
||||
@ -60,7 +61,7 @@ impl PlayState for MainMenuState {
|
||||
global_state.window.renderer_mut().clear(BG_COLOR);
|
||||
|
||||
// Poll client creation
|
||||
match client_init.as_ref().and_then(|init| init.poll()) {
|
||||
match client_init.as_ref().and_then(|init| init.poll()) {
|
||||
Some(Ok(client)) => {
|
||||
self.main_menu_ui.connected();
|
||||
return PlayStateResult::Push(Box::new(CharSelectionState::new(
|
||||
@ -70,11 +71,14 @@ impl PlayState for MainMenuState {
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
client_init = None;
|
||||
self.main_menu_ui.login_error(match err {
|
||||
InitError::BadAddress(_) | InitError::NoAddress => "No such host is known",
|
||||
InitError::ConnectionFailed(_) => "Could not connect to address",
|
||||
}.to_string());
|
||||
},
|
||||
self.main_menu_ui.login_error(
|
||||
match err {
|
||||
InitError::BadAddress(_) | InitError::NoAddress => "Server not found",
|
||||
InitError::ConnectionFailed(_) => "Connection failed",
|
||||
}
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
@ -95,11 +99,13 @@ impl PlayState for MainMenuState {
|
||||
(
|
||||
comp::Player::new(username.clone()),
|
||||
Some(comp::Character::test()),
|
||||
Some(comp::Animation::Idle),
|
||||
300,
|
||||
),
|
||||
)));
|
||||
}
|
||||
},
|
||||
MainMenuEvent::StartSingleplayer => {
|
||||
global_state.singleplayer = Some(Singleplayer::new());
|
||||
},
|
||||
MainMenuEvent::Quit => return PlayStateResult::Shutdown,
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,14 @@ use crate::{
|
||||
render::Renderer,
|
||||
ui::{self, ScaleMode, Ui},
|
||||
window::Window,
|
||||
DEFAULT_PUBLIC_SERVER,
|
||||
};
|
||||
use common::{
|
||||
assets,
|
||||
figure::Segment,
|
||||
};
|
||||
use common::assets;
|
||||
use conrod_core::{
|
||||
color,
|
||||
color::TRANSPARENT,
|
||||
image::Id as ImgId,
|
||||
position::{Dimension, Relative},
|
||||
@ -36,6 +41,9 @@ widget_ids! {
|
||||
servers_button,
|
||||
settings_button,
|
||||
quit_button,
|
||||
// Error
|
||||
error_frame,
|
||||
button_ok,
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,11 +60,15 @@ struct Imgs {
|
||||
button: ImgId,
|
||||
button_hover: ImgId,
|
||||
button_press: ImgId,
|
||||
|
||||
error_frame: ImgId,
|
||||
button_dark: ImgId,
|
||||
button_dark_hover: ImgId,
|
||||
button_dark_press: ImgId,
|
||||
}
|
||||
impl Imgs {
|
||||
fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs {
|
||||
// TODO: update paths
|
||||
let mut load = |filename| {
|
||||
let load_img = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/", filename].concat();
|
||||
let image = image::load_from_memory(
|
||||
assets::load(fullpath.as_str())
|
||||
@ -64,24 +76,41 @@ impl Imgs {
|
||||
.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
ui.new_image(renderer, &image).unwrap()
|
||||
ui.new_graphic(ui::Graphic::Image(image))
|
||||
};
|
||||
let 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_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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,6 +120,7 @@ pub enum Event {
|
||||
username: String,
|
||||
server_address: String,
|
||||
},
|
||||
StartSingleplayer,
|
||||
Quit,
|
||||
}
|
||||
|
||||
@ -116,20 +146,16 @@ impl MainMenuUi {
|
||||
// Load images
|
||||
let imgs = Imgs::new(&mut ui, window.renderer_mut());
|
||||
// Load fonts
|
||||
let font_opensans = ui.new_font(
|
||||
conrod_core::text::font::from_file(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../assets/voxygen/font/OpenSans-Regular.ttf"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let font_metamorph = ui.new_font(
|
||||
conrod_core::text::font::from_file(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/../assets/voxygen/font/Metamorphous-Regular.ttf"
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
let load_font = |filename, ui: &mut Ui| {
|
||||
let fullpath: String = ["/voxygen/font", filename].concat();
|
||||
ui.new_font(conrod_core::text::Font::from_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
).unwrap())
|
||||
};
|
||||
let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui);
|
||||
let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui);
|
||||
|
||||
Self {
|
||||
ui,
|
||||
imgs,
|
||||
@ -137,7 +163,7 @@ impl MainMenuUi {
|
||||
font_metamorph,
|
||||
font_opensans,
|
||||
username: "Username".to_string(),
|
||||
server_address: "veloren.mac94.de".to_string(),
|
||||
server_address: DEFAULT_PUBLIC_SERVER.to_string(),
|
||||
login_error: None,
|
||||
connecting: None,
|
||||
}
|
||||
@ -146,6 +172,7 @@ impl MainMenuUi {
|
||||
fn update_layout(&mut self) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
let ref mut ui_widgets = self.ui.set_widgets();
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
// Background image, Veloren logo, Alpha-Version Label
|
||||
Image::new(self.imgs.bg)
|
||||
.middle_of(ui_widgets.window)
|
||||
@ -153,7 +180,7 @@ impl MainMenuUi {
|
||||
Button::image(self.imgs.v_logo)
|
||||
.w_h(346.0, 111.0)
|
||||
.top_left_with_margins(30.0, 40.0)
|
||||
.label("Alpha 0.1")
|
||||
.label(version)
|
||||
.label_rgba(1.0, 1.0, 1.0, 1.0)
|
||||
.label_font_size(10)
|
||||
.label_y(Relative::Scalar(-40.0))
|
||||
@ -172,6 +199,20 @@ impl MainMenuUi {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
//Singleplayer
|
||||
//Used when the singleplayer button is pressed
|
||||
macro_rules! singleplayer {
|
||||
() => {
|
||||
self.login_error = None;
|
||||
events.push(Event::StartSingleplayer);
|
||||
events.push(Event::LoginAttempt {
|
||||
username: "singleplayer".to_string(),
|
||||
server_address: "localhost".to_string(),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||
// Username
|
||||
// TODO: get a lower resolution and cleaner input_bg.png
|
||||
@ -203,20 +244,34 @@ impl MainMenuUi {
|
||||
// Login error
|
||||
if let Some(msg) = &self.login_error {
|
||||
let text = Text::new(&msg)
|
||||
.rgba(0.5, 0.0, 0.0, 1.0)
|
||||
.rgba(1.0, 1.0, 1.0, 1.0)
|
||||
.font_size(30)
|
||||
.font_id(self.font_opensans);
|
||||
let x = match text.get_x_dimension(ui_widgets) {
|
||||
Dimension::Absolute(x) => x + 10.0,
|
||||
_ => 0.0,
|
||||
};
|
||||
Rectangle::fill([x, 40.0])
|
||||
.rgba(0.2, 0.3, 0.3, 0.7)
|
||||
Rectangle::fill_with([400.0, 100.0], color::TRANSPARENT)
|
||||
.rgba(0.1, 0.1, 0.1, 1.0)
|
||||
.parent(ui_widgets.window)
|
||||
.up_from(self.ids.username_bg, 35.0)
|
||||
.mid_top_with_margin_on(self.ids.username_bg, -35.0)
|
||||
.set(self.ids.login_error_bg, ui_widgets);
|
||||
text.middle_of(self.ids.login_error_bg)
|
||||
Image::new(self.imgs.error_frame)
|
||||
.w_h(400.0, 100.0)
|
||||
.middle_of(self.ids.login_error_bg)
|
||||
.set(self.ids.error_frame, ui_widgets);
|
||||
text.mid_top_with_margin_on(self.ids.error_frame, 10.0)
|
||||
.set(self.ids.login_error, ui_widgets);
|
||||
if Button::image(self.imgs.button_dark)
|
||||
.w_h(100.0, 30.0)
|
||||
.mid_bottom_with_margin_on(self.ids.login_error_bg, 5.0)
|
||||
.hover_image(self.imgs.button_dark_hover)
|
||||
.press_image(self.imgs.button_dark_press)
|
||||
.label_y(Relative::Scalar(2.0))
|
||||
.label("Okay")
|
||||
.label_font_size(10)
|
||||
.label_color(TEXT_COLOR)
|
||||
.set(self.ids.button_ok, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
self.login_error = None
|
||||
};
|
||||
}
|
||||
// Server address
|
||||
Image::new(self.imgs.input_bg)
|
||||
@ -290,12 +345,13 @@ impl MainMenuUi {
|
||||
.align_middle_x_of(self.ids.address_bg)
|
||||
.label("Singleplayer")
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(26)
|
||||
.label_font_size(24)
|
||||
.label_y(Relative::Scalar(5.0))
|
||||
.label_x(Relative::Scalar(2.0))
|
||||
.set(self.ids.singleplayer_button, ui_widgets)
|
||||
.was_clicked()
|
||||
{
|
||||
singleplayer!();
|
||||
login!();
|
||||
}
|
||||
// Quit
|
||||
|
@ -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,
|
||||
|
@ -8,7 +8,8 @@ use client::Client;
|
||||
use common::{
|
||||
comp,
|
||||
figure::Segment,
|
||||
msg
|
||||
msg,
|
||||
assets,
|
||||
};
|
||||
use crate::{
|
||||
Error,
|
||||
@ -43,19 +44,25 @@ impl Figures {
|
||||
pub fn new(renderer: &mut Renderer) -> Self {
|
||||
// TODO: Make a proper asset loading system
|
||||
fn load_segment(filename: &'static str) -> Segment {
|
||||
Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/voxel/").to_string() + filename)).unwrap())
|
||||
let fullpath: String = ["/voxygen/voxel/", filename].concat();
|
||||
Segment::from(dot_vox::load_bytes(
|
||||
assets::load(fullpath.as_str())
|
||||
.expect("Error loading file")
|
||||
.as_slice(),
|
||||
).unwrap())
|
||||
}
|
||||
|
||||
let bone_meshes = [
|
||||
Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))),
|
||||
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))),
|
||||
Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))),
|
||||
Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))),
|
||||
|
||||
Some(load_segment("head.vox").generate_mesh(Vec3::new(-3.5, -7.0, -6.0))),
|
||||
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))),
|
||||
Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))),
|
||||
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))),
|
||||
Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))),
|
||||
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))),
|
||||
Some(load_segment("sword.vox").generate_mesh(Vec3::new(0.0, -0.0, 0.0))),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -82,19 +89,19 @@ impl Figures {
|
||||
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||
let time = client.state().get_time();
|
||||
let ecs = client.state_mut().ecs_mut().internal_mut();
|
||||
for (entity, pos, dir, character, animation) in (
|
||||
let ecs = client.state_mut().ecs_mut();
|
||||
for (entity, pos, dir, character, animation_history) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<comp::phys::Pos>(),
|
||||
&ecs.read_storage::<comp::phys::Dir>(),
|
||||
&ecs.read_storage::<comp::Character>(),
|
||||
&ecs.read_storage::<comp::Animation>(),
|
||||
&ecs.read_storage::<comp::AnimationHistory>(),
|
||||
).join() {
|
||||
let state = self.states
|
||||
.entry(entity)
|
||||
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
||||
|
||||
let target_skeleton = match animation {
|
||||
let target_skeleton = match animation_history.current {
|
||||
comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time),
|
||||
comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time),
|
||||
};
|
||||
@ -138,7 +145,7 @@ impl<S: Skeleton> FigureState<S> {
|
||||
let mat =
|
||||
Mat4::<f32>::identity() *
|
||||
Mat4::translation_3d(pos) *
|
||||
Mat4::rotation_z(dir.y.atan2(dir.x) + f32::consts::PI / 2.0);
|
||||
Mat4::rotation_z(dir.y.atan2(dir.x));// + f32//::consts)::PI / 2.0);
|
||||
|
||||
let locals = FigureLocals::new(mat);
|
||||
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
||||
|
@ -111,7 +111,6 @@ impl Scene {
|
||||
let player_pos = client
|
||||
.state()
|
||||
.ecs()
|
||||
.internal()
|
||||
.read_storage::<comp::phys::Pos>()
|
||||
.get(client.player())
|
||||
.map(|pos| pos.0)
|
||||
|
@ -120,19 +120,20 @@ impl PlayState for SessionState {
|
||||
// Handle window events
|
||||
for event in global_state.window.fetch_events() {
|
||||
|
||||
// Pass all events to the ui first
|
||||
if self.hud.handle_event(event.clone()) {
|
||||
// Pass all events to the ui first
|
||||
if self.hud.handle_event(event.clone(), global_state) {
|
||||
continue;
|
||||
}
|
||||
let _handled = match event {
|
||||
Event::Close => return PlayStateResult::Shutdown,
|
||||
Event::Close => {
|
||||
global_state.singleplayer = None;
|
||||
return PlayStateResult::Shutdown;
|
||||
},
|
||||
// Toggle cursor grabbing
|
||||
Event::KeyDown(Key::ToggleCursor) => {
|
||||
global_state
|
||||
.window
|
||||
.grab_cursor(!global_state.window.is_cursor_grabbed());
|
||||
self.hud
|
||||
.update_grab(global_state.window.is_cursor_grabbed());
|
||||
}
|
||||
// Movement Key Pressed
|
||||
Event::KeyDown(Key::MoveForward) => self.key_state.up = true,
|
||||
@ -166,7 +167,10 @@ impl PlayState for SessionState {
|
||||
self.client.borrow_mut().send_chat(msg);
|
||||
},
|
||||
HudEvent::Logout => return PlayStateResult::Pop,
|
||||
HudEvent::Quit => return PlayStateResult::Shutdown,
|
||||
HudEvent::Quit => {
|
||||
global_state.singleplayer = None;
|
||||
return PlayStateResult::Shutdown;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ pub struct ControlSettings {
|
||||
pub spellbook: VirtualKeyCode,
|
||||
pub settings: VirtualKeyCode,
|
||||
pub help: VirtualKeyCode,
|
||||
pub interface: VirtualKeyCode,
|
||||
pub toggle_interface: VirtualKeyCode,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@ -56,7 +56,7 @@ impl Default for Settings {
|
||||
spellbook: VirtualKeyCode::P,
|
||||
settings: VirtualKeyCode::N,
|
||||
help: VirtualKeyCode::F1,
|
||||
interface: VirtualKeyCode::F2,
|
||||
toggle_interface: VirtualKeyCode::F2,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
81
voxygen/src/singleplayer.rs
Normal file
81
voxygen/src/singleplayer.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use std::time::Duration;
|
||||
use log::info;
|
||||
use server::{Input, Event, Server};
|
||||
use common::clock::Clock;
|
||||
use std::{
|
||||
thread,
|
||||
thread::JoinHandle
|
||||
};
|
||||
use std::sync::mpsc::{
|
||||
channel, Receiver, Sender, TryRecvError,
|
||||
};
|
||||
|
||||
const TPS: u64 = 30;
|
||||
|
||||
enum Msg {
|
||||
Stop,
|
||||
}
|
||||
|
||||
/// Used to start and stop the background thread running the server
|
||||
/// when in singleplayer mode.
|
||||
pub struct Singleplayer {
|
||||
server_thread: JoinHandle<()>,
|
||||
sender: Sender<Msg>,
|
||||
}
|
||||
|
||||
impl Singleplayer {
|
||||
pub fn new() -> Self {
|
||||
let (sender, reciever) = channel();
|
||||
let thread = thread::spawn(move || {
|
||||
run_server(reciever);
|
||||
});
|
||||
Singleplayer {
|
||||
server_thread: thread,
|
||||
sender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Singleplayer {
|
||||
fn drop(&mut self) {
|
||||
self.sender.send(Msg::Stop);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_server(rec: Receiver<Msg>) {
|
||||
info!("Starting server-cli...");
|
||||
|
||||
// Set up an fps clock
|
||||
let mut clock = Clock::new();
|
||||
|
||||
// Create server
|
||||
let mut server = Server::new()
|
||||
.expect("Failed to create server instance");
|
||||
|
||||
loop {
|
||||
let events = server.tick(Input::default(), clock.get_last_delta())
|
||||
.expect("Failed to tick server");
|
||||
|
||||
for event in events {
|
||||
match event {
|
||||
Event::ClientConnected { entity } => info!("Client connected!"),
|
||||
Event::ClientDisconnected { entity } => info!("Client disconnected!"),
|
||||
Event::Chat { entity, msg } => info!("[Client] {}", msg),
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the server after a tick
|
||||
server.cleanup();
|
||||
|
||||
match rec.try_recv() {
|
||||
Ok(msg) => break,
|
||||
Err(err) => match err {
|
||||
TryRecvError::Empty => (),
|
||||
TryRecvError::Disconnected => break,
|
||||
},
|
||||
}
|
||||
|
||||
// Wait for the next tick
|
||||
clock.tick(Duration::from_millis(1000 / TPS));
|
||||
}
|
||||
}
|
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,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
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,
|
||||
}
|
||||
}
|
@ -51,7 +51,7 @@ impl Window {
|
||||
key_map.insert(settings.controls.spellbook, Key::Spellbook);
|
||||
key_map.insert(settings.controls.settings, Key::Settings);
|
||||
key_map.insert(settings.controls.help, Key::Help);
|
||||
key_map.insert(settings.controls.interface, Key::Interface);
|
||||
key_map.insert(settings.controls.toggle_interface, Key::ToggleInterface);
|
||||
|
||||
let tmp = Ok(Self {
|
||||
events_loop,
|
||||
@ -180,7 +180,7 @@ pub enum Key {
|
||||
Social,
|
||||
Spellbook,
|
||||
Settings,
|
||||
Interface,
|
||||
ToggleInterface,
|
||||
Help,
|
||||
}
|
||||
|
||||
|
BIN
voxygen/test_assets/body.vox
Normal file
BIN
voxygen/test_assets/body.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_body.vox
Normal file
BIN
voxygen/test_assets/dragon_body.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_lfoot.vox
Normal file
BIN
voxygen/test_assets/dragon_lfoot.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_rfoot.vox
Normal file
BIN
voxygen/test_assets/dragon_rfoot.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_tail.vox
Normal file
BIN
voxygen/test_assets/dragon_tail.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_wingL_in.vox
Normal file
BIN
voxygen/test_assets/dragon_wingL_in.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_wingL_out.vox
Normal file
BIN
voxygen/test_assets/dragon_wingL_out.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_wingR_in.vox
Normal file
BIN
voxygen/test_assets/dragon_wingR_in.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragon_wingR_out.vox
Normal file
BIN
voxygen/test_assets/dragon_wingR_out.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/dragonhead.vox
Normal file
BIN
voxygen/test_assets/dragonhead.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/foot_BL.vox
Normal file
BIN
voxygen/test_assets/foot_BL.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/foot_BR.vox
Normal file
BIN
voxygen/test_assets/foot_BR.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/foot_FL.vox
Normal file
BIN
voxygen/test_assets/foot_FL.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/foot_FR.vox
Normal file
BIN
voxygen/test_assets/foot_FR.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/lionhead.vox
Normal file
BIN
voxygen/test_assets/lionhead.vox
Normal file
Binary file not shown.
BIN
voxygen/test_assets/sabremale.vox
Normal file
BIN
voxygen/test_assets/sabremale.vox
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user