path normalization

This commit is contained in:
Robin Appelman 2023-12-19 17:48:32 +01:00
commit 0683c4f4f2
11 changed files with 112 additions and 39 deletions

View file

@ -1,13 +1,14 @@
use super::deserialize_path;
use crate::{default_scale, Vec3}; use crate::{default_scale, Vec3};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EyeRefractMaterial { pub struct EyeRefractMaterial {
/// Usually referred to as a "sludge-layer", acts as a layer on top of the surface of the $AboveWater Material. /// Usually referred to as a "sludge-layer", acts as a layer on top of the surface of the $AboveWater Material.
#[serde(rename = "$iris")] #[serde(rename = "$iris", deserialize_with = "deserialize_path")]
pub iris: String, pub iris: String,
/// A texture to specify the shape of the cornea, similar to a normal map. Influences lighting and dilation. The red and green channels are used for the normal mapping, the blue channel is a mask for parallax mapping (straight multiply), and the alpha channel seems to be a multiplier for lighting. Because the $iris is warped in various ways the normals will not match 1-to-1 with the base texture. /// A texture to specify the shape of the cornea, similar to a normal map. Influences lighting and dilation. The red and green channels are used for the normal mapping, the blue channel is a mask for parallax mapping (straight multiply), and the alpha channel seems to be a multiplier for lighting. Because the $iris is warped in various ways the normals will not match 1-to-1 with the base texture.
#[serde(rename = "$corneatexture")] #[serde(rename = "$corneatexture", deserialize_with = "deserialize_path")]
pub cornea_texture: String, pub cornea_texture: String,
/// Strength of the $corneatexture. /// Strength of the $corneatexture.
#[serde(rename = "$corneabumpstrength", default = "default_scale")] #[serde(rename = "$corneabumpstrength", default = "default_scale")]
@ -20,17 +21,17 @@ pub struct EyeRefractMaterial {
pub dilation: f32, pub dilation: f32,
/// 1-dimensional texture which remaps lighting colors. /// 1-dimensional texture which remaps lighting colors.
#[serde(rename = "$lightwarptexture")] #[serde(rename = "$lightwarptexture", deserialize_with = "deserialize_path")]
pub light_warp_texture: String, pub light_warp_texture: String,
/// Enables cubemap reflections. This shader has a specific cubemap made for it, engine/eye-reflection-cubemap-.vtf, but others can be used, including env_cubemap. /// Enables cubemap reflections. This shader has a specific cubemap made for it, engine/eye-reflection-cubemap-.vtf, but others can be used, including env_cubemap.
#[serde(rename = "$envmap")] #[serde(rename = "$envmap", deserialize_with = "deserialize_path")]
pub env_map: String, pub env_map: String,
/// The opacity of the cubemap reflection. Does not affect the eye glint. Default 0.5. /// The opacity of the cubemap reflection. Does not affect the eye glint. Default 0.5.
#[serde(rename = "$glossiness", default = "default_dilation")] #[serde(rename = "$glossiness", default = "default_dilation")]
pub glossiness: f32, pub glossiness: f32,
/// An ambient occlusion texture overlaid onto the entire eye /// An ambient occlusion texture overlaid onto the entire eye
#[serde(rename = "$ambientoccltexture")] #[serde(rename = "$ambientoccltexture", deserialize_with = "deserialize_path")]
pub ambient_occlusion_texture: String, pub ambient_occlusion_texture: String,
/// Tints the $ambientoccltexture /// Tints the $ambientoccltexture
#[serde(rename = "$ambientocclcolor", default = "default_occl_color")] #[serde(rename = "$ambientocclcolor", default = "default_occl_color")]

View file

@ -1,3 +1,4 @@
use super::deserialize_path;
use crate::{ use crate::{
default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3, default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3,
}; };
@ -6,16 +7,16 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LightMappedGenericMaterial { pub struct LightMappedGenericMaterial {
/// Defines an albedo texture. /// Defines an albedo texture.
#[serde(rename = "$basetexture")] #[serde(rename = "$basetexture", deserialize_with = "deserialize_path")]
pub base_texture: String, pub base_texture: String,
/// Use this material as a decal. /// Use this material as a decal.
#[serde(rename = "$decal", default)] #[serde(rename = "$decal", default)]
pub decal: bool, pub decal: bool,
/// Detail texturing. /// Detail texturing.
#[serde(rename = "$detail")] #[serde(rename = "$detail", default, deserialize_with = "deserialize_path")]
pub detail: Option<String>, pub detail: Option<String>,
/// Links the surface to a set of physical properties. /// Links the surface to a set of physical properties.
#[serde(rename = "$surfaceprop")] #[serde(rename = "$surfaceprop", default)]
pub surface_prop: Option<String>, pub surface_prop: Option<String>,
/// Transforms the texture before use in the material. This does not affect lightmaps on the surface. /// Transforms the texture before use in the material. This does not affect lightmaps on the surface.
@ -37,7 +38,11 @@ pub struct LightMappedGenericMaterial {
#[serde(rename = "$detailblendmode", default)] #[serde(rename = "$detailblendmode", default)]
pub detail_blend_mode: BlendMode, pub detail_blend_mode: BlendMode,
/// A separate VertexLitGeneric material to that will replace this one if the decal hits a model. /// A separate VertexLitGeneric material to that will replace this one if the decal hits a model.
#[serde(rename = "$modelmaterial", default)] #[serde(
rename = "$modelmaterial",
default,
deserialize_with = "deserialize_path"
)]
pub model_material: Option<String>, pub model_material: Option<String>,
/// Disables texture filtering. /// Disables texture filtering.
#[serde(rename = "$pointsamplemagfilter", default)] #[serde(rename = "$pointsamplemagfilter", default)]
@ -66,10 +71,14 @@ pub struct LightMappedGenericMaterial {
pub translucent: bool, pub translucent: bool,
/// Specifies a texture that will provide three-dimensional lighting information for a material. /// Specifies a texture that will provide three-dimensional lighting information for a material.
#[serde(rename = "$bumpmap")] #[serde(rename = "$bumpmap", deserialize_with = "deserialize_path")]
pub bump_map: Option<String>, pub bump_map: Option<String>,
/// Per-texel color modification via a warp texture. /// Per-texel color modification via a warp texture.
#[serde(rename = "$lightwarptexture")] #[serde(
rename = "$lightwarptexture",
default,
deserialize_with = "deserialize_path"
)]
pub light_wrap_texture: Option<String>, pub light_wrap_texture: Option<String>,
/// Determines whether the surface is self-illuminated independent of environment lighting. /// Determines whether the surface is self-illuminated independent of environment lighting.
#[serde(rename = "$selfillum", default)] #[serde(rename = "$selfillum", default)]
@ -79,7 +88,7 @@ pub struct LightMappedGenericMaterial {
pub ss_bump: bool, pub ss_bump: bool,
/// Specular reflections. /// Specular reflections.
#[serde(rename = "$envmap")] #[serde(rename = "$envmap", default, deserialize_with = "deserialize_path")]
pub env_map: Option<String>, pub env_map: Option<String>,
/// Diffuse reflections. /// Diffuse reflections.
#[serde(rename = "$phong", default)] #[serde(rename = "$phong", default)]

View file

@ -7,7 +7,7 @@ mod worldvertextransition;
pub use eyerefract::EyeRefractMaterial; pub use eyerefract::EyeRefractMaterial;
pub use lightmappedgeneric::LightMappedGenericMaterial; pub use lightmappedgeneric::LightMappedGenericMaterial;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
pub use unlitgeneric::UnlitGenericMaterial; pub use unlitgeneric::UnlitGenericMaterial;
use vdf_reader::entry::{Entry, Table}; use vdf_reader::entry::{Entry, Table};
use vdf_reader::error::UnknownError; use vdf_reader::error::UnknownError;
@ -157,3 +157,26 @@ impl PatchMaterial {
Ok(from_entry(Entry::Table(material))?) Ok(from_entry(Entry::Table(material))?)
} }
} }
trait PathLike {
fn normalize(self) -> Self;
}
impl PathLike for String {
fn normalize(self) -> Self {
self.replace('\\', "/")
}
}
impl<T: PathLike> PathLike for Option<T> {
fn normalize(self) -> Self {
self.map(T::normalize)
}
}
/// Deserialize string and convert windows \ path separators to /
fn deserialize_path<'de, T: PathLike + Deserialize<'de>, D: Deserializer<'de>>(
deserializer: D,
) -> Result<T, D::Error> {
Ok(T::deserialize(deserializer)?.normalize())
}

