Pedantic comment and language fixes.

Former-commit-id: eb49765c911aaa97a9c8ed351216a7a6f8411213
This commit is contained in:
Cody 2019-05-17 05:22:32 -04:00
parent 96cdbdb881
commit 6b09fd7c53
80 changed files with 835 additions and 816 deletions

View File

@ -4,8 +4,8 @@ stages:
- post-build
- executable
# 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
# 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 don't need any gitlab caches.
variables:
GIT_STRATEGY: none
before_script:

View File

@ -6,15 +6,15 @@ use std::time::Duration;
const FPS: u64 = 60;
fn main() {
// Init logging
// Initialize logging.
pretty_env_logger::init();
info!("Starting chat-cli...");
// Set up an fps clock
// Set up an fps clock.
let mut clock = Clock::new();
// Create client
// Create a client.
let mut client =
Client::new(([127, 0, 0, 1], 59003), 300).expect("Failed to create client instance");
@ -38,10 +38,10 @@ fn main() {
}
}
// Clean up the server after a tick
// Clean up the server after a tick.
client.cleanup();
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / FPS));
}
}

View File

@ -95,7 +95,7 @@ impl Client {
}
/// Get a reference to the client's worker thread pool. This pool should be used for any
/// computationally expensive operations that run outside of the main thread (i.e: threads that
/// computationally expensive operations that run outside of the main thread (i.e., threads that
/// block on I/O operations are exempt).
#[allow(dead_code)]
pub fn thread_pool(&self) -> &threadpool::ThreadPool {
@ -114,7 +114,7 @@ impl Client {
&mut self.state
}
/// Get the player's entity
/// Get the player's entity.
#[allow(dead_code)]
pub fn entity(&self) -> EcsEntity {
self.entity
@ -126,13 +126,13 @@ impl Client {
self.tick
}
/// Send a chat message to the server
/// Send a chat message to the server.
#[allow(dead_code)]
pub fn send_chat(&mut self, msg: String) {
self.postbox.send_message(ClientMsg::Chat(msg))
}
/// Execute a single client tick, handle input and update the game state by the given duration
/// Execute a single client tick, handle input and update the game state by the given duration.
#[allow(dead_code)]
pub fn tick(&mut self, input: Input, dt: Duration) -> Result<Vec<Event>, Error> {
// This tick function is the centre of the Veloren universe. Most client-side things are
@ -147,13 +147,13 @@ impl Client {
// 4) Go through the terrain update queue and apply all changes to the terrain
// 5) Finish the tick, passing control of the main thread back to the frontend
// Build up a list of events for this frame, to be passed to the frontend
// Build up a list of events for this frame, to be passed to the frontend.
let mut frontend_events = Vec::new();
// Handle new messages from the server
// Handle new messages from the server.
frontend_events.append(&mut self.handle_new_messages()?);
// Pass character control from frontend input to the player's entity
// Pass character control from frontend input to the player's entity.
// TODO: Only do this if the entity already has a Control component!
self.state.write_component(
self.entity,
@ -164,10 +164,10 @@ impl Client {
},
);
// Tick the client's LocalState (step 3)
// Tick the client's LocalState (step 3).
self.state.tick(dt);
// Update the server about the player's physics attributes
// Update the server about the player's physics attributes.
match (
self.state.read_storage().get(self.entity).cloned(),
self.state.read_storage().get(self.entity).cloned(),
@ -180,7 +180,7 @@ impl Client {
_ => {}
}
// Update the server about the player's currently playing animation and the previous one
// 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>()
@ -201,7 +201,7 @@ impl Client {
if let Some(pos) = pos {
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
// Remove chunks that are too far from the player
// Remove chunks that are too far from the player.
let mut chunks_to_remove = Vec::new();
self.state.terrain().iter().for_each(|(key, _)| {
if (Vec2::from(chunk_pos) - Vec2::from(key))
@ -216,8 +216,8 @@ impl Client {
self.state.remove_chunk(key);
}
// Request chunks from the server
// TODO: This is really not very efficient
// Request chunks from the server.
// TODO: This is really inefficient.
'outer: for dist in 0..10 {
for i in chunk_pos.x - dist..chunk_pos.x + dist + 1 {
for j in chunk_pos.y - dist..chunk_pos.y + dist + 1 {
@ -237,25 +237,25 @@ impl Client {
}
}
// If chunks are taking too long, assume they're no longer pending
// If chunks are taking too long, assume they're no longer pending.
let now = Instant::now();
self.pending_chunks
.retain(|_, created| now.duration_since(*created) < Duration::from_secs(10));
}
// Finish the tick, pass control back to the frontend (step 6)
// Finish the tick, pass control back to the frontend (step 6).
self.tick += 1;
Ok(frontend_events)
}
/// Clean up the client after a tick
/// Clean up the client after a tick.
#[allow(dead_code)]
pub fn cleanup(&mut self) {
// Cleanup the local state
self.state.cleanup();
}
/// Handle new server messages
/// Handle new server messages.
fn handle_new_messages(&mut self) -> Result<Vec<Event>, Error> {
let mut frontend_events = Vec::new();
@ -324,7 +324,7 @@ impl Client {
} else if self.state.get_time() - self.last_ping > SERVER_TIMEOUT {
return Err(Error::ServerTimeout);
} else if self.state.get_time() - self.last_ping > SERVER_TIMEOUT * 0.5 {
// Try pinging the server if the timeout is nearing
// Try pinging the server if the timeout is nearing.
self.postbox.send_message(ClientMsg::Ping);
}

View File

@ -12,9 +12,9 @@ use std::{
#[derive(Debug, Clone)]
pub enum Error {
/// An asset of a different type has already been loaded with this specifier
/// An asset of a different type has already been loaded with this specifier.
InvalidType,
/// Asset does not exist
/// Asset does not exist.
NotFound(String),
}
@ -35,8 +35,8 @@ lazy_static! {
RwLock::new(HashMap::new());
}
/// Function used to load assets
/// loaded assets are cached in a global singleton hashmap
/// Function used to load assets.
/// Loaded assets are cached in a global singleton hashmap.
/// Example usage:
/// ```no_run
/// use image::DynamicImage;
@ -54,9 +54,9 @@ pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
.downcast()?)
}
/// Function used to load assets that will panic if the asset is not found
/// Use this to load essential assets
/// loaded assets are cached in a global singleton hashmap
/// Function used to load assets that will panic if the asset is not found.
/// Use this to load essential assets.
/// Loaded assets are cached in a global singleton hashmap.
/// Example usage:
/// ```no_run
/// use image::DynamicImage;
@ -89,11 +89,11 @@ impl Asset for DotVoxData {
}
}
// TODO: System to load file from specifiers (eg "core.ui.backgrounds.city")
// TODO: System to load file from specifiers (e.g.: "core.ui.backgrounds.city").
fn try_open_with_path(name: &str) -> Option<File> {
debug!("Trying to access \"{}\"", name);
// TODO: don't do this?
// if it's stupid and it works..,
// TODO: Don't do this?
// If it's stupid but it works...
[
"assets".to_string(),
"../assets".to_string(), /* optimizations */

View File

@ -43,7 +43,7 @@ impl Clock {
.duration_since(self.last_sys_time)
.expect("Time went backwards!");
// Attempt to sleep to fill the gap
// Attempt to sleep to fill the gap.
if let Some(sleep_dur) = tgt.checked_sub(delta) {
let adjustment = if self.running_tps_average == 0.0 {
1.0

View File

@ -71,24 +71,23 @@ pub enum Draw {
}
////
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Pighead {
pub enum PigHead {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Pigchest {
pub enum PigChest {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Pigleg_l {
pub enum PigLegL {
Default,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Pigleg_r {
pub enum PigLegR {
Default,
}
////
const ALL_RACES: [Race; 6] = [
Race::Danari,
@ -158,19 +157,19 @@ const ALL_QRACES: [Race; 6] = [
Race::Undead,
];
const ALL_QBODY_TYPES: [BodyType; 3] = [BodyType::Female, BodyType::Male, BodyType::Unspecified];
const ALL_QHEADS: [Pighead; 1] = [Pighead::Default];
const ALL_QCHESTS: [Pigchest; 1] = [Pigchest::Default];
const ALL_QPIGLEG_LS: [Pigleg_l; 1] = [Pigleg_l::Default];
const ALL_QPIGLEG_RS: [Pigleg_r; 1] = [Pigleg_r::Default];
const ALL_QPIG_HEADS: [PigHead; 1] = [PigHead::Default];
const ALL_QPIG_CHESTS: [PigChest; 1] = [PigChest::Default];
const ALL_QPIG_LEG_LS: [PigLegL; 1] = [PigLegL::Default];
const ALL_QPIG_LEG_RS: [PigLegR; 1] = [PigLegR::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct QuadrupedBody {
pub race: Race,
pub body_type: BodyType,
pub pighead: Pighead,
pub pigchest: Pigchest,
pub pigleg_l: Pigleg_l,
pub pigleg_r: Pigleg_r,
pub pig_head: PigHead,
pub pig_chest: PigChest,
pub pig_leg_l: PigLegL,
pub pig_leg_r: PigLegR,
}
impl QuadrupedBody {
@ -178,10 +177,10 @@ impl QuadrupedBody {
Self {
race: *thread_rng().choose(&ALL_QRACES).unwrap(),
body_type: *thread_rng().choose(&ALL_QBODY_TYPES).unwrap(),
pighead: *thread_rng().choose(&ALL_QHEADS).unwrap(),
pigchest: *thread_rng().choose(&ALL_QCHESTS).unwrap(),
pigleg_l: *thread_rng().choose(&ALL_QPIGLEG_LS).unwrap(),
pigleg_r: *thread_rng().choose(&ALL_QPIGLEG_RS).unwrap(),
pig_head: *thread_rng().choose(&ALL_QPIG_HEADS).unwrap(),
pig_chest: *thread_rng().choose(&ALL_QPIG_CHESTS).unwrap(),
pig_leg_l: *thread_rng().choose(&ALL_QPIG_LEG_LS).unwrap(),
pig_leg_r: *thread_rng().choose(&ALL_QPIG_LEG_RS).unwrap(),
}
}
}

View File

@ -1,7 +1,7 @@
use specs::{Component, FlaggedStorage, NullStorage, VecStorage};
use vek::*;
// Pos
// Position
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct Pos(pub Vec3<f32>);
@ -10,7 +10,7 @@ impl Component for Pos {
type Storage = VecStorage<Self>;
}
// Vel
// Velocity
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct Vel(pub Vec3<f32>);
@ -19,7 +19,7 @@ impl Component for Vel {
type Storage = VecStorage<Self>;
}
// Dir
// Direction
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct Dir(pub Vec3<f32>);
@ -28,7 +28,7 @@ impl Component for Dir {
type Storage = VecStorage<Self>;
}
// Dir
// Update
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
pub struct ForceUpdate;

View File

@ -4,7 +4,7 @@ use vek::*;
// Crate
use crate::vol::Vox;
/// A type representing a single voxel in a figure
/// A type representing a single voxel in a figure.
#[derive(Copy, Clone, Debug)]
pub enum Cell {
Filled([u8; 3]),

View File

@ -23,7 +23,7 @@ pub mod util;
pub mod vol;
pub mod volumes;
/// The networking module containing high-level wrappers of `TcpListener` and `TcpStream` (`PostOffice` and `PostBox` respectively) and data types used by both the server and client
/// The networking module containing high-level wrappers of `TcpListener` and `TcpStream` (`PostOffice` and `PostBox` respectively) and data types used by both the server and client.
/// # Examples
/// ```
/// use std::net::SocketAddr;

View File

@ -2,7 +2,8 @@ use crate::{comp, state};
use serde_derive::{Deserialize, Serialize};
use std::marker::PhantomData;
// Automatically derive From<T> for EcsResPacket for each variant EcsResPacket::T(T)
// Automatically derive From<T> for EcsResPacket
// for each variant EcsResPacket::T(T).
sphynx::sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsResPacket {
@ -11,7 +12,8 @@ sphynx::sum_type! {
}
}
impl sphynx::ResPacket for EcsResPacket {}
// Automatically derive From<T> for EcsCompPacket for each variant EcsCompPacket::T(T)
// Automatically derive From<T> for EcsCompPacket
// for each variant EcsCompPacket::T(T.)
sphynx::sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsCompPacket {
@ -23,7 +25,8 @@ sphynx::sum_type! {
Stats(comp::Stats),
}
}
// Automatically derive From<T> for EcsCompPhantom for each variant EcsCompPhantom::T(PhantomData<T>)
// Automatically derive From<T> for EcsCompPhantom
// for each variant EcsCompPhantom::T(PhantomData<T>).
sphynx::sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsCompPhantom {

View File

@ -1,18 +1,18 @@
/// Messages server sends to client
/// Messages server sends to client.
#[derive(Deserialize, Serialize, Debug)]
pub enum ServerMsg {
// VersionInfo MUST always stay first in this struct
// VersionInfo MUST always stay first in this struct.
VersionInfo {},
}
/// Messages client sends to server
/// Messages client sends to server.
#[derive(Deserialize, Serialize, Debug)]
pub enum ClientMsg {
// VersionInfo MUST always stay first in this struct
// VersionInfo MUST always stay first in this struct.
VersionInfo {},
}
/// Control message type, used in [PostBox](super::PostBox) and [PostOffice](super::PostOffice) to control threads
/// Control message type, used in [PostBox](super::PostBox) and [PostOffice](super::PostOffice) to control threads.
pub enum ControlMsg {
Shutdown,
}

View File

@ -253,7 +253,7 @@ impl<S: PostSend, R: PostRecv> PostBox<S, R> {
let _ = self.send_tx.send(data);
}
// TODO: This method is super messy
// TODO: This method is super messy.
pub fn next_message(&mut self) -> Option<R> {
if self.err.is_some() {
return None;
@ -528,14 +528,14 @@ fn connect() {
let mut postoffice = PostOffice::<TestMsg<u32>, TestMsg<f32>>::bind(srv_addr).unwrap();
// We should start off with 0 incoming connections
// We should start off with 0 incoming connections.
thread::sleep(Duration::from_millis(250));
assert_eq!(postoffice.new_connections().len(), 0);
assert_eq!(postoffice.error(), None);
let postbox = PostBox::<TestMsg<f32>, TestMsg<u32>>::to_server(srv_addr).unwrap();
// Now a postbox has been created, we should have 1 new
// Now a postbox has been created, we should have 1 new.
thread::sleep(Duration::from_millis(250));
let incoming = postoffice.new_connections();
assert_eq!(incoming.len(), 1);
@ -549,7 +549,7 @@ fn connect_fail() {
let mut postoffice = PostOffice::<TestMsg<u32>, TestMsg<f32>>::bind(listen_addr).unwrap();
// We should start off with 0 incoming connections
// We should start off with 0 incoming connections.
thread::sleep(Duration::from_millis(250));
assert_eq!(postoffice.new_connections().len(), 0);
assert_eq!(postoffice.error(), None);
@ -564,7 +564,7 @@ fn connection_count() {
let mut postoffice = PostOffice::<TestMsg<u32>, TestMsg<f32>>::bind(srv_addr).unwrap();
let mut postboxes = Vec::new();
// We should start off with 0 incoming connections
// We should start off with 0 incoming connections.
thread::sleep(Duration::from_millis(250));
assert_eq!(postoffice.new_connections().len(), 0);
assert_eq!(postoffice.error(), None);
@ -573,7 +573,7 @@ fn connection_count() {
postboxes.push(PostBox::<TestMsg<f32>, TestMsg<u32>>::to_server(srv_addr).unwrap());
}
// 5 postboxes created, we should have 5
// 5 postboxes created, we should have 5.
thread::sleep(Duration::from_millis(3500));
let incoming = postoffice.new_connections();
assert_eq!(incoming.len(), 5);
@ -597,7 +597,7 @@ fn disconnect() {
incoming.next().unwrap()
};
// The client postbox has since been disconnected
// The client postbox has since been disconnected.
thread::sleep(Duration::from_millis(2050));
let incoming_msgs = server_postbox.new_messages();
assert_eq!(incoming_msgs.len(), 0);

View File

@ -188,7 +188,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
Ok(None) => {}
}
// Try getting messages from the send channel
// Try getting messages from the send channel.
for _ in 0..100 {
match send_rx.try_recv() {
Ok(send_msg) => {
@ -202,12 +202,12 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
}
*/
// Assemble into packet
// Assemble into packet.
let mut packet_bytes = msg_bytes.len().to_le_bytes().as_ref().to_vec();
packet_bytes.push(msg_bytes.iter().fold(0, |a, x| a ^ *x));
packet_bytes.append(&mut msg_bytes);
// Split packet into chunks
// Split packet into chunks.
packet_bytes
.chunks(4096)
.map(|chunk| chunk.to_vec())
@ -222,7 +222,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
}
}
// Try sending bytes through the TCP stream
// Try sending bytes through the TCP stream.
for _ in 0..100 {
match outgoing_chunks.pop_front() {
Some(mut chunk) => match stream.write(&chunk) {
@ -232,7 +232,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
break;
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
// Return chunk to the queue to try again later
// Return chunk to the queue to try again later.
outgoing_chunks.push_front(chunk);
break;
}
@ -246,7 +246,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
}
}
// Try receiving bytes from the TCP stream
// Try receiving bytes from the TCP stream.
for _ in 0..100 {
let mut buf = [0; 4096];
@ -262,7 +262,7 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
}
}
// Try turning bytes into messages
// Try turning bytes into messages.
for _ in 0..100 {
match incoming_buf.get(0..9) {
Some(len_bytes) => {

View File

@ -54,7 +54,7 @@ impl<'a, V: ReadVol, F: RayUntil<V::Vox>> Ray<'a, V, F> {
pos = self.from + dir * dist;
ipos = pos.map(|e| e.floor() as i32);
// Allow one iteration above max
// Allow one iteration above max.
if dist > max {
break;
}

View File

@ -20,25 +20,25 @@ use std::{collections::HashSet, sync::Arc, time::Duration};
use vek::*;
/// How much faster should an in-game day be compared to a real day?
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
const DAY_CYCLE_FACTOR: f64 = 24.0 * 60.0;
/// A resource to store the time of day
/// A resource that stores the time of day.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TimeOfDay(f64);
/// A resource to store the tick (i.e: physics) time
/// A resource that stores the tick (i.e: physics) time.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Time(f64);
/// A resource used to store the time since the last tick
/// A resource that stores the time since the previous tick.
#[derive(Default)]
pub struct DeltaTime(pub f32);
/// At what point should we stop speeding up physics to compensate for lag? If we speed physics up
/// too fast, we'd skip important physics events like collisions. This constant determines what
/// the upper limit is. If delta time exceeds this value, the game's physics will begin to produce
/// time lag. Ideally, we'd avoid such a situation.
/// too fast, we'd skip important physics events like collisions. This constant determines the
/// upper limit. If delta time exceeds this value, the game's physics will begin to produce time
/// lag. Ideally, we'd avoid such a situation.
const MAX_DELTA_TIME: f32 = 0.15;
pub struct Changes {
@ -64,7 +64,7 @@ impl Changes {
}
/// A type used to represent game state stored on both the client and the server. This includes
/// things like entity components, terrain data, and global state like weather, time of day, etc.
/// things like entity components, terrain data, and global states like weather, time of day, etc.
pub struct State {
ecs: sphynx::World<EcsCompPacket, EcsResPacket>,
// Avoid lifetime annotation by storing a thread pool instead of the whole dispatcher
@ -82,7 +82,7 @@ impl State {
}
}
/// Create a new `State` from an ECS state package
/// Create a new `State` from an ECS state package.
pub fn from_state_package(
state_package: sphynx::StatePackage<EcsCompPacket, EcsResPacket>,
) -> Self {
@ -97,14 +97,14 @@ impl State {
}
}
// Create a new Sphynx ECS world
// Create a new Sphynx ECS world.
fn setup_sphynx_world(ecs: &mut sphynx::World<EcsCompPacket, EcsResPacket>) {
// Register synced components
// Register synced components.
ecs.register_synced::<comp::Actor>();
ecs.register_synced::<comp::Player>();
ecs.register_synced::<comp::Stats>();
// Register unsynched (or synced by other means) components
// Register unsynced (or synced by other means) components.
ecs.register::<comp::phys::Pos>();
ecs.register::<comp::phys::Vel>();
ecs.register::<comp::phys::Dir>();
@ -112,16 +112,16 @@ impl State {
ecs.register::<comp::Agent>();
ecs.register::<comp::Control>();
// Register synced resources used by the ECS
// Register synced resources used by the ECS.
ecs.add_resource_synced(TimeOfDay(0.0));
// Register unsynced resources used by the ECS
// Register unsynced resources used by the ECS.
ecs.add_resource(Time(0.0));
ecs.add_resource(DeltaTime(0.0));
ecs.add_resource(TerrainMap::new().unwrap());
}
/// Register a component with the state's ECS
/// Register a component with the state's ECS.
pub fn with_component<T: Component>(mut self) -> Self
where
<T as Component>::Storage: Default,
@ -130,27 +130,27 @@ impl State {
self
}
/// Write a component attributed to a particular entity
/// Write a component attributed to a particular entity.
pub fn write_component<C: Component>(&mut self, entity: EcsEntity, comp: C) {
let _ = self.ecs.write_storage().insert(entity, comp);
}
/// Read a component attributed to a particular entity
/// Read a component attributed to a particular entity.
pub fn read_component_cloned<C: Component + Clone>(&self, entity: EcsEntity) -> Option<C> {
self.ecs.read_storage().get(entity).cloned()
}
/// Get a read-only reference to the storage of a particular component type
/// 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.read_storage::<C>()
}
/// Get a reference to the internal ECS world
/// Get a reference to the internal ECS world.
pub fn ecs(&self) -> &sphynx::World<EcsCompPacket, EcsResPacket> {
&self.ecs
}
/// Get a mutable reference to the internal ECS world
/// Get a mutable reference to the internal ECS world.
pub fn ecs_mut(&mut self) -> &mut sphynx::World<EcsCompPacket, EcsResPacket> {
&mut self.ecs
}
@ -194,7 +194,7 @@ impl State {
}
}
/// Remove the chunk with the given key from this state's terrain, if it exists
/// Remove the chunk with the given key from this state's terrain, if it exists.
pub fn remove_chunk(&mut self, key: Vec2<i32>) {
if self
.ecs
@ -208,27 +208,27 @@ 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
// Change the time accordingly.
self.ecs.write_resource::<TimeOfDay>().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR;
self.ecs.write_resource::<Time>().0 += dt.as_secs_f64();
// Update delta time
// Above a delta time of MAX_DELTA_TIME, start lagging to avoid skipping important physics events
// Update delta time.
// Beyond a delta time of MAX_DELTA_TIME, start lagging to avoid skipping important physics events.
self.ecs.write_resource::<DeltaTime>().0 = dt.as_secs_f32().min(MAX_DELTA_TIME);
// Run systems to update the world
// Create and run dispatcher for ecs systems
// Run systems to update the world.
// Create and run a dispatcher for ecs systems.
let mut dispatch_builder = DispatcherBuilder::new().with_pool(self.thread_pool.clone());
sys::add_local_systems(&mut dispatch_builder);
// This dispatches all the systems in parallel
// This dispatches all the systems in parallel.
dispatch_builder.build().dispatch(&self.ecs.res);
self.ecs.maintain();
}
/// Clean up the state after a tick
/// Clean up the state after a tick.
pub fn cleanup(&mut self) {
// Clean up data structures from the last tick
// Clean up data structures from the last tick.
self.changes.cleanup();
}
}

View File

@ -34,10 +34,10 @@ impl<'a> System<'a> for Sys {
Some(tgt_pos) => {
let tgt_pos = tgt_pos.0 + *offset;
// Jump with target
// Jump with target.
control.jumping = tgt_pos.z > pos.0.z + 1.0;
// Move towards the target
// Move towards the target.
let dist = tgt_pos.distance(pos.0);
control.move_dir = if dist > 5.0 {
Vec2::from(tgt_pos - pos.0).normalized()
@ -50,7 +50,7 @@ impl<'a> System<'a> for Sys {
_ => control.move_dir = Vec2::zero(),
}
// Change offset occasionally
// Change offset occasionally.
if rand::random::<f32>() < 0.003 {
*offset =
Vec2::new(rand::random::<f32>() - 0.5, rand::random::<f32>() - 0.5)

View File

@ -42,8 +42,8 @@ impl<'a> System<'a> for Sys {
&& vel.0.z <= 0.0;
let (gliding, friction) = if on_ground {
// TODO: Don't hard-code this
// Apply physics to the player: acceleration and non-linear decceleration
// TODO: Don't hard-code this.
// Apply physics to the player: acceleration and non-linear deceleration.
vel.0 += Vec2::broadcast(dt.0) * control.move_dir * 200.0;
if control.jumping {
@ -52,12 +52,12 @@ impl<'a> System<'a> for Sys {
(false, 0.15)
} else {
// TODO: Don't hard-code this
// Apply physics to the player: acceleration and non-linear decceleration
// TODO: Don't hard-code this.
// Apply physics to the player: acceleration and non-linear deceleration.
vel.0 += Vec2::broadcast(dt.0) * control.move_dir * 10.0;
if control.gliding && vel.0.z < 0.0 {
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
let anti_grav = 9.81 * 3.95 + vel.0.z.powf(2.0) * 0.2;
vel.0.z +=
dt.0 * anti_grav * Vec2::<f32>::from(vel.0 * 0.15).magnitude().min(1.0);

View File

@ -28,8 +28,8 @@ impl<'a> System<'a> for Sys {
// Movement
pos.0 += vel.0 * dt.0;
// Don't fall into the void
// TODO: This shouldn't be needed when we have proper physics and chunk loading
// Don't fall into the void.
// TODO: This shouldn't be needed when we have proper physics and chunk loading.
if pos.0.z < 0.0 {
pos.0.z = 0.0;
vel.0.z = 0.0;

View File

@ -1,7 +1,7 @@
use crate::ray::{Ray, RayUntil};
use vek::*;
/// A voxel
/// A voxel.
pub trait Vox {
fn empty() -> Self;
fn is_empty(&self) -> bool;
@ -50,7 +50,7 @@ pub trait SizedVol: BaseVol {
#[inline(always)]
fn get_size(&self) -> Vec3<u32>;
/// Iterate through all potential voxel positions in this volume
/// Iterate through all potential voxel positions in this volume.
fn iter_positions(&self) -> VoxPosIter {
VoxPosIter {
pos: Vec3::zero(),
@ -73,7 +73,7 @@ pub trait ReadVol: BaseVol {
}
}
/// A volume that provides the ability to sample (i.e: clone a section of) its voxel data.
/// A volume that provides the ability to sample (i.e., clone a section of) its voxel data.
pub trait SampleVol<I>: BaseVol {
type Sample: BaseVol + ReadVol;
/// Take a sample of the volume by cloning voxels within the provided range.

View File

@ -25,8 +25,8 @@ pub struct Chunk<V: Vox, S: VolSize, M> {
}
impl<V: Vox, S: VolSize, M> Chunk<V, S, M> {
/// Used to transform a voxel position in the volume into its corresponding index in the voxel
// array.
/// Used to transform a voxel position in the volume into its corresponding index
/// in the voxel array.
#[inline(always)]
fn idx_for(pos: Vec3<i32>) -> Option<usize> {
if pos.map(|e| e >= 0).reduce_and()

View File

@ -20,8 +20,8 @@ pub struct Dyna<V: Vox, M> {
}
impl<V: Vox, M> Dyna<V, M> {
/// Used to transform a voxel position in the volume into its corresponding index in the voxel
// array.
/// Used to transform a voxel position in the volume into its corresponding index
/// in the voxel array.
#[inline(always)]
fn idx_for(sz: Vec3<u32>, pos: Vec3<i32>) -> Option<usize> {
if pos.map(|e| e >= 0).reduce_and() && pos.map2(sz, |e, lim| e < lim as i32).reduce_and() {

View File

View File

@ -15,7 +15,7 @@ fn main() {
let mut clock = Clock::new();
// Create server
let mut server = Server::new().expect("Failed to create server instance");
let mut server = Server::new().expect("Failed to create server instance!");
loop {
let events = server
@ -30,10 +30,10 @@ fn main() {
}
}
// Clean up the server after a tick
// Clean up the server after a tick.
server.cleanup();
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / TPS));
}
}

View File

@ -1,4 +1,4 @@
//! # Implementing new commands
//! # Implementing new commands.
//! To implement a new command, add an instance of `ChatCommand` to `CHAT_COMMANDS`
//! and provide a handler function.
@ -9,26 +9,26 @@ use vek::*;
use lazy_static::lazy_static;
use scan_fmt::scan_fmt;
/// Struct representing a command that a user can run from server chat
/// Struct representing a command that a user can run from server chat.
pub struct ChatCommand {
/// The keyword used to invoke the command, omitting the leading '/'
/// The keyword used to invoke the command, omitting the leading '/'.
pub keyword: &'static str,
/// A format string for parsing arguments
/// A format string for parsing arguments.
arg_fmt: &'static str,
/// message to explain how the command is used
/// A message that explains how the command is used.
help_string: &'static str,
/// Handler function called when the command is executed
/// Handler function called when the command is executed.
/// # Arguments
/// * `&mut Server` - the `Server` instance executing the command
/// * `EcsEntity` - an `Entity` corresponding to the player that invoked the command
/// * `String` - a `String` containing the part of the command after the keyword
/// * `&ChatCommand` - the command to execute with the above arguments
/// Handler functions must parse arguments from the the given `String` (`scan_fmt!` is included for this purpose)
/// * `&mut Server` - the `Server` instance executing the command.
/// * `EcsEntity` - an `Entity` corresponding to the player that invoked the command.
/// * `String` - a `String` containing the part of the command after the keyword.
/// * `&ChatCommand` - the command to execute with the above arguments.
/// Handler functions must parse arguments from the the given `String` (`scan_fmt!` is included for this purpose).
handler: fn(&mut Server, EcsEntity, String, &ChatCommand),
}
impl ChatCommand {
/// Creates a new chat command
/// Creates a new chat command.
pub fn new(
keyword: &'static str,
arg_fmt: &'static str,
@ -42,14 +42,14 @@ impl ChatCommand {
handler,
}
}
/// Calls the contained handler function, passing `&self` as the last argument
/// Calls the contained handler function, passing `&self` as the last argument.
pub fn execute(&self, server: &mut Server, entity: EcsEntity, args: String) {
(self.handler)(server, entity, args, self);
}
}
lazy_static! {
/// Static list of chat commands available to the server
/// Static list of chat commands available to the server.
pub static ref CHAT_COMMANDS: Vec<ChatCommand> = vec![
ChatCommand::new(
"jump",
@ -81,7 +81,8 @@ lazy_static! {
"/pet : Spawn a test pet NPC",
handle_pet
),
ChatCommand::new("help", "", "/help: Display this message", handle_help)
ChatCommand::new(
"help", "", "/help: Display this message", handle_help)
];
}
@ -104,7 +105,7 @@ fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
}
None => server.clients.notify(
entity,
ServerMsg::Chat(String::from("Command 'jump' invalid in current state")),
ServerMsg::Chat(String::from("Command 'jump' invalid in current state.")),
),
}
}
@ -165,7 +166,7 @@ fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &Chat
}
None => server.clients.notify(
entity,
ServerMsg::Chat(format!("Unable to teleport to player '{}'", alias)),
ServerMsg::Chat(format!("Unable to teleport to player '{}'!", alias)),
),
},
None => {

View File

@ -1,5 +1,5 @@
pub struct Input {
// TODO: Use this type to manage server input
// TODO: Use this type to manage server input.
}
impl Default for Input {

View File

@ -56,7 +56,7 @@ impl Server {
Self::bind(SocketAddr::from(([0; 4], 59003)))
}
/// Create a new server bound to the given socket
/// Create a new server bound to the given socket.
#[allow(dead_code)]
pub fn bind<A: Into<SocketAddr>>(addrs: A) -> Result<Self, Error> {
let (chunk_tx, chunk_rx) = mpsc::channel();
@ -114,7 +114,7 @@ impl Server {
&mut self.world
}
/// Build a non-player character
/// Build a non-player character.
#[allow(dead_code)]
pub fn create_npc(&mut self, name: String, body: comp::Body) -> EcsEntityBuilder {
self.state
@ -140,18 +140,18 @@ impl Server {
state.write_component(entity, comp::phys::Pos(Vec3::new(0.0, 0.0, 64.0)));
state.write_component(entity, comp::phys::Vel(Vec3::zero()));
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
// Make sure everything is accepted
// Make sure everything is accepted.
state.write_component(entity, comp::phys::ForceUpdate);
// Set initial animation
// Set initial animation.
state.write_component(entity, comp::AnimationHistory::new(comp::Animation::Idle));
// Tell the client his request was successful
// Tell the client its request was successful.
client.notify(ServerMsg::StateAnswer(Ok(ClientState::Character)));
client.client_state = ClientState::Character;
}
/// Execute a single server tick, handle input and update the game state by the given duration
/// Execute a single server tick, handle input and update the game state by the given duration.
#[allow(dead_code)]
pub fn tick(&mut self, input: Input, dt: Duration) -> Result<Vec<Event>, Error> {
// This tick function is the centre of the Veloren universe. Most server-side things are
@ -168,27 +168,27 @@ impl Server {
// 6) Send relevant state updates to all clients
// 7) Finish the tick, passing control of the main thread back to the frontend
// Build up a list of events for this frame, to be passed to the frontend
// Build up a list of events for this frame, to be passed to the frontend.
let mut frontend_events = Vec::new();
// If networking has problems, handle them
// If networking has problems, handle them.
if let Some(err) = self.postoffice.error() {
return Err(err.into());
}
// Handle new client connections (step 2)
// Handle new client connections (step 2).
frontend_events.append(&mut self.handle_new_connections()?);
// Handle new messages from clients
frontend_events.append(&mut self.handle_new_messages()?);
// Tick the client's LocalState (step 3)
// Tick the client's LocalState (step 3).
self.state.tick(dt);
// Fetch any generated `TerrainChunk`s and insert them into the terrain
// Also, send the chunk data to anybody that is close by
// Fetch any generated `TerrainChunk`s and insert them into the terrain.
// Also, send the chunk data to anybody that is close by.
if let Ok((key, chunk)) = self.chunk_rx.try_recv() {
// Send the chunk to all nearby players
// Send the chunk to all nearby players.
for (entity, player, pos) in (
&self.state.ecs().entities(),
&self.state.ecs().read_storage::<comp::Player>(),
@ -216,12 +216,12 @@ impl Server {
self.pending_chunks.remove(&key);
}
// Remove chunks that are too far from players
// Remove chunks that are too far from players.
let mut chunks_to_remove = Vec::new();
self.state.terrain().iter().for_each(|(key, _)| {
let mut min_dist = i32::MAX;
// For each player with a position, calculate the distance
// For each player with a position, calculate the distance.
for (_, pos) in (
&self.state.ecs().read_storage::<comp::Player>(),
&self.state.ecs().read_storage::<comp::phys::Pos>(),
@ -243,21 +243,21 @@ impl Server {
self.state.remove_chunk(key);
}
// Synchronise clients with the new state of the world
// Synchronise clients with the new state of the world.
self.sync_clients();
// Finish the tick, pass control back to the frontend (step 6)
// Finish the tick, pass control back to the frontend (step 6).
Ok(frontend_events)
}
/// Clean up the server after a tick
/// Clean up the server after a tick.
#[allow(dead_code)]
pub fn cleanup(&mut self) {
// Cleanup the local state
self.state.cleanup();
}
/// Handle new client connections
/// Handle new client connections.
fn handle_new_connections(&mut self) -> Result<Vec<Event>, Error> {
let mut frontend_events = Vec::new();
@ -269,11 +269,10 @@ impl Server {
last_ping: self.state.get_time(),
};
// Return the state of the current world
// (All components Sphynx tracks)
// Return the state of the current world (all of the components that Sphynx tracks).
client.notify(ServerMsg::InitialSync {
ecs_state: self.state.ecs().gen_state_package(),
entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail
entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail.
});
self.clients.add(entity, client);
@ -284,7 +283,7 @@ impl Server {
Ok(frontend_events)
}
/// Handle new client messages
/// Handle new client messages.
fn handle_new_messages(&mut self) -> Result<Vec<Event>, Error> {
let mut frontend_events = Vec::new();
@ -297,17 +296,17 @@ impl Server {
let mut disconnect = false;
let new_msgs = client.postbox.new_messages();
// Update client ping
// Update client ping.
if new_msgs.len() > 0 {
client.last_ping = state.get_time();
// Process incoming messages
// Process incoming messages.
for msg in new_msgs {
match msg {
ClientMsg::RequestState(requested_state) => match requested_state {
ClientState::Connected => disconnect = true, // Default state
ClientState::Registered => match client.client_state {
// Use ClientMsg::Register instead
// Use ClientMsg::Register instead.
ClientState::Connected => {
client.error_state(RequestStateError::WrongMessage)
}
@ -319,7 +318,7 @@ impl Server {
}
},
ClientState::Spectator => match requested_state {
// Become Registered first
// Become Registered first.
ClientState::Connected => {
client.error_state(RequestStateError::Impossible)
}
@ -330,7 +329,7 @@ impl Server {
client.allow_state(ClientState::Spectator)
}
},
// Use ClientMsg::Character instead
// Use ClientMsg::Character instead.
ClientState::Character => {
client.error_state(RequestStateError::WrongMessage)
}
@ -339,11 +338,11 @@ impl Server {
ClientState::Connected => {
Self::initialize_player(state, entity, client, player)
}
// Use RequestState instead (No need to send `player` again)
// Use RequestState instead (No need to send `player` again).
_ => client.error_state(RequestStateError::Impossible),
},
ClientMsg::Character { name, body } => match client.client_state {
// Become Registered first
// Become Registered first.
ClientState::Connected => {
client.error_state(RequestStateError::Impossible)
}
@ -367,7 +366,7 @@ impl Server {
ClientState::Character => {
state.write_component(entity, animation_history)
}
// Only characters can send animations
// Only characters can send animations.
_ => client.error_state(RequestStateError::Impossible),
}
}
@ -377,7 +376,7 @@ impl Server {
state.write_component(entity, vel);
state.write_component(entity, dir);
}
// Only characters send their position
// Only characters can send positions.
_ => client.error_state(RequestStateError::Impossible),
},
ClientMsg::TerrainChunkRequest { key } => match client.client_state {
@ -396,7 +395,7 @@ impl Server {
}
}
},
// Always possible
// Always possible.
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
ClientMsg::Pong => {}
ClientMsg::Disconnect => disconnect = true,
@ -408,7 +407,7 @@ impl Server {
{
disconnect = true;
} else if state.get_time() - client.last_ping > CLIENT_TIMEOUT * 0.5 {
// Try pinging the client if the timeout is nearing
// Try pinging the client if the timeout is nearing.
client.postbox.send_message(ServerMsg::Ping);
}
@ -421,9 +420,9 @@ impl Server {
}
});
// Handle new chat messages
// Handle new chat messages.
for (entity, msg) in new_chat_msgs {
// Handle chat commands
// Handle chat commands.
if msg.starts_with("/") && msg.len() > 1 {
let argv = String::from(&msg[1..]);
self.process_chat_cmd(entity, argv);
@ -439,14 +438,14 @@ impl Server {
}
}
// Handle client disconnects
// Handle client disconnects.
for entity in disconnected_clients {
self.state.ecs_mut().delete_entity_synced(entity);
frontend_events.push(Event::ClientDisconnected { entity });
}
// Generate requested chunks
// Generate requested chunks.
for key in requested_chunks {
self.generate_chunk(key);
}
@ -454,17 +453,17 @@ impl Server {
Ok(frontend_events)
}
/// Initialize a new client states with important information
/// Initialize a new client states with important information.
fn initialize_player(
state: &mut State,
entity: specs::Entity,
client: &mut Client,
player: comp::Player,
) {
// Save player metadata (for example the username)
// Save player metadata (for example the username).
state.write_component(entity, player);
// Sync logical information other players have authority over, not the server
// 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>(),
@ -479,17 +478,17 @@ impl Server {
});
}
// Tell the client his request was successful
// Tell the client its request was successful.
client.allow_state(ClientState::Registered);
}
/// Sync client states with the most up to date information
/// Sync client states with the most up to date information.
fn sync_clients(&mut self) {
// Sync 'logical' state using Sphynx
// Sync 'logical' state using Sphynx.
self.clients
.notify_registered(ServerMsg::EcsSync(self.state.ecs_mut().next_sync_package()));
// Sync 'physical' state
// Sync 'physical' state.
for (entity, &uid, &pos, &vel, &dir, force_update) in (
&self.state.ecs().entities(),
&self.state.ecs().read_storage::<Uid>(),
@ -516,7 +515,7 @@ impl Server {
}
}
// Sync animation states
// Sync animation states.
for (entity, &uid, &animation_history) in (
&self.state.ecs().entities(),
&self.state.ecs().read_storage::<Uid>(),
@ -524,7 +523,7 @@ impl Server {
)
.join()
{
// Check if we need to sync
// Check if we need to sync.
if Some(animation_history.current) == animation_history.last {
continue;
}
@ -538,7 +537,7 @@ impl Server {
);
}
// Update animation last/current state
// Update animation last/current state.
for (entity, mut animation_history) in (
&self.state.ecs().entities(),
&mut self.state.ecs().write_storage::<comp::AnimationHistory>(),
@ -548,7 +547,7 @@ impl Server {
animation_history.last = Some(animation_history.current);
}
// Remove all force flags
// Remove all force flags.
self.state
.ecs_mut()
.write_storage::<comp::phys::ForceUpdate>()
@ -564,18 +563,18 @@ impl Server {
}
fn process_chat_cmd(&mut self, entity: EcsEntity, cmd: String) {
// separate string into keyword and arguments
// Separate string into keyword and arguments.
let sep = cmd.find(' ');
let (kwd, args) = match sep {
Some(i) => (cmd[..i].to_string(), cmd[(i + 1)..].to_string()),
None => (cmd, "".to_string()),
};
// find command object and run its handler
// Find the command object and run its handler.
let action_opt = CHAT_COMMANDS.iter().find(|x| x.keyword == kwd);
match action_opt {
Some(action) => action.execute(self, entity, args),
// unknown command
// Unknown command
None => {
self.clients.notify(
entity,

View File

@ -6,7 +6,6 @@ use vek::*;
// Local
use super::{super::Animation, CharacterSkeleton, SCALE};
//
pub struct GlidingAnimation;
@ -21,19 +20,19 @@ impl Animation for GlidingAnimation {
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let waveslow = (anim_time as f32 * 7.0).sin();
let wavecos_slow = (anim_time as f32 * 7.0).cos();
let arcwave = (1.0f32.ln_1p() - 1.5).abs();
let wavetest = (wave.cbrt());
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 7.0).sin();
let wave_slow_cos = (anim_time as f32 * 7.0).cos();
let arc_wave = (1.0f32.ln_1p() - 1.5).abs();
let wave_test = (wave.cbrt());
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_stop = (anim_time as f32 * 1.5).min(PI / 2.0).sin();
let wave_stopalt = (anim_time as f32 * 5.0).min(PI / 2.0).sin();
let waveveryslow = (anim_time as f32 * 3.0).sin();
let waveveryslowalt = (anim_time as f32 * 2.5).sin();
let waveveryslowcos = (anim_time as f32 * 3.0).cos();
let wave_stop_alt = (anim_time as f32 * 5.0).min(PI / 2.0).sin();
let wave_very_slow = (anim_time as f32 * 3.0).sin();
let wave_very_slow_alt = (anim_time as f32 * 2.5).sin();
let wave_very_slow_cos = (anim_time as f32 * 3.0).cos();
let wave_slowtest = (anim_time as f32).min(PI / 2.0).sin();
let wave_slow_test = (anim_time as f32).min(PI / 2.0).sin();
let head_look = Vec2::new(
((global_time + anim_time) as f32 / 4.0)
@ -48,38 +47,48 @@ impl Animation for GlidingAnimation {
* 0.25,
);
next.head.offset = Vec3::new(5.5, 2.0, 12.0);
next.head.ori = Quaternion::rotation_x(0.35 - waveveryslow * 0.10 + head_look.y)
* Quaternion::rotation_z(head_look.x + waveveryslowcos * 0.15);
next.head.ori = Quaternion::rotation_x(0.35 - wave_very_slow * 0.10 + head_look.y)
* Quaternion::rotation_z(head_look.x + wave_very_slow_cos * 0.15);
next.head.scale = Vec3::one();
next.chest.offset = Vec3::new(5.5, 0.0, 8.0);
next.chest.ori = Quaternion::rotation_z(waveveryslowcos * 0.15);
next.chest.ori = Quaternion::rotation_z(wave_very_slow_cos * 0.15);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(5.5, 0.0, 6.0);
next.belt.ori = Quaternion::rotation_z(waveveryslowcos * 0.20);
next.belt.ori = Quaternion::rotation_z(wave_very_slow_cos * 0.20);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(5.5, 0.0, 3.0);
next.shorts.ori = Quaternion::rotation_z(waveveryslowcos * 0.25);
next.shorts.ori = Quaternion::rotation_z(wave_very_slow_cos * 0.25);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(-8.0, -10.0 + waveveryslow * 2.5, 18.5 + waveveryslow * 1.0);
next.l_hand.ori = Quaternion::rotation_x(0.9 - waveveryslow * 0.10);
next.l_hand.offset = Vec3::new(
-8.0,
-10.0 + wave_very_slow * 2.5,
18.5 + wave_very_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(0.9 - wave_very_slow * 0.10);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(11.0, -10.0 + waveveryslow * 2.5, 18.5 + waveveryslow * 1.0);
next.r_hand.ori = Quaternion::rotation_x(0.9 - waveveryslow * 0.10);
next.r_hand.offset = Vec3::new(
11.0,
-10.0 + wave_very_slow * 2.5,
18.5 + wave_very_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(0.9 - wave_very_slow * 0.10);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.4, 1.0, 8.0);
next.l_foot.ori =
Quaternion::rotation_x(wave_stop * -0.7 - wavecos_slow * -0.21 + waveveryslow * 0.19);
next.l_foot.ori = Quaternion::rotation_x(
wave_stop * -0.7 - wave_slow_cos * -0.21 + wave_very_slow * 0.19,
);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 1.0, 8.0);
next.r_foot.ori =
Quaternion::rotation_x(wave_stop * -0.8 + waveslow * -0.25 + waveveryslowalt * 0.13);
next.r_foot.ori = Quaternion::rotation_x(
wave_stop * -0.8 + wave_slow * -0.25 + wave_very_slow_alt * 0.13,
);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(-5.0, -6.0, 19.0);
@ -95,11 +104,11 @@ impl Animation for GlidingAnimation {
next.r_shoulder.scale = Vec3::one();
next.torso.offset = Vec3::new(-0.5, -0.2, 0.0);
next.torso.ori = Quaternion::rotation_x(-0.8 + waveveryslow * 0.10);
next.torso.ori = Quaternion::rotation_x(-0.8 + wave_very_slow * 0.10);
next.torso.scale = Vec3::one() / 11.0;
next.draw.offset = Vec3::new(13.5, 3.0, -1.0);
next.draw.ori = Quaternion::rotation_y(waveveryslowcos * 0.05);
next.draw.ori = Quaternion::rotation_y(wave_very_slow_cos * 0.05);
next.draw.scale = Vec3::one();
next

View File

@ -24,11 +24,11 @@ impl Animation for IdleAnimation {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 12.0).cos();
let wave_cos = (anim_time as f32 * 12.0).cos();
let wave_slow = (anim_time as f32 * 6.0 + PI).sin();
let wavecos_slow = (anim_time as f32 * 6.0 + PI).cos();
let waveultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let waveultracos_slow = (anim_time as f32 * 1.0 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 6.0 + PI).cos();
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
let head_look = Vec2::new(
@ -43,37 +43,37 @@ impl Animation for IdleAnimation {
.sin()
* 0.25,
);
next.head.offset = Vec3::new(5.5, 2.0, 11.0 + waveultra_slow * 0.3);
next.head.offset = Vec3::new(5.5, 2.0, 11.0 + wave_ultra_slow * 0.3);
next.head.ori = Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x(head_look.y);
next.head.scale = Vec3::one();
next.chest.offset = Vec3::new(5.5, 0.0, 7.0 + waveultra_slow * 0.3);
next.chest.offset = Vec3::new(5.5, 0.0, 7.0 + wave_ultra_slow * 0.3);
next.chest.ori = Quaternion::rotation_x(0.0);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(5.5, 0.0, 5.0 + waveultra_slow * 0.3);
next.belt.offset = Vec3::new(5.5, 0.0, 5.0 + wave_ultra_slow * 0.3);
next.belt.ori = Quaternion::rotation_x(0.0);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(5.5, 0.0, 2.0 + waveultra_slow * 0.3);
next.shorts.offset = Vec3::new(5.5, 0.0, 2.0 + wave_ultra_slow * 0.3);
next.shorts.ori = Quaternion::rotation_x(0.0);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(
-6.0,
-2.0 + waveultracos_slow * 0.15,
11.5 + waveultra_slow * 0.5,
-2.0 + wave_ultra_slow_cos * 0.15,
11.5 + wave_ultra_slow * 0.5,
);
next.l_hand.ori = Quaternion::rotation_x(0.0 + waveultra_slow * 0.06);
next.l_hand.ori = Quaternion::rotation_x(0.0 + wave_ultra_slow * 0.06);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(
9.0,
-2.0 + waveultracos_slow * 0.15,
11.5 + waveultra_slow * 0.5,
-2.0 + wave_ultra_slow_cos * 0.15,
11.5 + wave_ultra_slow * 0.5,
);
next.r_hand.ori = Quaternion::rotation_x(0.0 + waveultra_slow * 0.06);
next.r_hand.ori = Quaternion::rotation_x(0.0 + wave_ultra_slow * 0.06);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.3, -0.1, 8.0);

View File

@ -6,7 +6,6 @@ use vek::*;
// Local
use super::{super::Animation, CharacterSkeleton, SCALE};
//
pub struct JumpAnimation;
@ -21,16 +20,16 @@ impl Animation for JumpAnimation {
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let waveslow = (anim_time as f32 * 7.0).sin();
let arcwave = (1.0f32.ln_1p() - 1.5).abs();
let wavetest = (wave.cbrt());
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 7.0).sin();
let arc_wave = (1.0f32.ln_1p() - 1.5).abs();
let wave_test = (wave.cbrt());
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_stop = (anim_time as f32 * 4.5).min(PI / 2.0).sin();
let wave_stopalt = (anim_time as f32 * 5.0).min(PI / 2.0).sin();
let wave_stop_alt = (anim_time as f32 * 5.0).min(PI / 2.0).sin();
let wave_slowtest = (anim_time as f32).min(PI / 2.0).sin();
let wavecos_slow = (anim_time as f32 * 8.0 + PI).cos();
let wave_slow_test = (anim_time as f32).min(PI / 2.0).sin();
let wave_slow_cos = (anim_time as f32 * 8.0 + PI).cos();
next.head.offset = Vec3::new(5.5, 2.0, 12.0);
next.head.ori = Quaternion::rotation_x(0.25);
@ -49,19 +48,19 @@ impl Animation for JumpAnimation {
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(-6.0, 0.0, 12.0);
next.l_hand.ori = Quaternion::rotation_x(wave_stopalt * 1.2 - waveslow * 0.15);
next.l_hand.ori = Quaternion::rotation_x(wave_stop_alt * 1.2 - wave_slow * 0.15);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(9.0, 0.0, 12.0);
next.r_hand.ori = Quaternion::rotation_x(wave_stopalt * -1.2 + waveslow * 0.15);
next.r_hand.ori = Quaternion::rotation_x(wave_stop_alt * -1.2 + wave_slow * 0.15);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.4, 1.0, 6.0);
next.l_foot.ori = Quaternion::rotation_x(wave_stop * -1.2 - waveslow * 0.2);
next.l_foot.ori = Quaternion::rotation_x(wave_stop * -1.2 - wave_slow * 0.2);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, -1.0, 6.0);
next.r_foot.ori = Quaternion::rotation_x(wave_stop * 1.2 + waveslow * 0.2);
next.r_foot.ori = Quaternion::rotation_x(wave_stop * 1.2 + wave_slow * 0.2);
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(-5.0, -6.0, 19.0);

View File

@ -21,35 +21,35 @@ impl Animation for RunAnimation {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wavetest = (wave.cbrt());
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_test = (wave.cbrt());
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 7.0 + PI).sin();
let wavecos_slow = (anim_time as f32 * 8.0 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 8.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
next.head.offset = Vec3::new(5.5, 2.0, 11.0 + wavecos * 1.3);
next.head.offset = Vec3::new(5.5, 2.0, 11.0 + wave_cos * 1.3);
next.head.ori = Quaternion::rotation_x(0.15);
next.head.scale = Vec3::one();
next.chest.offset = Vec3::new(5.5, 0.0, 7.0 + wavecos * 1.1);
next.chest.offset = Vec3::new(5.5, 0.0, 7.0 + wave_cos * 1.1);
next.chest.ori = Quaternion::rotation_z(wave * 0.1);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(5.5, 0.0, 5.0 + wavecos * 1.1);
next.belt.offset = Vec3::new(5.5, 0.0, 5.0 + wave_cos * 1.1);
next.belt.ori = Quaternion::rotation_z(wave * 0.25);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(5.5, 0.0, 2.0 + wavecos * 1.1);
next.shorts.offset = Vec3::new(5.5, 0.0, 2.0 + wave_cos * 1.1);
next.shorts.ori = Quaternion::rotation_z(wave * 0.6);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(-6.0, 0.0 + wavecos * 2.5, 11.0 - wave * 1.5);
next.l_hand.ori = Quaternion::rotation_x(wavecos * 0.9);
next.l_hand.offset = Vec3::new(-6.0, 0.0 + wave_cos * 2.5, 11.0 - wave * 1.5);
next.l_hand.ori = Quaternion::rotation_x(wave_cos * 0.9);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(9.0, 0.0 - wavecos * 2.5, 11.0 + wave * 1.5);
next.r_hand.ori = Quaternion::rotation_x(wavecos * -0.9);
next.r_hand.offset = Vec3::new(9.0, 0.0 - wave_cos * 2.5, 11.0 + wave * 1.5);
next.r_hand.ori = Quaternion::rotation_x(wave_cos * -0.9);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.4, 0.0 + wave * 1.0, 6.0);
@ -73,7 +73,7 @@ impl Animation for RunAnimation {
next.r_shoulder.scale = Vec3::one();
next.torso.offset = Vec3::new(-0.5, -0.2, 0.4);
next.torso.ori = Quaternion::rotation_x(-velocity * 0.05 - wavecos * 0.1);
next.torso.ori = Quaternion::rotation_x(-velocity * 0.05 - wave_cos * 0.1);
next.torso.scale = Vec3::one() / 11.0;
next.draw.offset = Vec3::new(13.5, 0.0, 0.0);

View File

@ -28,9 +28,9 @@ impl Bone {
* Mat4::from(self.ori)
}
/// Change the current bone to be more like `target`
/// Change the current bone to be more like `target`.
fn interpolate(&mut self, target: &Bone) {
// TODO: Make configurable
// TODO: Make configurable.
let factor = 0.3;
self.offset += (target.offset - self.offset) * factor;
self.ori = vek::ops::Slerp::slerp(self.ori, target.ori, factor);
@ -41,7 +41,7 @@ impl Bone {
pub trait Skeleton: Send + Sync + 'static {
fn compute_matrices(&self) -> [FigureBoneData; 16];
/// Change the current skeleton to be more like `target`
/// Change the current skeleton to be more like `target`.
fn interpolate(&mut self, target: &Self);
}
@ -49,7 +49,7 @@ pub trait Animation {
type Skeleton;
type Dependency;
/// Returns a new skeleton that is generated by the animation
/// Returns a new skeleton that is generated by the animation.
fn update_skeleton(
skeleton: &Self::Skeleton,
dependency: Self::Dependency,

View File

@ -21,16 +21,16 @@ impl Animation for IdleAnimation {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wavetest = (wave.cbrt());
let waveultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let waveultracos_slow = (anim_time as f32 * 1.0 + PI).cos();
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_test = (wave.cbrt());
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 3.5 + PI).sin();
let wavecos_slow = (anim_time as f32 * 3.5 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
let pighead_look = Vec2::new(
let pig_head_look = Vec2::new(
((global_time + anim_time) as f32 / 8.0)
.floor()
.mul(7331.0)
@ -43,30 +43,30 @@ impl Animation for IdleAnimation {
* 0.25,
);
next.pighead.offset = Vec3::new(0.0, -2.0, -1.5 + wave * 0.2) / 11.0;
next.pighead.ori = Quaternion::rotation_z(pighead_look.x)
* Quaternion::rotation_x(pighead_look.y + wavecos_slow * 0.03);
next.pighead.scale = Vec3::one() / 10.5;
next.pig_head.offset = Vec3::new(0.0, -2.0, -1.5 + wave * 0.2) / 11.0;
next.pig_head.ori = Quaternion::rotation_z(pig_head_look.x)
* Quaternion::rotation_x(pig_head_look.y + wave_slow_cos * 0.03);
next.pig_head.scale = Vec3::one() / 10.5;
next.pigchest.offset = Vec3::new(wave_slow * 0.05, -9.0, 1.5 + wavecos_slow * 0.4) / 11.0;
next.pigchest.ori = Quaternion::rotation_y(wave_slow * 0.05);
next.pigchest.scale = Vec3::one() / 11.0;
next.pig_chest.offset = Vec3::new(wave_slow * 0.05, -9.0, 1.5 + wave_slow_cos * 0.4) / 11.0;
next.pig_chest.ori = Quaternion::rotation_y(wave_slow * 0.05);
next.pig_chest.scale = Vec3::one() / 11.0;
next.piglf_leg.offset = Vec3::new(-4.5, 2.0, 1.5) / 11.0;
next.piglf_leg.ori = Quaternion::rotation_x(wave_slow * 0.08);
next.piglf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lf.offset = Vec3::new(-4.5, 2.0, 1.5) / 11.0;
next.pig_leg_lf.ori = Quaternion::rotation_x(wave_slow * 0.08);
next.pig_leg_lf.scale = Vec3::one() / 11.0;
next.pigrf_leg.offset = Vec3::new(2.5, 2.0, 1.5) / 11.0;
next.pigrf_leg.ori = Quaternion::rotation_x(wavecos_slow * 0.08);
next.pigrf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rf.offset = Vec3::new(2.5, 2.0, 1.5) / 11.0;
next.pig_leg_rf.ori = Quaternion::rotation_x(wave_slow_cos * 0.08);
next.pig_leg_rf.scale = Vec3::one() / 11.0;
next.piglb_leg.offset = Vec3::new(-4.5, -3.0, 1.5) / 11.0;
next.piglb_leg.ori = Quaternion::rotation_x(wavecos_slow * 0.08);
next.piglb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lb.offset = Vec3::new(-4.5, -3.0, 1.5) / 11.0;
next.pig_leg_lb.ori = Quaternion::rotation_x(wave_slow_cos * 0.08);
next.pig_leg_lb.scale = Vec3::one() / 11.0;
next.pigrb_leg.offset = Vec3::new(2.5, -3.0, 1.5) / 11.0;
next.pigrb_leg.ori = Quaternion::rotation_x(wave_slow * 0.08);
next.pigrb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rb.offset = Vec3::new(2.5, -3.0, 1.5) / 11.0;
next.pig_leg_rb.ori = Quaternion::rotation_x(wave_slow * 0.08);
next.pig_leg_rb.scale = Vec3::one() / 11.0;
next
}

View File

@ -21,37 +21,37 @@ impl Animation for JumpAnimation {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wavetest = (wave.cbrt());
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_test = (wave.cbrt());
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 7.0 + PI).sin();
let wavecos_slow = (anim_time as f32 * 8.0 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 8.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
let wave_stop = (anim_time as f32 * 4.5).min(PI / 2.0).sin();
next.pighead.offset = Vec3::new(0.0, 0.0, -1.5) / 11.0;
next.pighead.ori = Quaternion::rotation_x(wave_stop * 0.4);
next.pighead.scale = Vec3::one() / 10.5;
next.pig_head.offset = Vec3::new(0.0, 0.0, -1.5) / 11.0;
next.pig_head.ori = Quaternion::rotation_x(wave_stop * 0.4);
next.pig_head.scale = Vec3::one() / 10.5;
next.pigchest.offset = Vec3::new(0.0, -9.0, 1.5) / 11.0;
next.pigchest.ori = Quaternion::rotation_x(0.0);
next.pigchest.scale = Vec3::one() / 11.0;
next.pig_chest.offset = Vec3::new(0.0, -9.0, 1.5) / 11.0;
next.pig_chest.ori = Quaternion::rotation_x(0.0);
next.pig_chest.scale = Vec3::one() / 11.0;
next.piglf_leg.offset = Vec3::new(-4.5, 3.0, 1.5) / 11.0;
next.piglf_leg.ori = Quaternion::rotation_x(wave_stop * 0.6 - wave_slow * 0.3);
next.piglf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lf.offset = Vec3::new(-4.5, 3.0, 1.5) / 11.0;
next.pig_leg_lf.ori = Quaternion::rotation_x(wave_stop * 0.6 - wave_slow * 0.3);
next.pig_leg_lf.scale = Vec3::one() / 11.0;
next.pigrf_leg.offset = Vec3::new(2.5, 3.0, 1.5) / 11.0;
next.pigrf_leg.ori = Quaternion::rotation_x(wave_stop * 0.6 - wave_slow * 0.3);
next.pigrf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rf.offset = Vec3::new(2.5, 3.0, 1.5) / 11.0;
next.pig_leg_rf.ori = Quaternion::rotation_x(wave_stop * 0.6 - wave_slow * 0.3);
next.pig_leg_rf.scale = Vec3::one() / 11.0;
next.piglb_leg.offset = Vec3::new(-4.5, -4.0, 2.0) / 11.0;
next.piglb_leg.ori = Quaternion::rotation_x(wave_stop * -0.6 + wave_slow * 0.3);
next.piglb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lb.offset = Vec3::new(-4.5, -4.0, 2.0) / 11.0;
next.pig_leg_lb.ori = Quaternion::rotation_x(wave_stop * -0.6 + wave_slow * 0.3);
next.pig_leg_lb.scale = Vec3::one() / 11.0;
next.pigrb_leg.offset = Vec3::new(2.5, -4.0, 2.0) / 11.0;
next.pigrb_leg.ori = Quaternion::rotation_x(wave_stop * -0.6 + wave_slow * 0.3);
next.pigrb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rb.offset = Vec3::new(2.5, -4.0, 2.0) / 11.0;
next.pig_leg_rb.ori = Quaternion::rotation_x(wave_stop * -0.6 + wave_slow * 0.3);
next.pig_leg_rb.scale = Vec3::one() / 11.0;
next
}

View File

@ -17,23 +17,23 @@ const SCALE: f32 = 11.0;
#[derive(Clone)]
pub struct QuadrupedSkeleton {
pighead: Bone,
pigchest: Bone,
piglf_leg: Bone,
pigrf_leg: Bone,
piglb_leg: Bone,
pigrb_leg: Bone,
pig_head: Bone,
pig_chest: Bone,
pig_leg_lf: Bone,
pig_leg_rf: Bone,
pig_leg_lb: Bone,
pig_leg_rb: Bone,
}
impl QuadrupedSkeleton {
pub fn new() -> Self {
Self {
pighead: Bone::default(),
pigchest: Bone::default(),
piglf_leg: Bone::default(),
pigrf_leg: Bone::default(),
piglb_leg: Bone::default(),
pigrb_leg: Bone::default(),
pig_head: Bone::default(),
pig_chest: Bone::default(),
pig_leg_lf: Bone::default(),
pig_leg_rf: Bone::default(),
pig_leg_lb: Bone::default(),
pig_leg_rb: Bone::default(),
}
}
}
@ -41,12 +41,12 @@ impl QuadrupedSkeleton {
impl Skeleton for QuadrupedSkeleton {
fn compute_matrices(&self) -> [FigureBoneData; 16] {
[
FigureBoneData::new(self.pighead.compute_base_matrix()),
FigureBoneData::new(self.pigchest.compute_base_matrix()),
FigureBoneData::new(self.piglf_leg.compute_base_matrix()),
FigureBoneData::new(self.pigrf_leg.compute_base_matrix()),
FigureBoneData::new(self.piglb_leg.compute_base_matrix()),
FigureBoneData::new(self.pigrb_leg.compute_base_matrix()),
FigureBoneData::new(self.pig_head.compute_base_matrix()),
FigureBoneData::new(self.pig_chest.compute_base_matrix()),
FigureBoneData::new(self.pig_leg_lf.compute_base_matrix()),
FigureBoneData::new(self.pig_leg_rf.compute_base_matrix()),
FigureBoneData::new(self.pig_leg_lb.compute_base_matrix()),
FigureBoneData::new(self.pig_leg_rb.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
@ -61,11 +61,11 @@ impl Skeleton for QuadrupedSkeleton {
}
fn interpolate(&mut self, target: &Self) {
self.pighead.interpolate(&target.pighead);
self.pigchest.interpolate(&target.pigchest);
self.piglf_leg.interpolate(&target.piglf_leg);
self.pigrf_leg.interpolate(&target.pigrf_leg);
self.piglb_leg.interpolate(&target.piglb_leg);
self.pigrb_leg.interpolate(&target.pigrb_leg);
self.pig_head.interpolate(&target.pig_head);
self.pig_chest.interpolate(&target.pig_chest);
self.pig_leg_lf.interpolate(&target.pig_leg_lf);
self.pig_leg_rf.interpolate(&target.pig_leg_rf);
self.pig_leg_lb.interpolate(&target.pig_leg_lb);
self.pig_leg_rb.interpolate(&target.pig_leg_rb);
}
}

View File

@ -21,43 +21,43 @@ impl Animation for RunAnimation {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 14.0).sin();
let wavequick = (anim_time as f32 * 20.0).sin();
let wavequickcos = (anim_time as f32 * 20.0).cos();
let wavetest = (wave.cbrt());
let fuzzwave = (anim_time as f32 * 12.0).sin();
let wavecos = (anim_time as f32 * 14.0).cos();
let wave_quick = (anim_time as f32 * 20.0).sin();
let wave_quick_cos = (anim_time as f32 * 20.0).cos();
let wave_test = (wave.cbrt());
let fuzz_wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 14.0).cos();
let wave_slow = (anim_time as f32 * 7.0 + PI).sin();
let wavecos_slow = (anim_time as f32 * 8.0 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 8.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
next.pighead.offset = Vec3::new(0.0, 0.0, -1.5 + wave * 1.5) / 11.0;
next.pighead.ori =
Quaternion::rotation_x(0.2 + wave * 0.05) * Quaternion::rotation_y(wavecos * 0.03);
next.pighead.scale = Vec3::one() / 10.5;
next.pig_head.offset = Vec3::new(0.0, 0.0, -1.5 + wave * 1.5) / 11.0;
next.pig_head.ori =
Quaternion::rotation_x(0.2 + wave * 0.05) * Quaternion::rotation_y(wave_cos * 0.03);
next.pig_head.scale = Vec3::one() / 10.5;
next.pigchest.offset = Vec3::new(0.0, -9.0, 1.5 + wavecos * 1.2) / 11.0;
next.pigchest.ori = Quaternion::rotation_x(wave * 0.1);
next.pigchest.scale = Vec3::one() / 11.0;
next.pig_chest.offset = Vec3::new(0.0, -9.0, 1.5 + wave_cos * 1.2) / 11.0;
next.pig_chest.ori = Quaternion::rotation_x(wave * 0.1);
next.pig_chest.scale = Vec3::one() / 11.0;
next.piglf_leg.offset =
Vec3::new(-4.5, 2.0 + wavequick * 0.8, 2.5 + wavequickcos * 1.5) / 11.0;
next.piglf_leg.ori = Quaternion::rotation_x(wavequick * 0.3);
next.piglf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lf.offset =
Vec3::new(-4.5, 2.0 + wave_quick * 0.8, 2.5 + wave_quick_cos * 1.5) / 11.0;
next.pig_leg_lf.ori = Quaternion::rotation_x(wave_quick * 0.3);
next.pig_leg_lf.scale = Vec3::one() / 11.0;
next.pigrf_leg.offset =
Vec3::new(2.5, 2.0 - wavequickcos * 0.8, 2.5 + wavequick * 1.5) / 11.0;
next.pigrf_leg.ori = Quaternion::rotation_x(wavequickcos * -0.3);
next.pigrf_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rf.offset =
Vec3::new(2.5, 2.0 - wave_quick_cos * 0.8, 2.5 + wave_quick * 1.5) / 11.0;
next.pig_leg_rf.ori = Quaternion::rotation_x(wave_quick_cos * -0.3);
next.pig_leg_rf.scale = Vec3::one() / 11.0;
next.piglb_leg.offset =
Vec3::new(-4.5, -3.0 - wavequickcos * 0.8, 2.5 + wavequick * 1.5) / 11.0;
next.piglb_leg.ori = Quaternion::rotation_x(wavequickcos * -0.3);
next.piglb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_lb.offset =
Vec3::new(-4.5, -3.0 - wave_quick_cos * 0.8, 2.5 + wave_quick * 1.5) / 11.0;
next.pig_leg_lb.ori = Quaternion::rotation_x(wave_quick_cos * -0.3);
next.pig_leg_lb.scale = Vec3::one() / 11.0;
next.pigrb_leg.offset =
Vec3::new(2.5, -3.0 + wavequick * 0.8, 2.5 + wavequickcos * 1.5) / 11.0;
next.pigrb_leg.ori = Quaternion::rotation_x(wavequick * 0.3);
next.pigrb_leg.scale = Vec3::one() / 11.0;
next.pig_leg_rb.offset =
Vec3::new(2.5, -3.0 + wave_quick * 0.8, 2.5 + wave_quick_cos * 1.5) / 11.0;
next.pig_leg_rb.ori = Quaternion::rotation_x(wave_quick * 0.3);
next.pig_leg_rb.scale = Vec3::one() / 11.0;
next
}

View File

@ -7,16 +7,16 @@ use client;
// Crate
use crate::render::RenderError;
/// Represents any error that may be triggered by Voxygen
/// Represents any error that may be triggered by Voxygen.
#[derive(Debug)]
pub enum Error {
/// An error relating to the internal client
/// An error relating to the internal client.
ClientError(client::Error),
/// A miscellaneous error relating to a backend dependency
/// A miscellaneous error relating to a backend dependency.
BackendError(Box<any::Any>),
/// An error relating the rendering subsystem
/// An error relating the rendering subsystem.
RenderError(RenderError),
// A miscellaneous error with an unknown or unspecified source
/// A miscellaneous error with an unknown or unspecified source.
Other(failure::Error),
}

View File

@ -150,9 +150,9 @@ impl<'a> Widget for Buttons<'a> {
return Some(Event::ToggleMap);
};
// Other Windows can only be accessed, when Settings are closed.
// Opening Settings will close all other Windows including the Bag.
// Opening the Map won't close the windows displayed before.
// Other Windows can only be accessed when `Settings` is closed.
// Opening `Settings` will close all other Windows, including the `Bag`.
// Opening the `Map` won't close the previously displayed windows.
Image::new(self.imgs.social_button)
.w_h(25.0, 25.0)
.left_from(state.ids.settings_button, 10.0)

View File

@ -104,7 +104,7 @@ impl<'a> Widget for CharacterWindow<'a> {
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
let widget::UpdateArgs { id, state, ui, .. } = args;
// TODO: Read from parameter / character struct
// TODO: Read from parameter/character struct.
let xp_percentage = 0.4;
// Frame
@ -133,7 +133,8 @@ impl<'a> Widget for CharacterWindow<'a> {
}
// Title
Text::new("Character Name") // Add in actual Character Name
// TODO: Use an actual character name.
Text::new("Character Name")
.mid_top_with_margin_on(state.charwindow_frame, 6.0)
.font_id(self.fonts.metamorph)
.font_size(14)
@ -319,7 +320,8 @@ impl<'a> Widget for CharacterWindow<'a> {
.top_left_with_margins_on(state.charwindow_tab_bg, 7.0 * 4.0, 4.0 * 4.0)
.set(state.charwindow_rectangle, ui);
// Tab Button -> Add that back in when we have multiple tabs
// TODO: Add this back in when we have multiple tabs.
// Tab Button ->
// Button::image(self.imgs.charwindow_tab)
//.w_h(65.0, 23.0)
//.top_left_with_margins_on(state.charwindow_tab_bg, -18.0, 1.8)
@ -328,7 +330,8 @@ impl<'a> Widget for CharacterWindow<'a> {
//.label_font_size(14)
//.set(state.charwindow_tab1, ui);
Text::new("1") //Add in actual Character Level
// TODO: Use an actual character level.
Text::new("1")
.mid_top_with_margin_on(state.charwindow_rectangle, 10.0)
.font_id(self.fonts.opensans)
.font_size(30)
@ -352,7 +355,8 @@ impl<'a> Widget for CharacterWindow<'a> {
.set(state.charwindow_tab1_expbar, ui);
// Exp-Text
Text::new("120/170") // Shows the Exp / Exp to reach the next level
// TODO: Shows current Exp over the next threshold Exp.
Text::new("120/170")
.mid_top_with_margin_on(state.charwindow_tab1_expbar, 10.0)
.font_id(self.fonts.opensans)
.font_size(15)
@ -382,6 +386,7 @@ impl<'a> Widget for CharacterWindow<'a> {
.color(TEXT_COLOR)
.set(state.charwindow_tab1_statnames, ui);
// TODO: Shows actual stat points.
Text::new(
"1234\n\
\n\

View File

@ -39,7 +39,8 @@ impl<'a> Chat<'a> {
}
fn scrolled_to_bottom(state: &State, ui: &UiCell) -> bool {
// could be more efficient to cache result and update it when a scroll event has occurred instead of every frame
// Might be more efficient to cache result and update it when a scroll event has occurred
// instead of every frame.
if let Some(scroll) = ui
.widget_graph()
.widget(state.ids.message_box)
@ -84,7 +85,7 @@ impl<'a> Widget for Chat<'a> {
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
let widget::UpdateArgs { id, state, ui, .. } = args;
// Maintain scrolling
// Maintain scrolling.
if !self.new_messages.is_empty() {
state.update(|s| s.messages.extend(self.new_messages.drain(..)));
ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]);
@ -93,8 +94,8 @@ impl<'a> Widget for Chat<'a> {
let keyboard_capturer = ui.global_input().current.widget_capturing_keyboard;
let input_focused = keyboard_capturer == Some(state.ids.input);
// Only show if it has the keyboard captured
// Chat input with rectangle as background
// Only show if it has the keyboard captured.
// Chat input uses a rectangle as its background.
if input_focused {
let text_edit = TextEdit::new(&state.input)
.w(460.0)
@ -139,7 +140,7 @@ impl<'a> Widget for Chat<'a> {
.scroll_kids_vertically()
.set(state.ids.message_box, ui);
while let Some(item) = items.next(ui) {
// This would be easier if conrod used the v-metrics from rusttype
// This would be easier if conrod used the v-metrics from rusttype.
let widget = if item.i < state.messages.len() {
let text = Text::new(&state.messages[item.i])
.font_size(15)
@ -147,15 +148,15 @@ impl<'a> Widget for Chat<'a> {
.w(470.0)
.color(TEXT_COLOR)
.line_spacing(2.0);
// Add space between messages
// Add space between messages.
let y = match text.get_y_dimension(ui) {
Dimension::Absolute(y) => y + 2.0,
_ => 0.0,
};
text.h(y)
} else {
// Spacer at bottom of the last message so that it is not cut off
// Needs to be larger than the space above
// Spacer at bottom of the last message so that it is not cut off.
// Needs to be larger than the space above.
Text::new("")
.font_size(6)
.font_id(self.fonts.opensans)
@ -165,7 +166,7 @@ impl<'a> Widget for Chat<'a> {
}
// Chat Arrow
// Check if already at bottom
// Check if already at bottom.
if !Self::scrolled_to_bottom(state, ui) {
if Button::image(self.imgs.chat_arrow)
.w_h(20.0, 20.0)
@ -179,11 +180,11 @@ impl<'a> Widget for Chat<'a> {
}
}
// If the chat widget is focused return a focus event to pass the focus to the input box
// If the chat widget is focused, return a focus event to pass the focus to the input box.
if keyboard_capturer == Some(id) {
Some(Event::Focus(state.ids.input))
}
// If enter is pressed and the input box is not empty send the current message
// If enter is pressed and the input box is not empty, send the current message.
else if ui
.widget_input(state.ids.input)
.presses()

View File

@ -103,7 +103,7 @@ impl<'a> Widget for EscMenu<'a> {
.set(state.ids.menu_button_2, ui)
.was_clicked()
{
// TODO: Show controls window
// TODO: Show controls window.
};
// Servers
if Button::image(self.imgs.button)
@ -118,7 +118,7 @@ impl<'a> Widget for EscMenu<'a> {
.set(state.ids.menu_button_3, ui)
.was_clicked()
{
// TODO: Show servers window (is needed in-game?)
// TODO: Show servers window (needed in-game?).
};
// Logout
if Button::image(self.imgs.button)

View File

@ -103,7 +103,7 @@ impl<'a> Widget for MiniMap<'a> {
}
// Title
// Make it display the actual location
// TODO: Make it display the actual location.
Text::new("Uncanny Valley")
.mid_top_with_margin_on(state.ids.mmap_frame, 3.0)
.font_size(14)

View File

@ -94,13 +94,13 @@ pub enum Event {
Quit,
}
// TODO: are these the possible layouts we want?
// TODO: maybe replace this with bitflags
// map not here because it currently is displayed over the top of other open windows
// TODO: Are these the possible layouts we want?
// TODO: Maybe replace this with bitflags.
// `map` is not here because it currently is displayed over the top of other open windows.
#[derive(PartialEq)]
pub enum Windows {
Settings, // display settings window
CharacterAnd(Option<SmallWindowType>), // show character window + optionally another
Settings, // Display settings window.
CharacterAnd(Option<SmallWindowType>), // Show character window + optionally another.
Small(SmallWindowType),
None,
}
@ -146,7 +146,7 @@ impl Show {
};
}
fn toggle_charwindow(&mut self) {
fn toggle_char_window(&mut self) {
self.open_windows = match self.open_windows {
Windows::CharacterAnd(small) => match small {
Some(small) => Windows::Small(small),
@ -212,14 +212,14 @@ pub struct Hud {
impl Hud {
pub fn new(window: &mut Window, settings: Settings) -> Self {
let mut ui = Ui::new(window).unwrap();
// TODO: adjust/remove this, right now it is used to demonstrate window scaling functionality
// TODO: Adjust/remove this, right now it is used to demonstrate window scaling functionality.
ui.scaling_mode(ScaleMode::RelativeToWindow([1920.0, 1080.0].into()));
// Generate ids
// Generate ids.
let ids = Ids::new(ui.id_generator());
// Load images
let imgs = Imgs::load(&mut ui).expect("Failed to load images");
// Load fonts
let fonts = Fonts::load(&mut ui).expect("Failed to load fonts");
// Load images.
let imgs = Imgs::load(&mut ui).expect("Failed to load images!");
// Load fonts.
let fonts = Fonts::load(&mut ui).expect("Failed to load fonts!");
Self {
ui,
@ -251,12 +251,12 @@ impl Hud {
let ref mut ui_widgets = self.ui.set_widgets();
let version = env!("CARGO_PKG_VERSION");
// Don't show anything if the UI is toggled off
// Don't show anything if the UI is toggled off.
if !self.show.ui {
return events;
}
// Display debug window
// Display debug window.
if self.show.debug {
// Alpha Version
Text::new(version)
@ -273,7 +273,7 @@ impl Hud {
.set(self.ids.fps_counter, ui_widgets);
}
// Add Bag-Space Button
// Add Bag-Space Button.
if self.show.inventory_test_button {
if Button::image(self.imgs.grid_button)
.w_h(100.0, 100.0)
@ -314,7 +314,7 @@ impl Hud {
};
}
// Bag button and icons near it
// Bag button and nearby icons
match Buttons::new(
&self.show.open_windows,
self.show.map,
@ -326,7 +326,7 @@ impl Hud {
{
Some(buttons::Event::ToggleBag) => self.show.toggle_bag(),
Some(buttons::Event::ToggleSettings) => self.show.toggle_settings(),
Some(buttons::Event::ToggleCharacter) => self.show.toggle_charwindow(),
Some(buttons::Event::ToggleCharacter) => self.show.toggle_char_window(),
Some(buttons::Event::ToggleSmall(small)) => self.show.toggle_small(small),
Some(buttons::Event::ToggleMap) => self.show.toggle_map(),
None => {}
@ -367,8 +367,8 @@ impl Hud {
// Windows
//Char Window will always appear at the left side. Other Windows either appear at the left side,
//or when the Char Window is opened they will appear right from it.
// Char Window will always appear at the left side. Other Windows default to the
// left side, but when the Char Window is opened they will appear to the right of it.
// Settings
if let Windows::Settings = self.show.open_windows {
@ -447,7 +447,7 @@ impl Hud {
self.new_messages.push_back(msg);
}
// Checks if a TextEdit widget has the keyboard captured
// Checks if a TextEdit widget has the keyboard captured.
fn typing(&self) -> bool {
if let Some(id) = self.ui.widget_capturing_keyboard() {
self.ui
@ -515,7 +515,7 @@ impl Hud {
true
}
Key::CharacterWindow => {
self.show.toggle_charwindow();
self.show.toggle_char_window();
true
}
Key::Social => {
@ -547,7 +547,7 @@ impl Hud {
}
_ => false,
};
// Handle cursor grab
// Handle cursor grab.
if !self.force_ungrab {
if cursor_grabbed != self.show.want_grab {
global_state.window.grab_cursor(self.show.want_grab);
@ -571,8 +571,8 @@ impl Hud {
}
}
//Get the text to show in the help window, along with the
//length of the longest line in order to resize the window
// Get the text to show in the help window and use the
// length of the longest line to resize the window.
fn get_help_text(cs: &ControlSettings) -> String {
format!(
"{free_cursor:?} = Free cursor\n\

View File

@ -237,7 +237,7 @@ impl<'a> Widget for SettingsWindow<'a> {
.set(state.ids.debug_button_label, ui);
}
// 2 Gameplay////////////////
// 2 Gameplay
if Button::image(if let SettingsTab::Gameplay = state.settings_tab {
self.imgs.settings_button_pressed
} else {
@ -264,7 +264,7 @@ impl<'a> Widget for SettingsWindow<'a> {
state.update(|s| s.settings_tab = SettingsTab::Gameplay);
}
// 3 Controls/////////////////////
// 3 Controls
if Button::image(if let SettingsTab::Controls = state.settings_tab {
self.imgs.settings_button_pressed
} else {
@ -356,7 +356,7 @@ impl<'a> Widget for SettingsWindow<'a> {
.font_id(self.fonts.opensans)
.font_size(18)
.set(state.ids.controls_text, ui);
// TODO: Replace with buttons that show the actual keybind and allow the user to change it.
// TODO: Replace with buttons that show actual keybinds and allow the user to change them.
Text::new(
"TAB\n\
F1\n\
@ -423,7 +423,7 @@ impl<'a> Widget for SettingsWindow<'a> {
.font_size(18)
.set(state.ids.controls_controls, ui);
}
// 4 Video////////////////////////////////
// 4 Video
if Button::image(if let SettingsTab::Video = state.settings_tab {
self.imgs.settings_button_pressed
} else {
@ -451,7 +451,7 @@ impl<'a> Widget for SettingsWindow<'a> {
state.update(|s| s.settings_tab = SettingsTab::Video);
}
// 5 Sound///////////////////////////////
// 5 Sound
if Button::image(if let SettingsTab::Sound = state.settings_tab {
self.imgs.settings_button_pressed
} else {

View File

@ -73,7 +73,8 @@ impl<'a> Widget for Skillbar<'a> {
let hp_percentage = 1.0;
let mana_percentage = 1.0;
// Crosshair TODO: Only show while aiming with a bow or when casting a spell
// TODO: Only show while aiming with a bow or when casting a spell.
// Crosshair
// Image::new(self.imgs.crosshair)
// .w_h(101.0 * 0.5, 101.0 * 0.5)
// .mid_top_with_margin_on(ui.window, 500.0)
@ -158,14 +159,14 @@ impl<'a> Widget for Skillbar<'a> {
// Level Display
// Insert actual Level here
// TODO: Insert actual Level here.
Text::new("1")
.left_from(state.ids.xp_bar, -15.0)
.font_size(10)
.color(TEXT_COLOR)
.set(state.ids.level_text, ui);
// Insert next Level here
// TODO: Insert next Level here.
Text::new("2")
.right_from(state.ids.xp_bar, -15.0)
.font_size(10)

View File

@ -24,17 +24,17 @@ use log;
use simplelog::{CombinedLogger, Config, TermLogger, WriteLogger};
use std::{fs::File, mem, panic, str::FromStr, thread};
/// The URL of the default public server that Voxygen will connect to
/// 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
/// A type used to store state that is shared between all play states.
pub struct GlobalState {
settings: Settings,
window: Window,
}
impl GlobalState {
/// Called after a change in play state has occured (usually used to reverse any temporary
/// Called after a change in play state has occurred (usually used to reverse any temporary
/// effects a state may have made).
pub fn on_play_state_changed(&mut self) {
self.window.grab_cursor(false);
@ -47,16 +47,16 @@ pub enum Direction {
Backwards,
}
// States can either close (and revert to a previous state), push a new state on top of themselves,
// or switch to a totally different state
/// States can either close (and revert to a previous state), push a new state on top of themselves,
/// or switch to a totally different state.
pub enum PlayStateResult {
/// Pop all play states in reverse order and shut down the program
/// Pop all play states in reverse order and shut down the program.
Shutdown,
/// Close the current play state and pop it from the play state stack
/// Close the current play state and pop it from the play state stack.
Pop,
/// Push a new play state onto the play state stack
/// Push a new play state onto the play state stack.
Push(Box<dyn PlayState>),
/// Switch the current play state with a new play state
/// Switch the current play state with a new play state.
Switch(Box<dyn PlayState>),
}
@ -67,16 +67,16 @@ pub trait PlayState {
/// is closed).
fn play(&mut self, direction: Direction, global_state: &mut GlobalState) -> PlayStateResult;
/// Get a descriptive name for this state type
/// Get a descriptive name for this state type.
fn name(&self) -> &'static str;
}
fn main() {
// Set up the global state
// Set up the global state.
let settings = Settings::load();
let window = Window::new(&settings).expect("Failed to create window");
let window = Window::new(&settings).expect("Failed to create window!");
// Init logging
// Initialize logging.
let term_log_level = std::env::var_os("VOXYGEN_LOG")
.and_then(|env| env.to_str().map(|s| s.to_owned()))
.and_then(|s| log::LevelFilter::from_str(&s).ok())
@ -91,7 +91,7 @@ fn main() {
])
.unwrap();
// Set up panic handler to relay swish panic messages to the user
// Set up panic handler to relay swish panic messages to the user.
let settings_clone = settings.clone();
let default_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
@ -155,7 +155,7 @@ fn main() {
let mut global_state = GlobalState { settings, window };
// Set up the initial play state
// Set up the initial play state.
let mut states: Vec<Box<dyn PlayState>> = vec![Box::new(MainMenuState::new(&mut global_state))];
states
.last()
@ -173,14 +173,14 @@ fn main() {
.last_mut()
.map(|last| last.play(direction, &mut global_state))
{
// Implement state transfer logic
// Implement state transfer logic.
match state_result {
PlayStateResult::Shutdown => {
direction = Direction::Backwards;
log::info!("Shutting down all states...");
while states.last().is_some() {
states.pop().map(|old_state| {
log::info!("Popped state '{}'", old_state.name());
log::info!("Popped state '{}'.", old_state.name());
global_state.on_play_state_changed();
});
}
@ -188,13 +188,13 @@ fn main() {
PlayStateResult::Pop => {
direction = Direction::Backwards;
states.pop().map(|old_state| {
log::info!("Popped state '{}'", old_state.name());
log::info!("Popped state '{}'.", old_state.name());
global_state.on_play_state_changed();
});
}
PlayStateResult::Push(new_state) => {
direction = Direction::Forwards;
log::info!("Pushed state '{}'", new_state.name());
log::info!("Pushed state '{}'.", new_state.name());
states.push(new_state);
global_state.on_play_state_changed();
}
@ -202,7 +202,7 @@ fn main() {
direction = Direction::Forwards;
states.last_mut().map(|old_state| {
log::info!(
"Switching to state '{}' from state '{}'",
"Switching to state '{}' from state '{}'.",
new_state.name(),
old_state.name()
);

View File

@ -22,7 +22,7 @@ pub struct CharSelectionState {
}
impl CharSelectionState {
/// Create a new `CharSelectionState`
/// Create a new `CharSelectionState`.
pub fn new(window: &mut Window, client: Rc<RefCell<Client>>) -> Self {
Self {
char_selection_ui: CharSelectionUi::new(window),
@ -32,7 +32,7 @@ impl CharSelectionState {
}
}
// The background colour
// Background colour
const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0,
g: 0.3,
@ -42,28 +42,28 @@ const BG_COLOR: Rgba<f32> = Rgba {
impl PlayState for CharSelectionState {
fn play(&mut self, _: Direction, global_state: &mut GlobalState) -> PlayStateResult {
// Set up an fps clock
// Set up an fps clock.
let mut clock = Clock::new();
loop {
// Handle window events
// Handle window events.
for event in global_state.window.fetch_events() {
match event {
Event::Close => {
return PlayStateResult::Shutdown;
}
// Pass events to ui
// Pass events to ui.
Event::Ui(event) => {
self.char_selection_ui.handle_event(event);
}
// Ignore all other events
// Ignore all other events.
_ => {}
}
}
global_state.window.renderer_mut().clear(BG_COLOR);
// Maintain the UI
// Maintain the UI.
for event in self
.char_selection_ui
.maintain(global_state.window.renderer_mut())
@ -89,33 +89,33 @@ impl PlayState for CharSelectionState {
}
}
// Maintain the scene
// Maintain the scene.
self.scene
.maintain(global_state.window.renderer_mut(), &self.client.borrow());
// Render the scene
// Render the scene.
self.scene
.render(global_state.window.renderer_mut(), &self.client.borrow());
// Draw the UI to the screen
// Draw the UI to the screen.
self.char_selection_ui
.render(global_state.window.renderer_mut());
// Tick the client (currently only to keep the connection alive)
// Tick the client (currently only to keep the connection alive).
self.client
.borrow_mut()
.tick(client::Input::default(), clock.get_last_delta())
.expect("Failed to tick the client");
self.client.borrow_mut().cleanup();
// Finish the frame
// Finish the frame.
global_state.window.renderer_mut().flush();
global_state
.window
.swap_buffers()
.expect("Failed to swap window buffers");
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / FPS));
}
}

View File

@ -276,16 +276,16 @@ pub struct CharSelectionUi {
impl CharSelectionUi {
pub fn new(window: &mut Window) -> Self {
let mut ui = Ui::new(window).unwrap();
// TODO: adjust/remove this, right now it is used to demonstrate window scaling functionality
// TODO: Adjust/remove this, right now it is used to demonstrate window scaling functionality.
ui.scaling_mode(ScaleMode::RelativeToWindow([1920.0, 1080.0].into()));
// Generate ids
let ids = Ids::new(ui.id_generator());
// Load images
let imgs = Imgs::load(&mut ui).expect("Failed to load images");
let imgs = Imgs::load(&mut ui).expect("Failed to load images!");
// Load fonts
let fonts = Fonts::load(&mut ui).expect("Failed to load fonts");
let fonts = Fonts::load(&mut ui).expect("Failed to load fonts!");
// TODO: Randomize initial values
// TODO: Randomize initial values.
Self {
ui,
ids,
@ -299,20 +299,20 @@ impl CharSelectionUi {
}
}
// TODO: split this up into multiple modules or functions
// TODO: Split this into multiple modules or functions.
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 /////////////////
// Character Selection
// Supposed functionality:
// 3d rendered characters have to be clicked for selection
// Selected characters will appear in the selection window
// the selection window is only active when there are >0 characters on the server
// after logging into the server the character that was played last will be selected automatically
// if >1 characters are on the server but none of them was logged in last the one that was created last will be selected
// if the no. of characters = character_limit the "Create Character" button won't be clickable anymore
// 3d rendered characters have to be clicked for selection.
// Selected characters will appear in the selection window.
// The selection window is only active when there are >0 characters on the server.
// After logging into the server the character that was played last will be selected automatically.
// If >1 characters are on the server but none of them was logged in last the one that was created last will be selected.
// If the no. of characters = character_limit the "Create Character" button won't be clickable anymore.
// Background Image
if !self.character_creation {
@ -336,7 +336,7 @@ impl CharSelectionUi {
events.push(Event::Logout);
}
// Create Character Button
// Create Character Button.
if Button::image(self.imgs.button)
.mid_bottom_with_margin_on(ui_widgets.window, 10.0)
.w_h(270.0, 50.0)
@ -374,7 +374,7 @@ impl CharSelectionUi {
.font_size(14)
.color(TEXT_COLOR)
.set(self.ids.version, ui_widgets);
// Click Character to Login <-- Temporary!
// Click Character to Login TODO: <-- Temporary!
Image::new(self.imgs.window_frame_2)
.mid_top_with_margin_on(ui_widgets.window, 60.0)
.w_h(700.0, 70.0)
@ -443,7 +443,7 @@ impl CharSelectionUi {
{}
}
}
// Character_Creation //////////////
// Character_Creation
else {
// Background
//Image::new(self.imgs.bg_creation)
@ -478,7 +478,7 @@ impl CharSelectionUi {
.set(self.ids.create_button, ui_widgets)
.was_clicked()
{
// TODO: Save character
// TODO: Save character.
self.character_creation = false;
}
// Character Name Input
@ -519,7 +519,7 @@ impl CharSelectionUi {
.set(self.ids.creation_window, ui_widgets);
// Arrows
// TODO: lower the resolution of the arrow images & use non decimal sizes below
// TODO: Lower the resolution of the arrow images & use non decimal sizes below.
const ARROW_WH: [f64; 2] = [986.0 * 0.03, 1024.0 * 0.03];
match self.creation_state {
CreationState::Race => {
@ -595,7 +595,7 @@ impl CharSelectionUi {
.set(self.ids.select_window_title, ui_widgets);
// Male/Female/Race Icons
// for alignment
// Alignment
Rectangle::fill_with([151.0, 68.0], color::TRANSPARENT)
.mid_top_with_margin_on(self.ids.creation_window, 210.0)
.set(self.ids.body_type_bg, ui_widgets);
@ -636,11 +636,11 @@ impl CharSelectionUi {
{
self.character_body.body_type = BodyType::Female;
}
// for alignment
// Alignment
Rectangle::fill_with([458.0, 68.0], color::TRANSPARENT)
.mid_top_with_margin_on(self.ids.creation_window, 120.0)
.set(self.ids.races_bg, ui_widgets);
// TODO: If races where in some sort of array format we could do this in a loop
// TODO: If races were in some sort of array format, we could do this in a loop.
// Human
Image::new(if let BodyType::Male = self.character_body.body_type {
self.imgs.human_m
@ -777,7 +777,7 @@ impl CharSelectionUi {
// Description Headline and Text
// TODO: Load these from files (or from the server???)
// TODO: Load these from files (or from the server???).
const HUMAN_DESC: &str =
"The former nomads were only recently able to gain a foothold in the world of Veloren. \n\
\n\
@ -854,7 +854,6 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.wrap_by_word()
.set(self.ids.race_description, ui_widgets);
// Races Descriptions
}
if let CreationState::Weapon = self.creation_state {
@ -863,7 +862,7 @@ impl CharSelectionUi {
.font_size(28)
.color(TEXT_COLOR)
.set(self.ids.select_window_title, ui_widgets);
// BG for Alignment
// Alignment
Rectangle::fill_with([470.0, 60.0], color::TRANSPARENT)
.mid_top_with_margin_on(self.ids.creation_window, 180.0)
.set(self.ids.weapon_bg, ui_widgets);
@ -997,7 +996,7 @@ impl CharSelectionUi {
self.character_body.weapon = Weapon::Staff;
}
// TODO: Load these from files (or from the server???)
// TODO: Load these from files (or from the server???).
const SWORDSHIELD_DESC: &str = " MISSING ";
const DAGGERS_DESC: &str = " MISSING ";
const SWORD_DESC: &str = " MISSING ";
@ -1028,12 +1027,11 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.wrap_by_word()
.set(self.ids.race_description, ui_widgets);
// Races Descriptions
}
// 3 states/windows: 1.Skin & Eyes 2.Hair 3.Accessories
// If one state is activated the other ones collapse
// The title bar is the button to unfold/collapse the windows
// The BG Frame can be stretched to the needed size
// 3 states/windows: 1: Skin & Eyes 2: Hair 3: Accessories
// If one state is activated, the other ones collapse.
// The title bar is the button to unfold/collapse the windows.
// The BG Frame can be stretched to the needed size.
// Window BG
if let CreationState::Body(state) = self.creation_state {
@ -1093,7 +1091,7 @@ impl CharSelectionUi {
{
self.creation_state = CreationState::Body(BodyPart::Accessories);
}
} // State 1 fin
}
// Hair Open
BodyPart::Hair => {
@ -1144,7 +1142,7 @@ impl CharSelectionUi {
{
self.creation_state = CreationState::Body(BodyPart::Accessories);
}
} // State 2 fin
}
// Open: Accessories
BodyPart::Accessories => {
@ -1195,10 +1193,10 @@ impl CharSelectionUi {
{
self.creation_state = CreationState::Body(BodyPart::Accessories);
}
} // State 3 fin
} // match fin
}
}
// Body Customization Window Contents ////////////////////////
// Body Customization Window Contents
match state {
BodyPart::SkinEyes => {
// Skin Color: Text, Brightness Slider, Picker
@ -1207,18 +1205,18 @@ impl CharSelectionUi {
.font_size(25)
.color(TEXT_COLOR)
.set(self.ids.skin_color_text, ui_widgets);
// TODO: Align Buttons here
// They set an i32 to a value from 0-14
// Depending on the race another color will be chosen
// Here only the BG image changes depending on the race.
// TODO: Align Buttons here.
// Users set a variable to a value from 0-14.
// Depending on the race another color will be chosen.
// Only the BG image (190x114 -> 2px border!) changes depending on the race.
Rectangle::fill_with([192.0, 116.0], color::WHITE)
.top_right_with_margins_on(self.ids.skin_eyes_window, 60.0, 30.0)
.color(TEXT_COLOR)
.set(self.ids.skin_rect, ui_widgets);
// TODO: Slider
// Sliders actually change the Alpha-Level of the main colour chosen above
// -> They will appear "brighter", therefore the sliders are labeled "Brightness"
// Sliders actually change the Alpha-Level of the main colour chosen above.
// -> They will appear "brighter", therefore the sliders are labeled "Brightness".
Image::new(self.imgs.slider_range)
.w_h(208.0, 12.0)
.bottom_left_with_margins_on(self.ids.skin_rect, 10.0, -255.0)
@ -1241,10 +1239,9 @@ impl CharSelectionUi {
.font_size(25)
.color(TEXT_COLOR)
.set(self.ids.eye_color_text, ui_widgets);
// TODO: Align 16 Buttons here
//
// They set a variable to a value from 0-14
// Depending on the race another color will be chosen
// TODO: Align 16 Buttons here.
// Users set a variable to a value from 0-14.
// Depending on the race another color will be chosen.
// Only the BG image (190x114 -> 2px border!) changes depending on the race.
Rectangle::fill_with([192.0, 116.0], color::WHITE)
.top_right_with_margins_on(self.ids.skin_eyes_window, 186.0, 30.0)
@ -1270,7 +1267,7 @@ impl CharSelectionUi {
.set(self.ids.eye_color_slider_text, ui_widgets);
}
// Hair ///////////////////////////////////////////////////////
// Hair
// Hair Styles -> Arrows
// Hair Color -> Picker
@ -1352,7 +1349,7 @@ impl CharSelectionUi {
.set(self.ids.eyebrow_arrow_l, ui_widgets)
.was_clicked()
{};
// Beard -> Only active when "male" was chosen
// Beard -> Only active if "male" was chosen.
if let BodyType::Male = self.character_body.body_type {
Text::new("Beard Style")
.mid_top_with_margin_on(self.ids.hair_window, 340.0)
@ -1378,9 +1375,9 @@ impl CharSelectionUi {
}
}
// Accessories ///////////////////////////////
// Accessories
// Accessory Picker -> Arrows (Name Changes with race!)
// Accessory Picker -> Arrows (Name changes with race!)
// Color -> Picker
// Brightness -> Slider
BodyPart::Accessories => {
@ -1450,7 +1447,7 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Human
}
Race::Orc => {
Text::new("Head Band")
.mid_top_with_margin_on(self.ids.accessories_window, 60.0)
@ -1516,7 +1513,7 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Orc
}
Race::Elf => {
Text::new("Tribe Markings")
.mid_top_with_margin_on(self.ids.accessories_window, 60.0)
@ -1582,7 +1579,7 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Elf
}
Race::Dwarf => {
Text::new("War Paint")
.mid_top_with_margin_on(self.ids.accessories_window, 60.0)
@ -1648,7 +1645,7 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Dwarf
}
Race::Undead => {
Text::new("Teeth")
.mid_top_with_margin_on(self.ids.accessories_window, 60.0)
@ -1714,7 +1711,7 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Undead
}
Race::Danari => {
Text::new("Horns")
.mid_top_with_margin_on(self.ids.accessories_window, 60.0)
@ -1780,12 +1777,12 @@ impl CharSelectionUi {
.color(TEXT_COLOR)
.font_size(14)
.set(self.ids.warpaint_slider_text, ui_widgets);
} // Danari
}
} // match Race fin
} // Accessories fin
} // Body Customization Fin
} // CreationState::Body Fin
} // Char Creation fin
}
}
}
}
events
}

View File

@ -9,16 +9,17 @@ use std::{
#[derive(Debug)]
pub enum Error {
// Error parsing input string or error resolving host name
// Error parsing input string or error resolving host name.
BadAddress(std::io::Error),
// Parsing yielded an empty iterator (specifically to_socket_addrs())
// Parsing yielded an empty iterator (specifically to_socket_addrs()).
NoAddress,
// Parsing/host name resolution successful but could not connect
// Parsing/host name resolution successful but could not connect.
ConnectionFailed(ClientError),
ClientCrashed,
}
// Used to asynchronusly parse the server address, resolve host names, and create the client (which involves establishing a connection to the server)
// Used to asynchronously parse the server address, resolve host names,
// and create the client (which involves establishing a connection to the server).
pub struct ClientInit {
rx: Receiver<Result<Client, Error>>,
}
@ -34,19 +35,20 @@ impl ClientInit {
let (tx, rx) = channel();
thread::spawn(move || {
// Sleep the thread to wait for the single-player server to start up
// Sleep the thread to wait for the single-player server to start up.
if wait {
thread::sleep(Duration::from_millis(500));
}
// Parses ip address or resolves hostname
// Note: if you use an ipv6 address the number after the last colon will be used as the port unless you use [] around the address
// Parse ip address or resolves hostname.
// Note: if you use an ipv6 address, the number after the last colon will be used
// as the port unless you use [] around the address.
match server_address
.to_socket_addrs()
.or((server_address.as_ref(), default_port).to_socket_addrs())
{
Ok(socket_adders) => {
Ok(socket_address) => {
let (first_addrs, second_addrs) =
socket_adders.partition::<Vec<_>, _>(|a| a.is_ipv6() == prefer_ipv6);
socket_address.partition::<Vec<_>, _>(|a| a.is_ipv6() == prefer_ipv6);
let mut last_err = None;
@ -59,11 +61,11 @@ impl ClientInit {
}
Err(err) => {
match err {
// assume connection failed and try next address
// Assume the connection failed and try next address.
ClientError::Network(_) => {
last_err = Some(Error::ConnectionFailed(err))
}
// TODO: handle error?
// TODO: Handle errors?
_ => panic!(
"Unexpected non-network error when creating client: {:?}",
err
@ -72,11 +74,11 @@ impl ClientInit {
}
}
}
// Parsing/host name resolution successful but no connection succeeded
// Parsing/host name resolution successful but no connection succeeded.
let _ = tx.send(Err(last_err.unwrap_or(Error::NoAddress)));
}
Err(err) => {
// Error parsing input string or error resolving host name
// Error parsing input string or error resolving host name.
let _ = tx.send(Err(Error::BadAddress(err)));
}
}
@ -84,8 +86,8 @@ impl ClientInit {
ClientInit { rx }
}
// Returns None is the thread is still running
// Otherwise returns the Result of client creation
/// Poll if the thread is complete.
/// Returns None if the thread is still running, otherwise returns the Result of client creation.
pub fn poll(&self) -> Option<Result<Client, Error>> {
match self.rx.try_recv() {
Ok(result) => Some(result),

View File

@ -21,7 +21,7 @@ pub struct MainMenuState {
}
impl MainMenuState {
/// Create a new `MainMenuState`
/// Create a new `MainMenuState`.
pub fn new(global_state: &mut GlobalState) -> Self {
Self {
main_menu_ui: MainMenuUi::new(global_state),
@ -41,29 +41,29 @@ const BG_COLOR: Rgba<f32> = Rgba {
impl PlayState for MainMenuState {
fn play(&mut self, _: Direction, global_state: &mut GlobalState) -> PlayStateResult {
// Set up an fps clock
// Set up an fps clock.
let mut clock = Clock::new();
// Used for client creation
// Used for client creation.
let mut client_init: Option<ClientInit> = None;
loop {
// Handle window events
// Handle window events.
for event in global_state.window.fetch_events() {
match event {
Event::Close => return PlayStateResult::Shutdown,
// Pass events to ui
// Pass events to ui.
Event::Ui(event) => {
self.main_menu_ui.handle_event(event);
}
// Ignore all other events
// Ignore all other events.
_ => {}
}
}
global_state.window.renderer_mut().clear(BG_COLOR);
// Poll client creation
// Poll client creation.
match client_init.as_ref().and_then(|init| init.poll()) {
Some(Ok(client)) => {
self.main_menu_ui.connected();
@ -86,7 +86,7 @@ impl PlayState for MainMenuState {
None => {}
}
// Maintain the UI
// Maintain the UI.
for event in self.main_menu_ui.maintain(global_state) {
match event {
MainMenuEvent::LoginAttempt {
@ -98,9 +98,9 @@ impl PlayState for MainMenuState {
if !net_settings.servers.contains(&server_address) {
net_settings.servers.push(server_address.clone());
}
// TODO: Handle this result
// TODO: Handle this result.
global_state.settings.save_to_file();
// Don't try to connect if there is already a connection in progress
// Don't try to connect if there is already a connection in progress.
client_init = client_init.or(Some(ClientInit::new(
(server_address, DEFAULT_PORT, false),
(comp::Player::new(username.clone()), 300),
@ -114,17 +114,17 @@ impl PlayState for MainMenuState {
}
}
// Draw the UI to the screen
// Draw the UI to the screen.
self.main_menu_ui.render(global_state.window.renderer_mut());
// Finish the frame
// Finish the frame.
global_state.window.renderer_mut().flush();
global_state
.window
.swap_buffers()
.expect("Failed to swap window buffers");
.expect("Failed to swap window buffers!");
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / FPS));
}
}

View File

@ -13,7 +13,7 @@ pub struct StartSingleplayerState {
}
impl StartSingleplayerState {
/// Create a new `MainMenuState`
/// Create a new `MainMenuState`.
pub fn new() -> Self {
let (singleplayer, sock) = Singleplayer::new();
@ -34,13 +34,12 @@ impl PlayState for StartSingleplayerState {
true,
);
// Client creation
// Create the client.
let client = loop {
match client_init.poll() {
Some(Ok(client)) => break client,
// An error occured!
Some(Err(err)) => {
warn!("Failed to start singleplayer server: {:?}", err);
warn!("Failed to start single-player server: {:?}", err);
return PlayStateResult::Pop;
}
_ => {}
@ -52,7 +51,7 @@ impl PlayState for StartSingleplayerState {
if !net_settings.servers.contains(&server_address) {
net_settings.servers.push(server_address.clone());
}
// TODO: Handle this result
// TODO: Handle this result.
global_state.settings.save_to_file();
PlayStateResult::Push(Box::new(CharSelectionState::new(
@ -65,6 +64,6 @@ impl PlayState for StartSingleplayerState {
}
fn name(&self) -> &'static str {
"Starting Singleplayer"
"Starting Single-Player"
}
}

View File

@ -237,7 +237,7 @@ impl MainMenuUi {
let netsettings = &global_state.settings.networking;
// TODO: draw scroll bar or remove it
// TODO: Draw scroll bar or remove it.
let (mut items, scrollbar) = List::flow_down(netsettings.servers.len())
.top_left_with_margins_on(self.ids.servers_frame, 0.0, 5.0)
.w_h(400.0, 300.0)

View File

@ -7,7 +7,7 @@ use crate::render::{
Pipeline,
};
/// Given a volume, a position and the cardinal directions, compute each vertex' AO value
/// Given volume, position, and cardinal directions, compute each vertex's AO value.
/// `dirs` should be a slice of length 5 so that the sliding window of size 2 over the slice
/// yields each vertex' adjacent positions.
fn get_ao_quad<V: ReadVol>(vol: &V, pos: Vec3<i32>, dirs: &[Vec3<i32>]) -> Vec4<f32> {
@ -29,7 +29,7 @@ fn get_ao_quad<V: ReadVol>(vol: &V, pos: Vec3<i32>, dirs: &[Vec3<i32>]) -> Vec4<
.get(pos + offs[0] + offs[1])
.map(|v| !v.is_empty())
.unwrap_or(false);
// Map both 1 and 2 neighbors to 0.5 occlusion
// Map both 1 and 2 neighbors to 0.5 occlusion.
if s1 || s2 || corner {
0.5
} else {

View File

@ -12,7 +12,7 @@ pub struct Consts<T: Copy + gfx::traits::Pod> {
}
impl<T: Copy + gfx::traits::Pod> Consts<T> {
/// Create a new `Const<T>`
/// Create a new `Const<T>`.
pub fn new(factory: &mut gfx_backend::Factory, len: usize) -> Self {
Self {
buf: factory.create_constant_buffer(len),

View File

@ -8,12 +8,12 @@ pub struct Mesh<P: Pipeline> {
}
impl<P: Pipeline> Mesh<P> {
/// Create a new `Mesh`
/// Create a new `Mesh`.
pub fn new() -> Self {
Self { verts: vec![] }
}
/// Clear vertices, allows reusing allocated memory of the underlying Vec
/// Clear vertices, allows reusing allocated memory of the underlying Vec.
pub fn clear(&mut self) {
self.verts.clear();
}
@ -50,12 +50,12 @@ impl<P: Pipeline> Mesh<P> {
self.verts.push(quad.a);
}
/// Push the vertices of another mesh onto the end of this mesh
/// Push the vertices of another mesh onto the end of this mesh.
pub fn push_mesh(&mut self, other: &Mesh<P>) {
self.verts.extend_from_slice(other.vertices());
}
/// Push the vertices of another mesh onto the end of this mesh
/// Map and push the vertices of another mesh onto the end of this mesh.
pub fn push_mesh_map<F: FnMut(P::Vertex) -> P::Vertex>(&mut self, other: &Mesh<P>, mut f: F) {
// Reserve enough space in our Vec. This isn't necessary, but it tends to reduce the number
// of required (re)allocations.

View File

@ -33,7 +33,7 @@ use gfx_device_gl as gfx_backend;
// Library
use gfx;
/// Used to represent one of many possible errors that may be omitted by the rendering subsystem
/// Used to represent one of many possible errors that may be omitted by the rendering subsystem.
#[derive(Debug)]
pub enum RenderError {
PipelineError(gfx::PipelineStateError<String>),

View File

@ -28,7 +28,7 @@ impl<P: Pipeline> Model<P> {
}
}
/// Represents a mesh on the GPU which can be updated dynamically
/// Represents a mesh on the GPU which can be updated dynamically.
pub struct DynamicModel<P: Pipeline> {
pub vbuf: gfx::handle::Buffer<gfx_backend::Resources, P::Vertex>,
}
@ -42,7 +42,7 @@ impl<P: Pipeline> DynamicModel<P> {
})
}
/// Create a model with a slice of a portion of this model to send to the renderer
/// Create a model with a slice of a portion of this model to send to the renderer.
pub fn submodel(&self, range: Range<usize>) -> Model<P> {
Model {
vbuf: self.vbuf.clone(),

View File

@ -23,9 +23,9 @@ gfx_defines! {
proj_mat: [[f32; 4]; 4] = "proj_mat",
cam_pos: [f32; 4] = "cam_pos",
focus_pos: [f32; 4] = "focus_pos",
// TODO: Fix whatever alignment issue requires these uniforms to be aligned
// TODO: Fix whatever alignment issue requires these uniforms to be aligned.
view_distance: [f32; 4] = "view_distance",
time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64
time_of_day: [f32; 4] = "time_of_day", // TODO: Make this f64.
tick: [f32; 4] = "tick",
screen_res: [f32; 4] = "screen_res",
}

View File

@ -67,8 +67,7 @@ pub struct Renderer {
}
impl Renderer {
/// Create a new `Renderer` from a variety of backend-specific components and the window
/// targets.
/// Create a new `Renderer` from a variety of backend-specific components and the window targets.
pub fn new(
device: gfx_backend::Device,
mut factory: gfx_backend::Factory,
@ -186,11 +185,11 @@ impl Renderer {
(&mut self.win_color_view, &mut self.win_depth_view)
}
/// Resize internal render targets to match window render target dimensions
/// Resize internal render targets to match window render target dimensions.
pub fn on_resize(&mut self) -> Result<(), RenderError> {
let dims = self.win_color_view.get_dimensions();
// Panics when creating texture with w,h of 0,0
// Avoid panics when creating texture with w,h of 0,0.
if dims.0 != 0 && dims.1 != 0 {
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
Self::create_rt_views(&mut self.factory, (dims.0, dims.1))?;
@ -224,7 +223,7 @@ impl Renderer {
}
/// Queue the clearing of the color and depth targets ready for a new frame to be rendered.
/// TODO: Make a version of this that doesn't clear the colour target for speed
/// TODO: Make a version of this that doesn't clear the colour target for speed.
pub fn clear(&mut self, col: Rgba<f32>) {
self.encoder.clear(&self.tgt_color_view, col.into_array());
self.encoder.clear_depth(&self.tgt_depth_view, 1.0);
@ -262,7 +261,7 @@ impl Renderer {
Ok(Model::new(&mut self.factory, mesh))
}
/// Create a new dynamic model with the specified size
/// Create a new dynamic model with the specified size.
pub fn create_dynamic_model<P: Pipeline>(
&mut self,
size: usize,
@ -270,7 +269,7 @@ impl Renderer {
DynamicModel::new(&mut self.factory, size)
}
/// Update a dynamic model with a mesh and a offset
/// Update a dynamic model with a mesh and a offset.
pub fn update_model<P: Pipeline>(
&mut self,
model: &DynamicModel<P>,
@ -288,7 +287,7 @@ impl Renderer {
Texture::new(&mut self.factory, image)
}
/// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the specified dimensions
/// Create a new dynamic texture (gfx::memory::Usage::Dynamic) with the specified dimensions.
pub fn create_dynamic_texture<P: Pipeline>(
&mut self,
dims: Vec2<u16>,
@ -296,7 +295,7 @@ impl Renderer {
Texture::new_dynamic(&mut self.factory, dims.x, dims.y)
}
/// Update a texture with the provided offset, size, and data
/// Update a texture with the provided offset, size, and data.
pub fn update_texture<P: Pipeline>(
&mut self,
texture: &Texture<P>,
@ -449,7 +448,7 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
},
pipe,
)
// Do some funky things to work around an oddity in gfx's error ownership rules
// Do some funky things to work around an oddity in gfx's error ownership rules.
.map_err(|err| {
RenderError::PipelineError(match err {
gfx::PipelineStateError::Program(err) => gfx::PipelineStateError::Program(err),

View File

@ -89,7 +89,7 @@ impl<P: Pipeline> Texture<P> {
})
}
// Updates a texture with the given data (used for updating the glyph cache texture)
/// Update a texture with the given data (used for updating the glyph cache texture).
pub fn update(
&self,
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
@ -113,7 +113,7 @@ impl<P: Pipeline> Texture<P> {
)
.map_err(|err| RenderError::TexUpdateError(err))
}
/// Get dimensions of the represented image
/// Get dimensions of the represented image.
pub fn get_dimensions(&self) -> Vec2<u16> {
let (w, h, ..) = self.tex.get_info().kind.get_dimensions();
Vec2::new(w, h)

View File

@ -1,4 +1,4 @@
// TODO: Get rid of this ugliness
// TODO: Get rid of this ugliness.
#[rustfmt::skip]
pub fn arr_to_mat(arr: [f32; 16]) -> [[f32; 4]; 4] {
[

View File

@ -79,7 +79,7 @@ impl Camera {
let proj_mat = Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE);
// TODO: Make this more efficient
// TODO: Make this more efficient.
let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w());
(view_mat, proj_mat, cam_pos)
@ -95,7 +95,7 @@ impl Camera {
self.ori.z = (self.ori.z + delta.z) % (2.0 * PI);
}
/// Set the orientation of the camera about its focus
/// Set the orientation of the camera about its focus.
pub fn set_orientation(&mut self, orientation: Vec3<f32>) {
// Wrap camera yaw
self.ori.x = orientation.x % (2.0 * PI);
@ -111,7 +111,7 @@ impl Camera {
self.tgt_dist = (self.tgt_dist + delta).max(0.0);
}
/// Set the distance of the camera from the target (i.e: zoom)
/// Set the distance of the camera from the target (i.e., zoom).
pub fn set_distance(&mut self, dist: f32) {
self.tgt_dist = dist;
}
@ -146,7 +146,7 @@ impl Camera {
self.aspect = if aspect.is_normal() { aspect } else { 1.0 };
}
/// Get the orientation of the camera
/// Get the orientation of the camera.
pub fn get_orientation(&self) -> Vec3<f32> {
self.ori
}

View File

@ -16,7 +16,7 @@ use common::{
comp::{
self,
actor::{
Belt, Chest, Draw, Foot, Hand, Head, Pants, Pigchest, Pighead, Pigleg_l, Pigleg_r,
Belt, Chest, Draw, Foot, Hand, Head, Pants, PigChest, PigHead, PigLegL, PigLegR,
Shoulder, Weapon,
},
Body, HumanoidBody, QuadrupedBody,
@ -75,12 +75,12 @@ impl FigureModelCache {
None,
],
Body::Quadruped(body) => [
Some(Self::load_pighead(body.pighead)),
Some(Self::load_pigchest(body.pigchest)),
Some(Self::load_piglf_leg(body.pigleg_l)),
Some(Self::load_pigrf_leg(body.pigleg_r)),
Some(Self::load_piglb_leg(body.pigleg_l)),
Some(Self::load_pigrb_leg(body.pigleg_r)),
Some(Self::load_pig_head(body.pig_head)),
Some(Self::load_pig_chest(body.pig_chest)),
Some(Self::load_pig_leg_lf(body.pig_leg_l)),
Some(Self::load_pig_leg_rf(body.pig_leg_r)),
Some(Self::load_pig_leg_lb(body.pig_leg_l)),
Some(Self::load_pig_leg_rb(body.pig_leg_r)),
None,
None,
None,
@ -117,15 +117,15 @@ impl FigureModelCache {
}
pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
self.models
.retain(|_, (_, last_used)| *last_used + 60 > tick);
}
// TODO: Don't make this public
// TODO: Don't make this public.
pub fn load_mesh(filename: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(fullpath.as_str()).as_ref())
let full_path: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(full_path.as_str()).as_ref())
.generate_mesh(position)
}
@ -205,7 +205,7 @@ impl FigureModelCache {
Self::load_mesh(
match weapon {
Weapon::Sword => "sword.vox",
// TODO actually match against other weapons and set the right model
// TODO actually match against other weapons and set the right model.
_ => "sword.vox",
},
Vec3::new(0.0, 0.0, -4.0),
@ -238,55 +238,55 @@ impl FigureModelCache {
)
}
fn load_pighead(pighead: Pighead) -> Mesh<FigurePipeline> {
fn load_pig_head(pig_head: PigHead) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pighead {
Pighead::Default => "pighead.vox",
match pig_head {
PigHead::Default => "pighead.vox",
},
Vec3::new(-6.0, 4.5, 3.0),
)
}
fn load_pigchest(pigchest: Pigchest) -> Mesh<FigurePipeline> {
fn load_pig_chest(pig_chest: PigChest) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pigchest {
Pigchest::Default => "pigchest.vox",
match pig_chest {
PigChest::Default => "pigchest.vox",
},
Vec3::new(-5.0, 4.5, 0.0),
)
}
fn load_piglf_leg(pigleg_l: Pigleg_l) -> Mesh<FigurePipeline> {
fn load_pig_leg_lf(pig_leg_l: PigLegL) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pig_leg_l {
PigLegL::Default => "pigleg_l.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
}
fn load_pig_leg_rf(pig_leg_r: PigLegR) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pig_leg_r {
PigLegR::Default => "pigleg_r.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
}
fn load_pig_leg_lb(pigleg_l: PigLegL) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pigleg_l {
Pigleg_l::Default => "pigleg_l.vox",
PigLegL::Default => "pigleg_l.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
}
fn load_pigrf_leg(pigleg_r: Pigleg_r) -> Mesh<FigurePipeline> {
fn load_pig_leg_rb(pig_leg_r: PigLegR) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pigleg_r {
Pigleg_r::Default => "pigleg_r.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
}
fn load_piglb_leg(pigleg_l: Pigleg_l) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pigleg_l {
Pigleg_l::Default => "pigleg_l.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
}
fn load_pigrb_leg(pigleg_r: Pigleg_r) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pigleg_r {
Pigleg_r::Default => "pigleg_r.vox",
match pig_leg_r {
PigLegR::Default => "pigleg_r.vox",
},
Vec3::new(0.0, -1.0, -1.5),
)
@ -411,7 +411,7 @@ impl FigureMgr {
}
}
// Clear states that have dead entities
// Clear states that have dead entities.
self.character_states
.retain(|entity, _| ecs.entities().is_alive(*entity));
self.quadruped_states

View File

@ -93,15 +93,15 @@ impl FigureModelCache {
}
pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
self.models
.retain(|_, (_, last_used)| *last_used + 60 > tick);
}
// TODO: Don't make this public
// TODO: Don't make this public.
pub fn load_mesh(filename: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(fullpath.as_str()).as_ref())
let full_path: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(full_path.as_str()).as_ref())
.generate_mesh(position)
}
@ -181,7 +181,7 @@ impl FigureModelCache {
Self::load_mesh(
match weapon {
Weapon::Sword => "sword.vox",
// TODO actually match against other weapons and set the right model
// TODO actually match against other weapons and set the right model.
_ => "sword.vox",
},
Vec3::new(0.0, 0.0, -4.0),
@ -276,9 +276,9 @@ impl FigureMgr {
state.skeleton.interpolate(&target_skeleton);
state.update(renderer, pos.0, dir.0);
} // TODO: Non-humanoid bodies
} // TODO: Non-humanoid bodies.
},
// TODO: Non-character actors
// TODO: Non-character actors.
}
}
@ -308,9 +308,9 @@ impl FigureMgr {
state.bone_consts(),
);
}
} // TODO: Non-humanoid bodies
} // TODO: Non-humanoid bodies.
},
// TODO: Non-character actors
// TODO: Non-character actors.
}
}
}

View File

@ -93,15 +93,15 @@ impl FigureModelCache {
}
pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
self.models
.retain(|_, (_, last_used)| *last_used + 60 > tick);
}
// TODO: Don't make this public
// TODO: Don't make this public.
pub fn load_mesh(filename: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(fullpath.as_str()).as_ref())
let full_path: String = ["/voxygen/voxel/", filename].concat();
Segment::from(assets::load_expect::<DotVoxData>(full_path.as_str()).as_ref())
.generate_mesh(position)
}
@ -123,7 +123,7 @@ impl FigureModelCache {
)
}
fn load_lf_leg(leg_l: Leg_l) -> Mesh<FigurePipeline> {
fn load_leg_lf(leg_l: Leg_l) -> Mesh<FigurePipeline> {
Self::load_mesh(
match belt {
Belt::Default => "pigleg_l.vox",
@ -132,7 +132,7 @@ impl FigureModelCache {
)
}
fn load_rf_leg(leg_R: Leg_r) -> Mesh<FigurePipeline> {
fn load_leg_rf(leg_r: Leg_r) -> Mesh<FigurePipeline> {
Self::load_mesh(
match pants {
Pants::Default => "pigleg_r.vox",
@ -141,7 +141,7 @@ impl FigureModelCache {
)
}
fn load_lb_leg(leg_l: Leg_l) -> Mesh<FigurePipeline> {
fn load_leg_lb(leg_l: Leg_l) -> Mesh<FigurePipeline> {
Self::load_mesh(
match hand {
Hand::Default => "pigleg_l.vox",
@ -150,7 +150,7 @@ impl FigureModelCache {
)
}
fn load_rb_leg(leg_R: Leg_r) -> Mesh<FigurePipeline> {
fn load_leg_rb(leg_r: Leg_r) -> Mesh<FigurePipeline> {
Self::load_mesh(
match hand {
Hand::Default => "pigleg_r.vox",
@ -214,7 +214,7 @@ impl FigureMgr {
self.states
.retain(|entity, _| ecs.entities().is_alive(*entity));
}
} // TODO: Place `render` into above impl and fix `maintain`.
pub fn render(
&mut self,

View File

@ -20,7 +20,7 @@ use common::{comp, figure::Segment};
use dot_vox;
use vek::*;
// TODO: Don't hard-code this
// TODO: Don't hard-code this.
const CURSOR_PAN_SCALE: f32 = 0.005;
struct Skybox {
@ -78,9 +78,9 @@ impl Scene {
&mut self.camera
}
/// Handle an incoming user input event (i.e: cursor moved, key pressed, window closed, etc.).
/// Handle an incoming user input event (e.g.: cursor moved, key pressed, window closed).
///
/// If the event is handled, return true
/// If the event is handled, return true.
pub fn handle_input_event(&mut self, event: Event) -> bool {
match event {
// When the window is resized, change the camera's aspect ratio
@ -105,7 +105,7 @@ impl Scene {
/// Maintain data such as GPU constant buffers, models, etc. To be called once per tick.
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) {
// Get player position
// Get player position.
let player_pos = client
.state()
.ecs()
@ -114,16 +114,16 @@ impl Scene {
.map(|pos| pos.0)
.unwrap_or(Vec3::zero());
// Alter camera position to match player
// Alter camera position to match player.
self.camera.set_focus_pos(player_pos + Vec3::unit_z() * 2.1);
// Tick camera for interpolation
// Tick camera for interpolation.
self.camera.update(client.state().get_time());
// Compute camera matrices
// Compute camera matrices.
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(client);
// Update global constants
// Update global constants.
renderer
.update_consts(
&mut self.globals,
@ -140,22 +140,22 @@ impl Scene {
)
.expect("Failed to update global constants");
// Maintain the terrain
// Maintain the terrain.
self.terrain.maintain(renderer, client);
// Maintain the figures
// Maintain the figures.
self.figure_mgr.maintain(renderer, client);
// Remove unused figures
// Remove unused figures.
self.figure_mgr.clean(client.get_tick());
}
/// Render the scene using the provided `Renderer`
/// Render the scene using the provided `Renderer`.
pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client) {
// Render the skybox first (it appears over everything else so must be rendered first)
// Render the skybox first (it appears over everything else so must be rendered first).
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
// Render terrain and figures
// Render terrain and figures.
self.terrain.render(renderer, &self.globals);
self.figure_mgr.render(renderer, client, &self.globals);

View File

@ -19,14 +19,14 @@ struct ChunkMeshState {
active_worker: bool,
}
/// A type produced by mesh worker threads corresponding to the position and mesh of a chunk
/// A type produced by mesh worker threads corresponding to the position and mesh of a chunk.
struct MeshWorkerResponse {
pos: Vec2<i32>,
mesh: Mesh<TerrainPipeline>,
started_tick: u64,
}
/// Function executed by worker threads dedicated to chunk meshing
/// Function executed by worker threads dedicated to chunk meshing.
fn mesh_worker(
pos: Vec2<i32>,
started_tick: u64,
@ -44,7 +44,7 @@ pub struct Terrain {
chunks: HashMap<Vec2<i32>, TerrainChunk>,
// The mpsc sender and receiver used for talking to meshing worker threads.
// We keep the sender component for no reason othe than to clone it and send it to new workers.
// We keep the sender component for no reason other than to clone it and send it to new workers.
mesh_send_tmp: mpsc::Sender<MeshWorkerResponse>,
mesh_recv: mpsc::Receiver<MeshWorkerResponse>,
mesh_todo: HashMap<Vec2<i32>, ChunkMeshState>,
@ -69,7 +69,7 @@ impl Terrain {
pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) {
let current_tick = client.get_tick();
// Add any recently created or changed chunks to the list of chunks to be meshed
// Add any recently created or changed chunks to the list of chunks to be meshed.
for pos in client
.state()
.changes()
@ -108,7 +108,7 @@ impl Terrain {
}
}
}
// Remove any models for chunks that have been recently removed
// Remove any models for chunks that have been recently removed.
for pos in &client.state().changes().removed_chunks {
self.chunks.remove(pos);
self.mesh_todo.remove(pos);
@ -117,11 +117,11 @@ impl Terrain {
for todo in self
.mesh_todo
.values_mut()
// Only spawn workers for meshing jobs without an active worker already
// Only spawn workers for meshing jobs without an active worker already.
.filter(|todo| !todo.active_worker)
{
// Find the area of the terrain we want. Because meshing needs to compute things like
// ambient occlusion and edge elision, we also need to borders of the chunk's
// ambient occlusion and edge elision, we also need the borders of the chunk's
// neighbours too (hence the `- 1` and `+ 1`).
let aabr = Aabr {
min: todo
@ -138,40 +138,40 @@ impl Terrain {
};
// Copy out the chunk data we need to perform the meshing. We do this by taking a
// sample of the terrain that includes both the chunk we want and
// sample of the terrain that includes both the chunk we want and its neighbours.
let volume = match client.state().terrain().sample(aabr) {
Ok(sample) => sample,
// If either this chunk or its neighbours doesn't yet exist, so we keep it in the
// todo queue to be processed at a later date when we have its neighbours.
// Either this chunk or its neighbours doesn't yet exist, so we keep it in the
// queue to be processed at a later date when we have its neighbours.
Err(VolMap2dErr::NoSuchChunk) => return,
_ => panic!("Unhandled edge case"),
};
// Clone various things to that they can be moved into the thread
// Clone various things so that they can be moved into the thread.
let send = self.mesh_send_tmp.clone();
let pos = todo.pos;
// Queue the worker thread
// Queue the worker thread.
client.thread_pool().execute(move || {
let _ = send.send(mesh_worker(pos, current_tick, volume, aabb));
});
todo.active_worker = true;
}
// Receive a chunk mesh from a worker thread, upload it to the GPU and then store it
// Receive a chunk mesh from a worker thread and upload it to the GPU, then store it.
// Only pull out one chunk per frame to avoid an unacceptable amount of blocking lag due
// to the GPU upload. That still gives us a 60 chunks / second budget to play with.
if let Ok(response) = self.mesh_recv.recv_timeout(Duration::new(0, 0)) {
match self.mesh_todo.get(&response.pos) {
// It's the mesh we want, insert the newly finished model into the terrain model
// data structure (convert the mesh to a model first of course)
// data structure (convert the mesh to a model first of course).
Some(todo) if response.started_tick == todo.started_tick => {
self.chunks.insert(
response.pos,
TerrainChunk {
model: renderer
.create_model(&response.mesh)
.expect("Failed to upload chunk mesh to the GPU"),
.expect("Failed to upload chunk mesh to the GPU!"),
locals: renderer
.create_consts(&[TerrainLocals {
model_offs: Vec3::from(
@ -181,12 +181,12 @@ impl Terrain {
)
.into_array(),
}])
.expect("Failed to upload chunk locals to the GPU"),
.expect("Failed to upload chunk locals to the GPU!"),
},
);
}
// Chunk must have been removed, or it was spawned on an old tick. Drop the mesh
// since it's either out of date or no longer needed
// since it's either out of date or no longer needed.
_ => {}
}
}

View File

@ -22,11 +22,11 @@ pub struct SessionState {
hud: Hud,
}
/// Represents an active game session (i.e: one that is being played)
/// Represents an active game session (i.e., the one being played).
impl SessionState {
/// Create a new `SessionState`
/// Create a new `SessionState`.
pub fn new(window: &mut Window, client: Rc<RefCell<Client>>, settings: Settings) -> Self {
// Create a scene for this session. The scene handles visible elements of the game world
// Create a scene for this session. The scene handles visible elements of the game world.
let scene = Scene::new(window.renderer_mut(), &client.borrow());
Self {
scene,
@ -38,7 +38,7 @@ impl SessionState {
}
}
// The background colour
// Background colour
const BG_COLOR: Rgba<f32> = Rgba {
r: 0.0,
g: 0.3,
@ -47,9 +47,10 @@ const BG_COLOR: Rgba<f32> = Rgba {
};
impl SessionState {
/// Tick the session (and the client attached to it)
/// Tick the session (and the client attached to it).
pub fn tick(&mut self, dt: Duration) -> Result<(), Error> {
// Calculate the movement input vector of the player from the current key presses and the camera direction
// Calculate the movement input vector of the player from the current key presses
// and the camera direction.
let ori = self.scene.camera().get_orientation();
let unit_vecs = (
Vec2::new(ori[0].cos(), -ori[0].sin()),
@ -58,7 +59,7 @@ impl SessionState {
let dir_vec = self.key_state.dir_vec();
let move_dir = unit_vecs.0 * dir_vec[0] + unit_vecs.1 * dir_vec[1];
// Take the input events
// Take the input events.
let mut input_events = Vec::new();
mem::swap(&mut self.input_events, &mut input_events);
@ -84,7 +85,7 @@ impl SessionState {
Ok(())
}
/// Clean up the session (and the client attached to it) after a tick
/// Clean up the session (and the client attached to it) after a tick.
pub fn cleanup(&mut self) {
self.client.borrow_mut().cleanup();
}
@ -108,13 +109,13 @@ impl SessionState {
impl PlayState for SessionState {
fn play(&mut self, _: Direction, global_state: &mut GlobalState) -> PlayStateResult {
// Trap the cursor
// Trap the cursor.
global_state.window.grab_cursor(true);
// Set up an fps clock
// Set up an fps clock.
let mut clock = Clock::new();
// Load a few chunks TODO: Remove this
// Load a few chunks. TODO: Remove this.
/*
for x in -6..7 {
for y in -6..7 {
@ -127,9 +128,9 @@ impl PlayState for SessionState {
// Game loop
loop {
// Handle window events
// Handle window events.
for event in global_state.window.fetch_events() {
// Pass all events to the ui first
// Pass all events to the ui first.
if self.hud.handle_event(event.clone(), global_state) {
continue;
}
@ -162,16 +163,16 @@ impl PlayState for SessionState {
// TODO: Do something if the event wasn't handled?
}
// Perform an in-game tick
// Perform an in-game tick.
self.tick(clock.get_last_delta())
.expect("Failed to tick the scene");
.expect("Failed to tick the scene!");
// Maintain the scene
// Maintain the scene.
self.scene.maintain(
global_state.window.renderer_mut(),
&mut self.client.borrow_mut(),
);
// Maintain the UI
// Maintain the UI.
for event in self
.hud
.maintain(global_state.window.renderer_mut(), clock.get_tps())
@ -188,19 +189,19 @@ impl PlayState for SessionState {
}
}
// Render the session
// Render the session.
self.render(global_state.window.renderer_mut());
// Display the frame on the window
// Display the frame on the window.
global_state
.window
.swap_buffers()
.expect("Failed to swap window buffers");
.expect("Failed to swap window buffers!");
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / FPS));
// Clean things up after the tick
// Clean things up after the tick.
self.cleanup();
}
}

View File

@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize};
use std::{fs::File, io::prelude::*, path::PathBuf};
use toml;
/// Settings contains everything that can be configured in the Settings.toml file
/// `Settings` contains everything that can be configured in the Settings.toml file.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct Settings {
@ -14,7 +14,7 @@ pub struct Settings {
pub log: Log,
}
/// ControlSettings contains keybindings
/// `ControlSettings` contains keybindings.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ControlSettings {
pub toggle_cursor: VirtualKeyCode,
@ -95,20 +95,20 @@ impl Settings {
config
.merge(
Config::try_from(&default_settings)
.expect("Default settings struct could not be converted to Config"),
.expect("Default settings struct could not be converted to Config!"),
)
.unwrap();
// TODO: log errors here
// If merge or try_into fail use the default settings
// TODO: Log errors here.
// If merge or try_into fail, use the default settings.
match config.merge::<config::File<_>>(path.into()) {
Ok(_) => match config.try_into() {
Ok(settings) => settings,
Err(_) => default_settings,
},
Err(_) => {
// Maybe the file didn't exist
// TODO: Handle this result
// Maybe the file didn't exist.
// TODO: Handle this result.
default_settings.save_to_file();
default_settings
}
@ -126,7 +126,7 @@ impl Settings {
fn get_settings_path() -> PathBuf {
let proj_dirs =
ProjectDirs::from("net", "veloren", "voxygen").expect("No home directory defined.");
ProjectDirs::from("net", "veloren", "voxygen").expect("No home directory defined!");
let path = proj_dirs.config_dir();
path.join("settings");
let path = path.with_extension("toml");

View File

@ -28,7 +28,7 @@ impl Singleplayer {
let sock = SocketAddr::from((
[127, 0, 0, 1],
pick_unused_port().expect("Failed to find unused port"),
pick_unused_port().expect("Failed to find unused port!"),
));
let sock2 = sock.clone();
@ -60,12 +60,12 @@ fn run_server(sock: SocketAddr, rec: Receiver<Msg>) {
let mut clock = Clock::new();
// Create server
let mut server = Server::bind(sock).expect("Failed to create server instance");
let mut server = Server::bind(sock).expect("Failed to create server instance!");
loop {
let events = server
.tick(Input::default(), clock.get_last_delta())
.expect("Failed to tick server");
.expect("Failed to tick server!");
for event in events {
match event {
@ -75,7 +75,7 @@ fn run_server(sock: SocketAddr, rec: Receiver<Msg>) {
}
}
// Clean up the server after a tick
// Clean up the server after a tick.
server.cleanup();
match rec.try_recv() {
@ -86,7 +86,7 @@ fn run_server(sock: SocketAddr, rec: Receiver<Msg>) {
},
}
// Wait for the next tick
// Wait for the next tick.
clock.tick(Duration::from_millis(1000 / TPS));
}
}

View File

@ -7,12 +7,12 @@ impl Event {
pub fn try_from(event: glutin::Event, window: &glutin::GlWindow) -> Option<Self> {
use conrod_winit::*;
use winit;
// A wrapper around the winit window that allows us to implement the trait necessary for enabling
// the winit <-> conrod conversion functions.
// A wrapper around the winit window that allows us to implement the trait necessary for
// enabling the winit <-> conrod conversion functions.
struct WindowRef<'a>(&'a winit::Window);
// Implement the `WinitWindow` trait for `WindowRef` to allow for generating compatible conversion
// functions.
// Implement the `WinitWindow` trait for `WindowRef` to allow for generating compatible
// conversion functions.
impl<'a> conrod_winit::WinitWindow for WindowRef<'a> {
fn get_inner_size(&self) -> Option<(u32, u32)> {
winit::Window::get_inner_size(&self.0).map(Into::into)

View File

@ -1,5 +1,5 @@
/// This macro will automatically load all specified assets, get the corresponding FontIds and
/// create a struct with all of them
/// create a struct with all of them.
///
/// Example usage:
/// ```

View File

@ -59,12 +59,12 @@ impl GraphicCache {
{
match self
.rect_map
.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) //<-------- TODO: Replace this with rounded representation of source
.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
// Allocate rectangle.
let aabr = match self
.atlas
.allocate(size2(i32::from(dims.x), i32::from(dims.y)))
@ -76,13 +76,16 @@ impl GraphicCache {
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
// Out of room.
// TODO: Make more room.
// 1) Expand cache size
// 2) Remove unused allocations
// 3) Rearrange rectangles
None => return None,
};
// Render image
// TODO: use source
// Render image.
// TODO: Use source.
let data = match graphic {
Graphic::Image(ref image) => image
.resize_exact(
@ -99,14 +102,14 @@ impl GraphicCache {
Graphic::Blank => return None,
};
// Draw to allocated area
// Draw to allocated area.
cacher(aabr, data);
// Insert area into map for retrieval
// Insert area into map for retrieval.
self.rect_map
.insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr);
// Return area
// Return area.
Some(aabr)
}
None => None,

View File

@ -109,7 +109,7 @@ pub fn draw_vox(
.map(|p| p.data)
.collect::<Vec<[u8; 4]>>()
} else {
// TODO: remove clone
// TODO: Remove clone.
color.as_ref().to_vec()
}
}
@ -121,7 +121,7 @@ fn ao_level(side1: bool, corner: bool, side2: bool) -> u8 {
3 - [side1, corner, side2].iter().filter(|e| **e).count() as u8
}
}
// TODO: generalize meshing code....
// TODO: Generalize meshing code.
fn create_quad(
origin: Vec3<f32>,
unit_x: Vec3<f32>,
@ -140,7 +140,7 @@ fn create_quad(
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
// Flip to fix anisotropy.
let (a, b, c, d) = if a_ao + c_ao > b_ao + d_ao {
(d, a, b, c)
} else {
@ -163,7 +163,7 @@ fn generate_mesh(segment: &Segment, offs: Vec3<f32>) -> Vec<Vert> {
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
// 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),

View File

@ -57,7 +57,7 @@ impl<'a> GraphicCreator<'a> for VoxelMs9Graphic {
}
/// This macro will automatically load all specified assets, get the corresponding ImgIds and
/// create a struct with all of them
/// create a struct with all of them.
///
/// Example usage:
/// ```

View File

@ -88,7 +88,7 @@ pub struct Ui {
draw_commands: Vec<DrawCommand>,
// Model for drawing the ui
model: DynamicModel<UiPipeline>,
// Stores new window size for updating scaling
// Window size for updating scaling
window_resized: Option<Vec2<f64>>,
// Scaling of the ui
scale: Scale,
@ -110,10 +110,10 @@ impl Ui {
})
}
// Set the scaling mode of the ui
// Set the scaling mode of the ui.
pub fn scaling_mode(&mut self, mode: ScaleMode) {
self.scale.scaling_mode(mode);
// Give conrod the new size
// Give conrod the new size.
let (w, h) = self.scale.scaled_window_size().into_tuple();
self.ui.handle_event(Input::Resize(w, h));
}
@ -134,7 +134,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,
@ -142,12 +142,12 @@ impl Ui {
});
}
// Get id of current widget capturing keyboard
// Get id of current widget capturing keyboard.
pub fn widget_capturing_keyboard(&self) -> Option<WidgId> {
self.ui.global_input().current.widget_capturing_keyboard
}
// Get whether 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()
@ -157,7 +157,7 @@ impl Ui {
.is_none()
}
// Get the widget graph
// Get the widget graph.
pub fn widget_graph(&self) -> &Graph {
self.ui.widget_graph()
}
@ -203,8 +203,8 @@ impl Ui {
self.draw_commands.clear();
let mut mesh = Mesh::new();
// 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
// TODO: this could be removed entirely if the draw call just used both textures,
// however this allows for flexibility if we want to interweave other draw calls later.
enum State {
Image,
Plain,
@ -213,8 +213,8 @@ impl Ui {
let mut current_state = State::Plain;
let mut start = 0;
let window_scizzor = default_scissor(renderer);
let mut current_scizzor = window_scizzor;
let window_scissor = default_scissor(renderer);
let mut current_scissor = window_scissor;
// Switches to the `Plain` state and completes the previous `Command` if not already in the
// `Plain` state.
@ -239,12 +239,12 @@ impl Ui {
..
} = prim;
// Check for a change in the scizzor
let new_scizzor = {
// Check for a change in the scissor.
let new_scissor = {
let (l, b, w, h) = scizzor.l_b_w_h();
// Calculate minimum x and y coordinates while
// - flipping y axis (from +up to +down)
// - moving origin to top-left corner (from middle)
// flipping y axis (from +up to +down) and
// moving origin to top-left corner (from middle).
let min_x = self.ui.win_w / 2.0 + l;
let min_y = self.ui.win_h / 2.0 - b - h;
Aabr {
@ -257,22 +257,22 @@ impl Ui {
y: ((min_y + h) * p_scale_factor) as u16,
},
}
.intersection(window_scizzor)
.intersection(window_scissor)
};
if new_scizzor != current_scizzor {
// Finish the current command
if new_scissor != current_scissor {
// Finish the current command.
self.draw_commands.push(match current_state {
State::Plain => DrawCommand::plain(start..mesh.vertices().len()),
State::Image => DrawCommand::image(start..mesh.vertices().len()),
});
start = mesh.vertices().len();
// Update the scizzor and produce a command.
current_scizzor = new_scizzor;
self.draw_commands.push(DrawCommand::Scissor(new_scizzor));
// Update the scissor and produce a command.
current_scissor = new_scissor;
self.draw_commands.push(DrawCommand::Scissor(new_scissor));
}
// Functions for converting for conrod scalar coords to GL vertex coords (-1.0 to 1.0)
// Functions for converting for conrod scalar coords to GL vertex coords (-1.0 to 1.0).
let ui_win_w = self.ui.win_w;
let ui_win_h = self.ui.win_h;
let vx = |x: f64| (x / ui_win_w * 2.0) as f32;
@ -303,7 +303,7 @@ impl Ui {
_ => {}
}
// Switch to the image state if we are not in it already
// Switch to the image state if we are not in it already.
if let State::Plain = current_state {
self.draw_commands
.push(DrawCommand::plain(start..mesh.vertices().len()));
@ -318,8 +318,8 @@ impl Ui {
(rect.w() * p_scale_factor).round() as u16,
(rect.h() * p_scale_factor).round() as u16,
);
// Transform the source rectangle into uv coordinate
// TODO: make sure this is right
// 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) => {
@ -339,7 +339,7 @@ impl Ui {
let (cache_w, cache_h) =
cache_tex.get_dimensions().map(|e| e as f32).into_tuple();
// Cache graphic at particular resolution
// Cache graphic at particular resolution.
let uv_aabr = match graphic_cache.cache_res(
*graphic_id,
resolution,
@ -371,15 +371,15 @@ impl Ui {
font_id,
} => {
switch_to_plain_state!();
// Get screen width and height
// Get screen width and height.
let (screen_w, screen_h) =
renderer.get_resolution().map(|e| e as f32).into_tuple();
// Calculate dpi factor
// Calculate dpi factor.
let dpi_factor = screen_w / ui_win_w as f32;
let positioned_glyphs = text.positioned_glyphs(dpi_factor);
let (glyph_cache, cache_tex) = self.cache.glyph_cache_mut_and_tex();
// Queue the glyphs to be cached
// Queue the glyphs to be cached.
for glyph in positioned_glyphs {
glyph_cache.queue_glyph(font_id.index(), glyph.clone());
}
@ -424,7 +424,7 @@ impl Ui {
}
PrimitiveKind::Rectangle { color } => {
let color = srgb_to_linear(color.to_fsa().into());
// Don't draw a transparent rectangle
// Don't draw a transparent rectangle.
if color[3] == 0.0 {
continue;
}
@ -442,7 +442,7 @@ impl Ui {
));
}
PrimitiveKind::TrianglesSingleColor { color, triangles } => {
// Don't draw transparent triangle or switch state if there are actually no triangles
// Don't draw transparent triangle or switch state if there are actually no triangles.
let color = srgb_to_linear(Rgba::from(Into::<[f32; 4]>::into(color)));
if triangles.is_empty() || color[3] == 0.0 {
continue;
@ -454,7 +454,7 @@ impl Ui {
let p1 = Vec2::new(vx(tri[0][0]), vy(tri[0][1]));
let p2 = Vec2::new(vx(tri[1][0]), vy(tri[1][1]));
let p3 = Vec2::new(vx(tri[2][0]), vy(tri[2][1]));
// If triangle is clockwise reverse it
// If triangle is clockwise, reverse it.
let (v1, v2): (Vec3<f32>, Vec3<f32>) = ((p2 - p1).into(), (p3 - p1).into());
let triangle = if v1.cross(v2).z > 0.0 {
[p1.into_array(), p2.into_array(), p3.into_array()]
@ -469,49 +469,49 @@ impl Ui {
));
}
}
_ => {} // TODO: Add this
_ => {} // TODO: Add this.
//PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);}
// Other uneeded for now
// Other unneeded for now.
//PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);}
}
}
// Enter the final command
// Enter the final command.
self.draw_commands.push(match current_state {
State::Plain => DrawCommand::plain(start..mesh.vertices().len()),
State::Image => DrawCommand::image(start..mesh.vertices().len()),
});
// create a larger dynamic model if the mesh is larger than the current model size
// Create a larger dynamic model if the mesh is larger than the current model size.
if self.model.vbuf.len() < mesh.vertices().len() {
self.model = renderer
.create_dynamic_model(mesh.vertices().len() * 4 / 3)
.unwrap();
}
renderer.update_model(&self.model, &mesh, 0).unwrap();
// Update model with new mesh
// Update model with new mesh.
// Handle window resizing
// 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));
let res = renderer.get_resolution();
// Avoid panic in graphic cache when minimizing
// Avoid panic in graphic cache when minimizing.
if res.x > 0 && res.y > 0 {
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
// TODO: Probably need to resize glyph cache, see conrod's gfx backend for reference.
}
}
pub fn render(&self, renderer: &mut Renderer) {
let mut scissor = default_scissor(renderer);
let mut scissor_to_render = default_scissor(renderer);
for draw_command in self.draw_commands.iter() {
match draw_command {
DrawCommand::Scissor(scizzor) => {
scissor = *scizzor;
DrawCommand::Scissor(scissor) => {
scissor_to_render = *scissor;
}
DrawCommand::Draw { kind, verts } => {
let tex = match kind {
@ -519,7 +519,7 @@ impl Ui {
DrawKind::Plain => self.cache.glyph_cache_tex(),
};
let model = self.model.submodel(verts.clone());
renderer.render_ui_element(&model, &tex, scissor);
renderer.render_ui_element(&model, &tex, scissor_to_render);
}
}
}

View File

@ -1,19 +1,18 @@
use crate::{render::Renderer, window::Window};
use vek::*;
// How the ui is scaled
/// Type of scaling to use.
pub enum ScaleMode {
// Scale against physical size
// Scale against physical size.
Absolute(f64),
// Use the dpi factor provided by the windowing system (i.e. use logical size)
// Use the dpi factor provided by the windowing system (i.e. use logical size).
DpiFactor,
// Scale based on the window's physical size, but maintain aspect ratio of widgets
// Contains width and height of the "default" window size (ie where there should be no scaling)
// Scale based on the window's physical size, but maintain aspect ratio of widgets.
// Contains width and height of the "default" window size (ie where there should be no scaling).
RelativeToWindow(Vec2<f64>),
}
pub struct Scale {
// Type of scaling to use
mode: ScaleMode,
// Current dpi factor
dpi_factor: f64,
@ -31,11 +30,11 @@ impl Scale {
window_dims,
}
}
// Change the scaling mode
// Change the scaling mode.
pub fn scaling_mode(&mut self, mode: ScaleMode) {
self.mode = mode;
}
// Calculate factor to transform between logical coordinates and our scaled coordinates
// Calculate factor to transform between logical coordinates and our scaled coordinates.
pub fn scale_factor_logical(&self) -> f64 {
match self.mode {
ScaleMode::Absolute(scale) => scale / self.dpi_factor,
@ -45,20 +44,20 @@ impl Scale {
}
}
}
// Calculate factor to transform between physical coordinates and our scaled coordinates
// Calculate factor to transform between physical coordinates and our scaled coordinates.
pub fn scale_factor_physical(&self) -> f64 {
self.scale_factor_logical() * self.dpi_factor
}
// Updates internal window size (and/or dpi_factor)
// Updates internal window size (and/or dpi_factor).
pub fn window_resized(&mut self, new_dims: Vec2<f64>, renderer: &Renderer) {
self.dpi_factor = renderer.get_resolution().x as f64 / new_dims.x;
self.window_dims = new_dims;
}
// Get scaled window size
// Get scaled window size.
pub fn scaled_window_size(&self) -> Vec2<f64> {
self.window_dims / self.scale_factor_logical()
}
// Transform point from logical to scaled coordinates
// Transform point from logical to scaled coordinates.
pub fn scale_point(&self, point: Vec2<f64>) -> Vec2<f64> {
point / self.scale_factor_logical()
}

View File

@ -17,7 +17,7 @@ pub trait ValueFromPercent<T> {
/// Linear value selection.
///
/// If the slider's width is greater than it's height, it will automatically become a horizontal
/// If the slider's width is greater than its height, it will automatically become a horizontal
/// slider, otherwise it will be a vertical slider.
///
/// Its reaction is triggered if the value is updated or if the mouse button is released while
@ -31,9 +31,9 @@ pub struct ImageSlider<T, K> {
max: T,
/// The amount in which the slider's display should be skewed.
///
/// Higher skew amounts (above 1.0) will weight lower values.
/// Higher skew amounts (above 1.0) will weigh lower values.
///
/// Lower skew amounts (below 1.0) will weight heigher values.
/// Lower skew amounts (below 1.0) will weigh higher values.
///
/// All skew amounts should be greater than 0.0.
skew: f32,
@ -47,7 +47,7 @@ struct Track {
color: Option<Color>,
src_rect: Option<Rect>,
breadth: Option<f32>,
// Padding on the ends of the track constraining the slider to a smaller area
// Padding on the ends of the track constraining the slider to a smaller area.
padding: (f32, f32),
}
@ -202,13 +202,13 @@ where
if mouse.buttons.left().is_down() {
let mouse_abs_xy = mouse.abs_xy();
let (mouse_offset, track_length) = if is_horizontal {
// Horizontal.
// Horizontal
(
mouse_abs_xy[0] - rect.x.start - start_pad,
rect.w() - start_pad - end_pad,
)
} else {
// Vertical.
// Vertical
(
mouse_abs_xy[1] - rect.y.start - start_pad,
rect.h() - start_pad - end_pad,
@ -264,7 +264,7 @@ where
})
.unwrap_or(slider.image_id);
// The rectangle for positioning and sizing the slider.
// A rectangle for positioning and sizing the slider.
let value_perc = utils::map_range(new_value, min, max, 0.0, 1.0);
let unskewed_perc = value_perc.powf(1.0 / skew as f64);
let slider_rect = if is_horizontal {

View File

@ -105,8 +105,10 @@ impl Widget for ToggleButton {
t_image,
..
} = self;
// Check if button was clicked
// (can't use .set().was_clicked() because we are changing the image and this is after setting the widget which causes flickering as it takes a frame to change after the mouse button is lifted)
// Check if the button was clicked.
// (Can't use `.set().was_clicked()` because we are changing the image after setting the
// widget, which causes flickering since it takes a frame to change after the mouse button
// is lifted).
if ui.widget_input(state.ids.button).clicks().left().count() % 2 == 1 {
value = !value;
}

View File

@ -85,15 +85,15 @@ impl Window {
self.needs_refresh_resize = false;
}
// Copy data that is needed by the events closure to avoid lifetime errors
// TODO: Remove this if/when the compiler permits it
// Copy data that is needed by the events closure to avoid lifetime errors.
// TODO: Remove this if/when the compiler permits it.
let cursor_grabbed = self.cursor_grabbed;
let renderer = &mut self.renderer;
let window = &mut self.window;
let key_map = &self.key_map;
self.events_loop.poll_events(|event| {
// Get events for ui
// Get events for ui.
if let Some(event) = ui::Event::try_from(event.clone(), &window) {
events.push(Event::Ui(event));
}
@ -174,7 +174,7 @@ impl Window {
}
}
/// Represents a key that the game recognises after keyboard mapping
/// Represents a key that the game recognises after keyboard mapping.
#[derive(Clone, Copy)]
pub enum Key {
ToggleCursor,
@ -197,12 +197,12 @@ pub enum Key {
Help,
}
/// Represents an incoming event from the window
/// Represents an incoming event from the window.
#[derive(Clone)]
pub enum Event {
/// The window has been requested to close.
Close,
/// The window has been resized
/// The window has been resized.
Resize(Vec2<u32>),
/// A key has been typed that corresponds to a specific character.
Char(char),
@ -210,12 +210,12 @@ pub enum Event {
CursorPan(Vec2<f32>),
/// The camera has been requested to zoom.
Zoom(f32),
/// A key that the game recognises has been pressed down
/// A key that the game recognises has been pressed down.
KeyDown(Key),
/// A key that the game recognises has been released down
/// A key that the game recognises has been released down.
KeyUp(Key),
/// Event that the ui uses
/// Event that the ui uses.
Ui(ui::Event),
/// Game settings have changed
/// Game settings have changed.
SettingsChanged,
}

View File

@ -21,7 +21,7 @@ impl World {
}
pub fn generate_chunk(chunk_pos: Vec2<i32>) -> TerrainChunk {
// TODO: This is all test code, remove/improve this later
// TODO: This is all test code, remove/improve this later.
let air = Block::empty();
let stone = Block::new(1, Rgb::new(200, 220, 255));