From c95e07db3b4dcca285678985e65e31b927cb1c61 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Thu, 20 Aug 2020 05:46:22 +0200 Subject: [PATCH] Address MR feedback, fix scene clouds. --- Cargo.lock | 4 +- common/Cargo.toml | 2 +- common/src/typed.rs | 116 +++++++++++++++++++++++++ voxygen/src/menu/char_selection/mod.rs | 1 + voxygen/src/scene/simple.rs | 5 +- 5 files changed, 123 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fea4b6344b..259543ab2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3560,9 +3560,9 @@ dependencies = [ [[package]] name = "roots" -version = "0.0.5" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c67c712ab62be58b24ab8960e2b95dd4ee00aac115c76f2709657821fe376d" +checksum = "84348444bd7ad45729d0c49a4240d7cdc11c9d512c06c5ad1835c1ad4acda6db" [[package]] name = "route-recognizer" diff --git a/common/Cargo.toml b/common/Cargo.toml index d33a938f3b..d9467ee3dc 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -11,7 +11,7 @@ no-assets = [] arraygen = "0.1.13" specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "specs-git" } -roots = "0.0.5" +roots = "0.0.6" specs = { git = "https://github.com/amethyst/specs.git", features = ["serde", "storage-event-control"], rev = "7a2e348ab2223818bad487695c66c43db88050a5" } vek = { version = "0.12.0", features = ["platform_intrinsics", "serde"] } dot_vox = "4.0" diff --git a/common/src/typed.rs b/common/src/typed.rs index 7c67bba295..395ee75548 100644 --- a/common/src/typed.rs +++ b/common/src/typed.rs @@ -22,6 +22,122 @@ impl, T, S> Typed, S> for T { fn reduce(self, context: Context) -> (Pure, S) { (Pure(self), context.sub_context()) } } +/// A lazy pattern match reified as a Rust type. +/// +/// `expr` is the expression being matched on, generally of some enum type `Ty`. +/// +/// `case` represents the pattenrn match--it will generally be a stsructure with +/// one field per constructor in `Ty`. The field should contain enough +/// information to run the match arm for that constructor, given the information +/// contained in the constructor arguments. +/// +/// `ty` represents the return type of the match expression. It does not carry +/// any runtime-relevant information, but is needed in order to simplify our +/// trait definitions. +/// +/// The intent is that you should not construct this structure directly, nor +/// should you define or construct the `Cases` structure directly. Instead, to +/// use this you are expected to wrap your enum declaration in a call to +/// [make_case_elim!], as follows: +/// +/// ``` +/// make_case_elim!( +/// my_type_module, +/// #[repr(u32)] +/// #[derive(Clone,Copy,OtherAttribs)] +/// pub enum MyType { +/// Constr1 = 0, +/// Constr2(arg : ArgType) = 1, +/// /* ..., */ +/// } +/// ); +/// ``` +/// +/// This macro automatically does a few things. First, it creates the `enum` +/// type `MyType` in the current scope, as expected. Second, it creates a +/// module named `my_type_module` in the current scope, into which it dumps a +/// few things. In this case: +/// +/// ``` +/// #[repr(u32)] +/// #[derive(Clone,Copy,OtherAttribs)] +/// pub enum MyType { +/// Constr1 = 0, +/// Constr2(arg : ArgType) = 1, +/// /* ..., */ +/// } +/// +/// mod make_case_elim { +/// use ::serde::{Deserialize, Serialize}; +/// +/// /// The number of variants in this enum. +/// pub const NUM_VARIANTS: usize = 2; +/// +/// /// An array of all the variant indices (in theory, this can be used by this or other +/// /// macros in order to easily build up things like uniform random samplers). +/// pub const ALL_INDICES: [u32; NUM_VARIANTS] = [ 0, 1 ]; +/// +/// /// A convenience trait used to store a different type for each constructor in this +/// /// pattern. +/// pub trait PackedElim { +/// type Constr1; +/// type Constr2; +/// } +/// +/// /// The actual *cases.* If you think of pattern match arms as being closures that accept +/// /// the cconstructor types as arguments, you can think of this structure as somehow +/// /// representing just the data *owned* by the closure. This is also what you will +/// /// generally store in your ron file--it has a field for each constructor of your enum, +/// /// with the types of all the fields specified by the implementation of [PackedElim] for +/// /// the [Elim] argument. Each field has the same name as the constructor it represents. +/// #[derive(Serialize, Deserialize)] +/// pub struct Cases { +/// pub constr: Elim::Constr1, +/// pub constr: Elim::Constr2, +/// } +/// +/// /// Finally, because it represents by an overwhelming margin the most common usecase, we +/// /// predefine a particular pattern matching strategy--"pure"--where every arm holds data of +/// /// the exact same type, T. +/// impl PackedElim for typed::Pure { +/// type Constr1 = T; +/// type Constr2 = T; +/// } +/// +/// /// Because PureCases is so convenient, we have an alias for it. Thus, in order to +/// /// represent a pattern match on an argument that returns a constant of type (u8,u8,u8) for +/// /// each arm, you'd use the type `PureCases<(u8, u8, u8)>`. +/// pub type PureCases = Cases<$crate::typed::Pure>; +/// } +/// ``` +/// +/// Finally, a useful implementation of the [Typed] trait completes this story, +/// providing a way to evaluate this lazy math statement within Rust. +/// Unfortunately, [Typed] is quite complicated, and this story is still being +/// fully evaluated, so showing teh type may not be that elucidating. +/// Instead, we'll just present the method you can use most easily to pattern +/// match using the PureCases pattern we mentioned earlier: +/// +/// pub fn elim_case_pure<'a, Type>(&'a self, cases: &'a $mod::PureCases) +/// -> &'a Type +/// +/// If self is expression of your defined enum type, and match data defined by +/// PureCases, this evaluates the pattern match on self and returns the matched +/// case. +/// +/// To see how this is used in more detail, check out +/// `common/src/body/humanoid.rs`; it is also used extensively in the world +/// repository. +/// +/// --- +/// +/// Limitations: +/// +/// Unfortunately, due to restrictions on procedural macros, we currently always +/// require the types defined to #[repr(inttype)] as you can see above. There +/// are also some other current limitations that we hopefully will be able to +/// lift at some point; struct variants are not yet supported, and neither +/// attributes on fields. #[fundamental] pub struct ElimCase { pub expr: Expr, diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 59d88b56ed..2edbc0f330 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -28,6 +28,7 @@ impl CharSelectionState { let scene = Scene::new( global_state.window.renderer_mut(), Some("fixture.selection_bg"), + &*client.borrow(), ); Self { char_selection_ui: CharSelectionUi::new(global_state), diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 8771fac83b..785b8a6784 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -17,6 +17,7 @@ use anim::{ fixture::FixtureSkeleton, Animation, }; +use client::Client; use common::{ comp::{humanoid, item::ItemKind, Body, Loadout}, figure::Segment, @@ -97,11 +98,11 @@ pub struct SceneData { } impl Scene { - pub fn new(renderer: &mut Renderer, backdrop: Option<&str>) -> Self { + pub fn new(renderer: &mut Renderer, backdrop: Option<&str>, client: &Client) -> Self { let start_angle = 90.0f32.to_radians(); let resolution = renderer.get_resolution().map(|e| e as f32); - let map_bounds = Vec2::new(-65536.0, 131071.0); + let map_bounds = client.world_map.2; let map_border = [0.0, 0.0, 0.0, 0.0]; let map_image = [0]; let alt_image = [0];