View file

@ -1,13 +1,14 @@
use super::deserialize_path;
use crate::{default_scale, default_scale3, Vec3}; use crate::{default_scale, default_scale3, Vec3};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnlitGenericMaterial { pub struct UnlitGenericMaterial {
/// Defines an albedo texture. /// Defines an albedo texture.
#[serde(rename = "$basetexture")] #[serde(rename = "$basetexture", deserialize_with = "deserialize_path")]
pub base_texture: String, pub base_texture: String,
/// Links the surface to a set of physical properties. /// Links the surface to a set of physical properties.
#[serde(rename = "$surfaceprop")] #[serde(rename = "$surfaceprop", default)]
pub surface_prop: Option<String>, pub surface_prop: Option<String>,
/// Tells this material is used for models and not brushes. /// Tells this material is used for models and not brushes.
#[serde(rename = "$model", default)] #[serde(rename = "$model", default)]
@ -34,7 +35,7 @@ pub struct UnlitGenericMaterial {
pub translucent: bool, pub translucent: bool,
/// Specifies a texture that will provide three-dimensional lighting information for a material. /// Specifies a texture that will provide three-dimensional lighting information for a material.
#[serde(rename = "$bumpmap")] #[serde(rename = "$bumpmap", default, deserialize_with = "deserialize_path")]
pub bump_map: Option<String>, pub bump_map: Option<String>,
/// Ignore z filtering /// Ignore z filtering

View file

@ -1,3 +1,4 @@
use super::deserialize_path;
use crate::{ use crate::{
default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3, default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3,
}; };
@ -6,13 +7,17 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VertexLitGenericMaterial { pub struct VertexLitGenericMaterial {
/// Defines an albedo texture. /// Defines an albedo texture.
#[serde(rename = "$basetexture")] #[serde(rename = "$basetexture", deserialize_with = "deserialize_path")]
pub base_texture: String, pub base_texture: String,
/// Detail texturing. /// Detail texturing.
#[serde(rename = "$detail")] #[serde(rename = "$detail", default, deserialize_with = "deserialize_path")]
pub detail: Option<String>, pub detail: Option<String>,
/// Use a 2nd UV channel for high-resolution decal support. /// Use a 2nd UV channel for high-resolution decal support.
#[serde(rename = "$decaltexture")] #[serde(
rename = "$decaltexture",
default,
deserialize_with = "deserialize_path"
)]
pub decal_texture: Option<String>, pub decal_texture: Option<String>,
/// Color tinting /// Color tinting
@ -34,7 +39,11 @@ pub struct VertexLitGenericMaterial {
#[serde(rename = "$detailblendmode", default)] #[serde(rename = "$detailblendmode", default)]
pub detail_blend_mode: BlendMode, pub detail_blend_mode: BlendMode,
/// A separate VertexLitGeneric material to that will replace this one if the decal hits a model. /// A separate VertexLitGeneric material to that will replace this one if the decal hits a model.
#[serde(rename = "$modelmaterial", default)] #[serde(
rename = "$modelmaterial",
default,
deserialize_with = "deserialize_path"
)]
pub model_material: Option<String>, pub model_material: Option<String>,
/// Disables texture filtering. /// Disables texture filtering.
#[serde(rename = "$pointsamplemagfilter", default)] #[serde(rename = "$pointsamplemagfilter", default)]
@ -63,10 +72,14 @@ pub struct VertexLitGenericMaterial {
pub translucent: bool, pub translucent: bool,
/// Specifies a texture that will provide three-dimensional lighting information for a material. /// Specifies a texture that will provide three-dimensional lighting information for a material.
#[serde(rename = "$bumpmap")] #[serde(rename = "$bumpmap", default, deserialize_with = "deserialize_path")]
pub bump_map: Option<String>, pub bump_map: Option<String>,
/// Per-texel color modification via a warp texture. /// Per-texel color modification via a warp texture.
#[serde(rename = "$lightwarptexture")] #[serde(
rename = "$lightwarptexture",
default,
deserialize_with = "deserialize_path"
)]
pub light_wrap_texture: Option<String>, pub light_wrap_texture: Option<String>,
/// Determines whether the surface is self-illuminated independent of environment lighting. /// Determines whether the surface is self-illuminated independent of environment lighting.
#[serde(rename = "$selfillum", default)] #[serde(rename = "$selfillum", default)]
@ -76,7 +89,7 @@ pub struct VertexLitGenericMaterial {
pub ss_bump: bool, pub ss_bump: bool,
/// Specular reflections. /// Specular reflections.
#[serde(rename = "$envmap")] #[serde(rename = "$envmap", default, deserialize_with = "deserialize_path")]
pub env_map: Option<String>, pub env_map: Option<String>,
/// Diffuse reflections. /// Diffuse reflections.
#[serde(rename = "$phong", default)] #[serde(rename = "$phong", default)]

View file

@ -1,25 +1,34 @@
use super::deserialize_path;
use crate::{default_scale, default_scale3, TextureTransform, Vec3}; use crate::{default_scale, default_scale3, TextureTransform, Vec3};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WaterMaterial { pub struct WaterMaterial {
/// Usually referred to as a "sludge-layer", acts as a layer on top of the surface of the $AboveWater Material. /// Usually referred to as a "sludge-layer", acts as a layer on top of the surface of the $AboveWater Material.
#[serde(rename = "$basetexture")] #[serde(rename = "$basetexture", deserialize_with = "deserialize_path")]
pub base_texture: String, pub base_texture: String,
/// Tells this material is used for models and not brushes. /// Tells this material is used for models and not brushes.
#[serde(rename = "$abovewater", default)] #[serde(rename = "$abovewater", default)]
pub above_water: bool, pub above_water: bool,
/// Required parameter. This is the material (not texture) to use when underneath the waters surface. The bottom material must have $reflecttexture, $abovewater and $envmap disabled, but can otherwise do whatever it wants. /// Required parameter. This is the material (not texture) to use when underneath the waters surface. The bottom material must have $reflecttexture, $abovewater and $envmap disabled, but can otherwise do whatever it wants.
#[serde(rename = "$bottommaterial")] #[serde(
rename = "$bottommaterial",
default,
deserialize_with = "deserialize_path"
)]
pub bottom_material: Option<String>, pub bottom_material: Option<String>,
/// Applies a refracting screen overlay when the camera is underwater. Generally used with effects\water_warp01. Requires $abovewater to be 0. /// Applies a refracting screen overlay when the camera is underwater. Generally used with effects\water_warp01. Requires $abovewater to be 0.
#[serde(rename = "$underwaterover")] #[serde(
rename = "$underwaterover",
default,
deserialize_with = "deserialize_path"
)]
pub underwater_overlay: Option<String>, pub underwater_overlay: Option<String>,
/// Specifies a texture that will provide three-dimensional lighting information for a material for DX8. /// Specifies a texture that will provide three-dimensional lighting information for a material for DX8.
#[serde(rename = "$bumpmap")] #[serde(rename = "$bumpmap", default, deserialize_with = "deserialize_path")]
pub bump_map: Option<String>, pub bump_map: Option<String>,
/// A Du/dv map for DirectX 8 rendering ($bumpmap), and a bump map for DirectX 9 and above ($normalmap). /// A Du/dv map for DirectX 8 rendering ($bumpmap), and a bump map for DirectX 9 and above ($normalmap).
#[serde(rename = "$normalmap")] #[serde(rename = "$normalmap", default, deserialize_with = "deserialize_path")]
pub normal_map: Option<String>, pub normal_map: Option<String>,
#[serde(rename = "$dudvframe", default)] #[serde(rename = "$dudvframe", default)]
pub du_dv_frame: u32, pub du_dv_frame: u32,

