Struct bevy::render::mesh::morph::MorphWeights
pub struct MorphWeights { /* private fields */ }
Expand description
Controls the morph targets for all child Handle<Mesh>
entities. In most cases, MorphWeights
should be considered
the “source of truth” when writing morph targets for meshes. However you can choose to write child MeshMorphWeights
if your situation requires more granularity. Just note that if you set MorphWeights
, it will overwrite child
MeshMorphWeights
values.
This exists because Bevy’s Mesh
corresponds to a single surface / material, whereas morph targets
as defined in the GLTF spec exist on “multi-primitive meshes” (where each primitive is its own surface with its own material).
Therefore in Bevy MorphWeights
an a parent entity are the “canonical weights” from a GLTF perspective, which then
synchronized to child Handle<Mesh>
/ MeshMorphWeights
(which correspond to “primitives” / “surfaces” from a GLTF perspective).
Add this to the parent of one or more Entities
with a Handle<Mesh>
with a MeshMorphWeights
.
Implementations§
§impl MorphWeights
impl MorphWeights
pub fn new( weights: Vec<f32>, first_mesh: Option<Handle<Mesh>> ) -> Result<MorphWeights, MorphBuildError>
pub fn first_mesh(&self) -> Option<&Handle<Mesh>>
pub fn first_mesh(&self) -> Option<&Handle<Mesh>>
The first child Handle<Mesh>
primitive controlled by these weights.
This can be used to look up metadata information such as Mesh::morph_target_names
.
Examples found in repository?
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
fn detect_morphs(
mut commands: Commands,
morphs: Query<(Entity, &MorphWeights, Option<&Name>)>,
meshes: Res<Assets<Mesh>>,
scene_handle: Res<SceneHandle>,
mut setup: Local<bool>,
asset_server: Res<AssetServer>,
) {
let no_morphing = morphs.iter().len() == 0;
if no_morphing {
return;
}
if scene_handle.is_loaded && !*setup {
*setup = true;
} else {
return;
}
let mut detected = Vec::new();
for (entity, weights, name) in &morphs {
let target_names = weights
.first_mesh()
.and_then(|h| meshes.get(h))
.and_then(|m| m.morph_target_names());
let targets = Target::new(name, weights.weights(), target_names, entity);
detected.extend(targets);
}
detected.truncate(AVAILABLE_KEYS.len());
let style = TextStyle {
font: asset_server.load("assets/fonts/FiraMono-Medium.ttf"),
font_size: 13.0,
..default()
};
let mut sections = vec![
TextSection::new("Morph Target Controls\n", style.clone()),
TextSection::new("---------------\n", style.clone()),
];
let target_to_text =
|(i, target): (usize, &Target)| target.text_section(AVAILABLE_KEYS[i].name, style.clone());
sections.extend(detected.iter().enumerate().map(target_to_text));
commands.insert_resource(WeightsControl { weights: detected });
commands.spawn(TextBundle::from_sections(sections).with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(10.0),
left: Val::Px(10.0),
..default()
}));
}
pub fn weights(&self) -> &[f32]
pub fn weights(&self) -> &[f32]
Examples found in repository?
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
fn update_text(
controls: Option<ResMut<WeightsControl>>,
mut text: Query<&mut Text>,
morphs: Query<&MorphWeights>,
) {
let Some(mut controls) = controls else {
return;
};
for (i, target) in controls.weights.iter_mut().enumerate() {
let Ok(weights) = morphs.get(target.entity) else {
continue;
};
let Some(&actual_weight) = weights.weights().get(target.index) else {
continue;
};
if actual_weight != target.weight {
target.weight = actual_weight;
}
let key_name = &AVAILABLE_KEYS[i].name;
let mut text = text.single_mut();
text.sections[i + 2].value = format!("[{key_name}] {target}\n");
}
}
fn update_morphs(
controls: Option<ResMut<WeightsControl>>,
mut morphs: Query<&mut MorphWeights>,
input: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
let Some(mut controls) = controls else {
return;
};
for (i, target) in controls.weights.iter_mut().enumerate() {
if !AVAILABLE_KEYS[i].active(&input) {
continue;
}
let Ok(mut weights) = morphs.get_mut(target.entity) else {
continue;
};
// To update individual morph target weights, get the `MorphWeights`
// component and call `weights_mut` to get access to the weights.
let weights_slice = weights.weights_mut();
let i = target.index;
let change = time.delta_seconds() * WEIGHT_PER_SECOND;
let new_weight = target.change_dir.change_weight(weights_slice[i], change);
weights_slice[i] = new_weight;
target.weight = new_weight;
}
}
fn detect_morphs(
mut commands: Commands,
morphs: Query<(Entity, &MorphWeights, Option<&Name>)>,
meshes: Res<Assets<Mesh>>,
scene_handle: Res<SceneHandle>,
mut setup: Local<bool>,
asset_server: Res<AssetServer>,
) {
let no_morphing = morphs.iter().len() == 0;
if no_morphing {
return;
}
if scene_handle.is_loaded && !*setup {
*setup = true;
} else {
return;
}
let mut detected = Vec::new();
for (entity, weights, name) in &morphs {
let target_names = weights
.first_mesh()
.and_then(|h| meshes.get(h))
.and_then(|m| m.morph_target_names());
let targets = Target::new(name, weights.weights(), target_names, entity);
detected.extend(targets);
}
detected.truncate(AVAILABLE_KEYS.len());
let style = TextStyle {
font: asset_server.load("assets/fonts/FiraMono-Medium.ttf"),
font_size: 13.0,
..default()
};
let mut sections = vec![
TextSection::new("Morph Target Controls\n", style.clone()),
TextSection::new("---------------\n", style.clone()),
];
let target_to_text =
|(i, target): (usize, &Target)| target.text_section(AVAILABLE_KEYS[i].name, style.clone());
sections.extend(detected.iter().enumerate().map(target_to_text));
commands.insert_resource(WeightsControl { weights: detected });
commands.spawn(TextBundle::from_sections(sections).with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(10.0),
left: Val::Px(10.0),
..default()
}));
}
pub fn weights_mut(&mut self) -> &mut [f32]
pub fn weights_mut(&mut self) -> &mut [f32]
Examples found in repository?
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
fn update_morphs(
controls: Option<ResMut<WeightsControl>>,
mut morphs: Query<&mut MorphWeights>,
input: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
let Some(mut controls) = controls else {
return;
};
for (i, target) in controls.weights.iter_mut().enumerate() {
if !AVAILABLE_KEYS[i].active(&input) {
continue;
}
let Ok(mut weights) = morphs.get_mut(target.entity) else {
continue;
};
// To update individual morph target weights, get the `MorphWeights`
// component and call `weights_mut` to get access to the weights.
let weights_slice = weights.weights_mut();
let i = target.index;
let change = time.delta_seconds() * WEIGHT_PER_SECOND;
let new_weight = target.change_dir.change_weight(weights_slice[i], change);
weights_slice[i] = new_weight;
target.weight = new_weight;
}
}
Trait Implementations§
§impl Clone for MorphWeights
impl Clone for MorphWeights
§fn clone(&self) -> MorphWeights
fn clone(&self) -> MorphWeights
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more§impl Component for MorphWeights
impl Component for MorphWeights
§const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::Table
const STORAGE_TYPE: StorageType = bevy_ecs::component::StorageType::Table
§fn register_component_hooks(_hooks: &mut ComponentHooks)
fn register_component_hooks(_hooks: &mut ComponentHooks)
ComponentHooks
.§impl Debug for MorphWeights
impl Debug for MorphWeights
§impl Default for MorphWeights
impl Default for MorphWeights
§fn default() -> MorphWeights
fn default() -> MorphWeights
§impl FromReflect for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
impl FromReflect for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
§fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<MorphWeights>
fn from_reflect(reflect: &(dyn Reflect + 'static)) -> Option<MorphWeights>
Self
from a reflected value.§fn take_from_reflect(
reflect: Box<dyn Reflect>
) -> Result<Self, Box<dyn Reflect>>
fn take_from_reflect( reflect: Box<dyn Reflect> ) -> Result<Self, Box<dyn Reflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read more§impl GetTypeRegistration for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
impl GetTypeRegistration for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration
for this type.§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
§impl Reflect for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
impl Reflect for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
§fn into_any(self: Box<MorphWeights>) -> Box<dyn Any>
fn into_any(self: Box<MorphWeights>) -> Box<dyn Any>
Box<dyn Any>
.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
.§fn into_reflect(self: Box<MorphWeights>) -> Box<dyn Reflect>
fn into_reflect(self: Box<MorphWeights>) -> Box<dyn Reflect>
§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
§fn clone_value(&self) -> Box<dyn Reflect>
fn clone_value(&self) -> Box<dyn Reflect>
Reflect
trait object. Read more§fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>
§fn apply(&mut self, value: &(dyn Reflect + 'static))
fn apply(&mut self, value: &(dyn Reflect + 'static))
§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
§fn reflect_owned(self: Box<MorphWeights>) -> ReflectOwned
fn reflect_owned(self: Box<MorphWeights>) -> ReflectOwned
§fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
fn reflect_partial_eq(&self, value: &(dyn Reflect + 'static)) -> Option<bool>
§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
§fn serializable(&self) -> Option<Serializable<'_>>
fn serializable(&self) -> Option<Serializable<'_>>
§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
§impl Struct for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
impl Struct for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
§fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn Reflect + 'static)>
name
as a &dyn Reflect
.§fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
fn field_mut(&mut self, name: &str) -> Option<&mut (dyn Reflect + 'static)>
name
as a
&mut dyn Reflect
.§fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn Reflect + 'static)>
index
as a
&dyn Reflect
.§fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
fn field_at_mut(&mut self, index: usize) -> Option<&mut (dyn Reflect + 'static)>
index
as a &mut dyn Reflect
.§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
§fn clone_dynamic(&self) -> DynamicStruct
fn clone_dynamic(&self) -> DynamicStruct
DynamicStruct
.§impl TypePath for MorphWeights
impl TypePath for MorphWeights
§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
§impl Typed for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
impl Typed for MorphWeightswhere
MorphWeights: Any + Send + Sync,
Vec<f32>: FromReflect + TypePath + RegisterForReflection,
Option<Handle<Mesh>>: FromReflect + TypePath + RegisterForReflection,
Auto Trait Implementations§
impl Freeze for MorphWeights
impl !RefUnwindSafe for MorphWeights
impl Send for MorphWeights
impl Sync for MorphWeights
impl Unpin for MorphWeights
impl !UnwindSafe for MorphWeights
Blanket Implementations§
§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<C> Bundle for Cwhere
C: Component,
impl<C> Bundle for Cwhere
C: Component,
fn component_ids( components: &mut Components, storages: &mut Storages, ids: &mut impl FnMut(ComponentId) )
unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> C
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<C> DynamicBundle for Cwhere
C: Component,
impl<C> DynamicBundle for Cwhere
C: Component,
fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>))
§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Self
using data from the given World
.§impl<T> GetPath for T
impl<T> GetPath for T
§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>
) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p> ) -> Result<&(dyn Reflect + 'static), ReflectPathError<'p>>
path
. Read more§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p> ) -> Result<&mut (dyn Reflect + 'static), ReflectPathError<'p>>
path
. Read more§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path
. Read more§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path
. Read more§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
§impl<T> NoneValue for Twhere
T: Default,
impl<T> NoneValue for Twhere
T: Default,
type NoneType = T
§fn null_value() -> T
fn null_value() -> T
§impl<T> Pointable for T
impl<T> Pointable for T
source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.