View file

@ -1,3 +1,4 @@
use super::deserialize_path;
use crate::{ use crate::{
default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3, default_detail_scale, default_scale, default_scale3, BlendMode, TextureTransform, Vec2, Vec3,
}; };
@ -6,22 +7,25 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorldVertexTransitionMaterial { pub struct WorldVertexTransitionMaterial {
/// The first texture in the blend. /// The first texture in the blend.
#[serde(rename = "$basetexture")] #[serde(rename = "$basetexture", deserialize_with = "deserialize_path")]
pub base_texture: String, pub base_texture: String,
/// The second texture to blend to. /// The second texture to blend to.
#[serde(rename = "$basetexture2")] #[serde(rename = "$basetexture2", deserialize_with = "deserialize_path")]
pub base_texture2: String, pub base_texture2: String,
/// Modulate the blending between materials using a special texture. /// Modulate the blending between materials using a special texture.
#[serde(rename = "$blendmodulatetexture")] #[serde(
rename = "$blendmodulatetexture",
deserialize_with = "deserialize_path"
)]
pub blend_modulate_texture: Option<String>, pub blend_modulate_texture: Option<String>,
/// Use this material as a decal. /// Use this material as a decal.
#[serde(rename = "$decal", default)] #[serde(rename = "$decal", default)]
pub decal: bool, pub decal: bool,
/// Detail texturing. /// Detail texturing.
#[serde(rename = "$detail")] #[serde(rename = "$detail", default)]
pub detail: Option<String>, pub detail: Option<String>,
/// Links the surface to a set of physical properties. /// Links the surface to a set of physical properties.
#[serde(rename = "$surfaceprop")] #[serde(rename = "$surfaceprop", default)]
pub surface_prop: Option<String>, pub surface_prop: Option<String>,
/// Transforms the texture before use in the material. This does not affect lightmaps on the surface. /// Transforms the texture before use in the material. This does not affect lightmaps on the surface.
@ -43,7 +47,11 @@ pub struct WorldVertexTransitionMaterial {
#[serde(rename = "$detailblendmode", default)] #[serde(rename = "$detailblendmode", default)]
pub detail_blend_mode: BlendMode, pub detail_blend_mode: BlendMode,
/// A separate VertexLitGeneric material to that will replace this one if the decal hits a model. /// A separate VertexLitGeneric material to that will replace this one if the decal hits a model.
#[serde(rename = "$modelmaterial", default)] #[serde(
rename = "$modelmaterial",
default,
deserialize_with = "deserialize_path"
)]
pub model_material: Option<String>, pub model_material: Option<String>,
/// Disables texture filtering. /// Disables texture filtering.
#[serde(rename = "$pointsamplemagfilter", default)] #[serde(rename = "$pointsamplemagfilter", default)]
@ -72,13 +80,17 @@ pub struct WorldVertexTransitionMaterial {
pub translucent: bool, pub translucent: bool,
/// bumpmap for the first texture. /// bumpmap for the first texture.
#[serde(rename = "$bumpmap")] #[serde(rename = "$bumpmap", default, deserialize_with = "deserialize_path")]
pub bump_map: Option<String>, pub bump_map: Option<String>,
/// bumpmap for the second texture. /// bumpmap for the second texture.
#[serde(rename = "$bumpmap2")] #[serde(rename = "$bumpmap2", default, deserialize_with = "deserialize_path")]
pub bump_map2: Option<String>, pub bump_map2: Option<String>,
/// Per-texel color modification via a warp texture. /// Per-texel color modification via a warp texture.
#[serde(rename = "$lightwarptexture")] #[serde(
rename = "$lightwarptexture",
default,
deserialize_with = "deserialize_path"
)]
pub light_wrap_texture: Option<String>, pub light_wrap_texture: Option<String>,
/// Determines whether the surface is self-illuminated independent of environment lighting. /// Determines whether the surface is self-illuminated independent of environment lighting.
#[serde(rename = "$selfillum", default)] #[serde(rename = "$selfillum", default)]
@ -88,7 +100,7 @@ pub struct WorldVertexTransitionMaterial {
pub ss_bump: bool, pub ss_bump: bool,
/// Specular reflections. /// Specular reflections.
#[serde(rename = "$envmap")] #[serde(rename = "$envmap", default, deserialize_with = "deserialize_path")]
pub env_map: Option<String>, pub env_map: Option<String>,
/// Diffuse reflections. /// Diffuse reflections.
#[serde(rename = "$phong", default)] #[serde(rename = "$phong", default)]

View file

@ -20,6 +20,7 @@ worldvertextransition(WorldVertexTransitionMaterial(
r#$seamless_scale: 1.0, r#$seamless_scale: 1.0,
r#$alpha: 1.0, r#$alpha: 1.0,
r#$alphatest: false, r#$alphatest: false,
r#$alphatestreference: 1.0,
r#$distancealpha: false, r#$distancealpha: false,
r#$nocull: false, r#$nocull: false,
r#$translucent: false, r#$translucent: false,

View file

@ -18,6 +18,7 @@ lightmappedgeneric(LightMappedGenericMaterial(
r#$seamless_scale: 1.0, r#$seamless_scale: 1.0,
r#$alpha: 1.0, r#$alpha: 1.0,
r#$alphatest: false, r#$alphatest: false,
r#$alphatestreference: 1.0,
r#$distancealpha: false, r#$distancealpha: false,
r#$nocull: false, r#$nocull: false,
r#$translucent: false, r#$translucent: false,

View file

@ -3,14 +3,16 @@ source: tests/parse.rs
expression: result expression: result
--- ---
unlitgeneric(UnlitGenericMaterial( unlitgeneric(UnlitGenericMaterial(
r#$basetexture: "vgui\\pve\\mvm_backpack", r#$basetexture: "vgui/pve/mvm_backpack",
r#$surfaceprop: None, r#$surfaceprop: None,
r#$model: false, r#$model: false,
r#$color: Vec3((1.0, 1.0, 1.0)), r#$color: Vec3((1.0, 1.0, 1.0)),
r#$alpha: 1.0, r#$alpha: 1.0,
r#$alphatest: false, r#$alphatest: false,
r#$alphatestreference: 1.0,
r#$nocull: false, r#$nocull: false,
r#$translucent: true, r#$translucent: true,
r#$bumpmap: None,
r#$ignorez: true, r#$ignorez: true,
r#$nofog: false, r#$nofog: false,
r#$receiveflashlight: false, r#$receiveflashlight: false,

View file

@ -18,6 +18,7 @@ lightmappedgeneric(LightMappedGenericMaterial(
r#$seamless_scale: 1.0, r#$seamless_scale: 1.0,
r#$alpha: 1.0, r#$alpha: 1.0,
r#$alphatest: false, r#$alphatest: false,
r#$alphatestreference: 1.0,
r#$distancealpha: false, r#$distancealpha: false,
r#$nocull: false, r#$nocull: false,
r#$translucent: false, r#$translucent: false,