mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Transform Rewrite (#374)
Remove individual Translation / Rotation / Scale components in favor of a combined Transform component
This commit is contained in:
parent
3bc5e4cb1e
commit
474bb5403e
46 changed files with 478 additions and 1386 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,4 +5,4 @@ Cargo.lock
|
|||
.cargo/config
|
||||
/.idea
|
||||
/.vscode
|
||||
/benches/target
|
||||
/benches/target
|
|
@ -7,7 +7,7 @@ use bevy_render::{
|
|||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||
render_graph::base::MainPass,
|
||||
};
|
||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||
|
||||
/// A component bundle for "pbr mesh" entities
|
||||
#[derive(Bundle)]
|
||||
|
@ -18,9 +18,7 @@ pub struct PbrComponents {
|
|||
pub draw: Draw,
|
||||
pub render_pipelines: RenderPipelines,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for PbrComponents {
|
||||
|
@ -49,9 +47,7 @@ impl Default for PbrComponents {
|
|||
main_pass: Default::default(),
|
||||
draw: Default::default(),
|
||||
transform: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +57,5 @@ impl Default for PbrComponents {
|
|||
pub struct LightComponents {
|
||||
pub light: Light,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use bevy_core::Byteable;
|
||||
use bevy_math::Mat4;
|
||||
use bevy_property::Properties;
|
||||
use bevy_render::{
|
||||
camera::{CameraProjection, PerspectiveProjection},
|
||||
color::Color,
|
||||
};
|
||||
use bevy_transform::components::Translation;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use std::ops::Range;
|
||||
|
||||
/// A point light
|
||||
|
@ -37,7 +36,7 @@ pub(crate) struct LightRaw {
|
|||
unsafe impl Byteable for LightRaw {}
|
||||
|
||||
impl LightRaw {
|
||||
pub fn from(light: &Light, transform: &Mat4, translation: &Translation) -> LightRaw {
|
||||
pub fn from(light: &Light, global_transform: &GlobalTransform) -> LightRaw {
|
||||
let perspective = PerspectiveProjection {
|
||||
fov: light.fov,
|
||||
aspect_ratio: 1.0,
|
||||
|
@ -45,8 +44,8 @@ impl LightRaw {
|
|||
far: light.depth.end,
|
||||
};
|
||||
|
||||
let proj = perspective.get_projection_matrix() * *transform;
|
||||
let (x, y, z) = translation.0.into();
|
||||
let proj = perspective.get_projection_matrix() * *global_transform.value();
|
||||
let (x, y, z) = global_transform.translation().into();
|
||||
LightRaw {
|
||||
proj: proj.to_cols_array_2d(),
|
||||
pos: [x, y, z, 1.0],
|
||||
|
|
|
@ -80,7 +80,7 @@ pub fn lights_node_system(
|
|||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
// TODO: this write on RenderResourceBindings will prevent this system from running in parallel with other systems that do the same
|
||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||
mut query: Query<(&Light, &Transform, &Translation)>,
|
||||
mut query: Query<(&Light, &GlobalTransform)>,
|
||||
) {
|
||||
let state = &mut state;
|
||||
let render_resource_context = &**render_resource_context;
|
||||
|
@ -132,14 +132,12 @@ pub fn lights_node_system(
|
|||
data[0..light_count_size].copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
|
||||
// light array
|
||||
for ((light, transform, translation), slot) in query
|
||||
for ((light, global_transform), slot) in query
|
||||
.iter()
|
||||
.iter()
|
||||
.zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &transform.value, &translation).as_bytes(),
|
||||
);
|
||||
slot.copy_from_slice(LightRaw::from(&light, &global_transform).as_bytes());
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -24,10 +24,13 @@ use bevy_render::{
|
|||
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
|
||||
shader::Shader,
|
||||
};
|
||||
use bevy_transform::prelude::Transform;
|
||||
use bevy_transform::prelude::GlobalTransform;
|
||||
|
||||
pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) {
|
||||
graph.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
||||
graph.add_system_node(
|
||||
node::TRANSFORM,
|
||||
RenderResourcesNode::<GlobalTransform>::new(true),
|
||||
);
|
||||
graph.add_system_node(
|
||||
node::STANDARD_MATERIAL,
|
||||
AssetRenderResourcesNode::<StandardMaterial>::new(true),
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::Draw;
|
|||
use bevy_core::FloatOrd;
|
||||
use bevy_ecs::{Entity, Query};
|
||||
use bevy_property::Properties;
|
||||
use bevy_transform::prelude::Transform;
|
||||
use bevy_transform::prelude::GlobalTransform;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VisibleEntity {
|
||||
|
@ -24,13 +24,13 @@ impl VisibleEntities {
|
|||
}
|
||||
|
||||
pub fn visible_entities_system(
|
||||
mut camera_query: Query<(&Camera, &Transform, &mut VisibleEntities)>,
|
||||
mut camera_query: Query<(&Camera, &GlobalTransform, &mut VisibleEntities)>,
|
||||
mut draw_query: Query<(Entity, &Draw)>,
|
||||
draw_transform_query: Query<(&Draw, &Transform)>,
|
||||
draw_transform_query: Query<(&Draw, &GlobalTransform)>,
|
||||
) {
|
||||
for (camera, camera_transform, mut visible_entities) in &mut camera_query.iter() {
|
||||
for (camera, camera_global_transform, mut visible_entities) in &mut camera_query.iter() {
|
||||
visible_entities.value.clear();
|
||||
let camera_position = camera_transform.value.w_axis().truncate();
|
||||
let camera_position = camera_global_transform.translation();
|
||||
|
||||
let mut no_transform_order = 0.0;
|
||||
let mut transparent_entities = Vec::new();
|
||||
|
@ -39,18 +39,19 @@ pub fn visible_entities_system(
|
|||
continue;
|
||||
}
|
||||
|
||||
let order = if let Ok(transform) = draw_transform_query.get::<Transform>(entity) {
|
||||
let position = transform.value.w_axis().truncate();
|
||||
// smaller distances are sorted to lower indices by using the distance from the camera
|
||||
FloatOrd(match camera.depth_calculation {
|
||||
DepthCalculation::ZDifference => camera_position.z() - position.z(),
|
||||
DepthCalculation::Distance => (camera_position - position).length(),
|
||||
})
|
||||
} else {
|
||||
let order = FloatOrd(no_transform_order);
|
||||
no_transform_order += 0.1;
|
||||
order
|
||||
};
|
||||
let order =
|
||||
if let Ok(global_transform) = draw_transform_query.get::<GlobalTransform>(entity) {
|
||||
let position = global_transform.translation();
|
||||
// smaller distances are sorted to lower indices by using the distance from the camera
|
||||
FloatOrd(match camera.depth_calculation {
|
||||
DepthCalculation::ZDifference => camera_position.z() - position.z(),
|
||||
DepthCalculation::Distance => (camera_position - position).length(),
|
||||
})
|
||||
} else {
|
||||
let order = FloatOrd(no_transform_order);
|
||||
no_transform_order += 0.1;
|
||||
order
|
||||
};
|
||||
|
||||
if draw.is_transparent {
|
||||
transparent_entities.push(VisibleEntity { entity, order })
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::{
|
|||
use base::MainPass;
|
||||
use bevy_asset::Handle;
|
||||
use bevy_ecs::Bundle;
|
||||
use bevy_transform::components::{Rotation, Scale, Transform, Translation};
|
||||
use bevy_math::Vec3;
|
||||
use bevy_transform::components::{GlobalTransform, Transform};
|
||||
|
||||
/// A component bundle for "mesh" entities
|
||||
#[derive(Bundle, Default)]
|
||||
|
@ -17,9 +18,7 @@ pub struct MeshComponents {
|
|||
pub render_pipelines: RenderPipelines,
|
||||
pub main_pass: MainPass,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
/// A component bundle for "3d camera" entities
|
||||
|
@ -29,9 +28,7 @@ pub struct Camera3dComponents {
|
|||
pub perspective_projection: PerspectiveProjection,
|
||||
pub visible_entities: VisibleEntities,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for Camera3dComponents {
|
||||
|
@ -44,9 +41,7 @@ impl Default for Camera3dComponents {
|
|||
perspective_projection: Default::default(),
|
||||
visible_entities: Default::default(),
|
||||
transform: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,9 +53,7 @@ pub struct Camera2dComponents {
|
|||
pub orthographic_projection: OrthographicProjection,
|
||||
pub visible_entities: VisibleEntities,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for Camera2dComponents {
|
||||
|
@ -78,10 +71,8 @@ impl Default for Camera2dComponents {
|
|||
..Default::default()
|
||||
},
|
||||
visible_entities: Default::default(),
|
||||
transform: Default::default(),
|
||||
translation: Translation::new(0.0, 0.0, far - 0.1),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, far - 0.1)),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,18 +73,19 @@ pub fn camera_node_system(
|
|||
// PERF: this write on RenderResourceAssignments will prevent this system from running in parallel
|
||||
// with other systems that do the same
|
||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||
query: Query<(&Camera, &Transform)>,
|
||||
query: Query<(&Camera, &GlobalTransform)>,
|
||||
) {
|
||||
let render_resource_context = &**render_resource_context;
|
||||
|
||||
let (camera, transform) = if let Some(camera_entity) = active_cameras.get(&state.camera_name) {
|
||||
(
|
||||
query.get::<Camera>(camera_entity).unwrap(),
|
||||
query.get::<Transform>(camera_entity).unwrap(),
|
||||
)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let (camera, global_transform) =
|
||||
if let Some(camera_entity) = active_cameras.get(&state.camera_name) {
|
||||
(
|
||||
query.get::<Camera>(camera_entity).unwrap(),
|
||||
query.get::<GlobalTransform>(camera_entity).unwrap(),
|
||||
)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
let staging_buffer = if let Some(staging_buffer) = state.staging_buffer {
|
||||
render_resource_context.map_buffer(staging_buffer);
|
||||
|
@ -118,7 +119,7 @@ pub fn camera_node_system(
|
|||
|
||||
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||
let camera_matrix: [f32; 16] =
|
||||
(camera.projection_matrix * transform.value.inverse()).to_cols_array();
|
||||
(camera.projection_matrix * global_transform.value().inverse()).to_cols_array();
|
||||
|
||||
render_resource_context.write_mapped_buffer(
|
||||
staging_buffer,
|
||||
|
|
|
@ -179,14 +179,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl RenderResources for bevy_transform::prelude::Transform {
|
||||
impl RenderResources for bevy_transform::prelude::GlobalTransform {
|
||||
fn render_resources_len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource> {
|
||||
if index == 0 {
|
||||
Some(&self.value)
|
||||
Some(self.value())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use bevy_render::{
|
|||
prelude::Draw,
|
||||
render_graph::base::MainPass,
|
||||
};
|
||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||
|
||||
#[derive(Bundle)]
|
||||
pub struct SpriteComponents {
|
||||
|
@ -21,9 +21,7 @@ pub struct SpriteComponents {
|
|||
pub draw: Draw,
|
||||
pub render_pipelines: RenderPipelines,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for SpriteComponents {
|
||||
|
@ -56,9 +54,7 @@ impl Default for SpriteComponents {
|
|||
main_pass: MainPass,
|
||||
material: Default::default(),
|
||||
transform: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,9 +73,7 @@ pub struct SpriteSheetComponents {
|
|||
pub main_pass: MainPass,
|
||||
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for SpriteSheetComponents {
|
||||
|
@ -112,9 +106,7 @@ impl Default for SpriteSheetComponents {
|
|||
sprite: Default::default(),
|
||||
texture_atlas: Default::default(),
|
||||
transform: Default::default(),
|
||||
translation: Default::default(),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
119
crates/bevy_transform/src/components/global_transform.rs
Normal file
119
crates/bevy_transform/src/components/global_transform.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
use bevy_math::{Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_property::Properties;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct GlobalTransform {
|
||||
value: Mat4,
|
||||
}
|
||||
|
||||
impl GlobalTransform {
|
||||
#[inline(always)]
|
||||
pub fn new(value: Mat4) -> Self {
|
||||
GlobalTransform { value }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn identity() -> Self {
|
||||
GlobalTransform {
|
||||
value: Mat4::identity(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_translation(translation: Vec3) -> Self {
|
||||
GlobalTransform::new(Mat4::from_translation(translation))
|
||||
}
|
||||
|
||||
pub fn from_rotation(rotation: Quat) -> Self {
|
||||
GlobalTransform::new(Mat4::from_quat(rotation))
|
||||
}
|
||||
|
||||
// TODO: make sure scale is positive
|
||||
pub fn from_scale(scale: Vec3) -> Self {
|
||||
GlobalTransform::new(Mat4::from_scale(scale))
|
||||
}
|
||||
|
||||
pub fn with_translation(mut self, translation: Vec3) -> Self {
|
||||
self.translate(translation);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rotation(mut self, rotation: Quat) -> Self {
|
||||
self.rotate(rotation);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_scale(mut self, scale: Vec3) -> Self {
|
||||
self.apply_scale(scale);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &Mat4 {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn value_mut(&mut self) -> &mut Mat4 {
|
||||
&mut self.value
|
||||
}
|
||||
|
||||
pub fn translation(&self) -> Vec3 {
|
||||
Vec3::from(self.value.w_axis().truncate())
|
||||
}
|
||||
|
||||
pub fn rotation(&self) -> Quat {
|
||||
let scale = self.scale();
|
||||
|
||||
Quat::from_rotation_mat3(&Mat3::from_cols(
|
||||
Vec3::from(self.value.x_axis().truncate()) / scale.x(),
|
||||
Vec3::from(self.value.y_axis().truncate()) / scale.y(),
|
||||
Vec3::from(self.value.z_axis().truncate()) / scale.z(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn scale(&self) -> Vec3 {
|
||||
Vec3::new(
|
||||
self.value.x_axis().truncate().length(),
|
||||
self.value.y_axis().truncate().length(),
|
||||
self.value.z_axis().truncate().length(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_translation(&mut self, translation: Vec3) {
|
||||
*self.value.w_axis_mut() = translation.extend(1.0);
|
||||
}
|
||||
|
||||
pub fn set_rotation(&mut self, rotation: Quat) {
|
||||
let rotation = rotation * self.rotation().conjugate();
|
||||
rotation.normalize();
|
||||
self.value = Mat4::from_quat(rotation) * self.value;
|
||||
}
|
||||
|
||||
pub fn set_scale(&mut self, scale: Vec3) {
|
||||
let scale = scale / self.scale();
|
||||
self.value = Mat4::from_scale(scale) * self.value;
|
||||
}
|
||||
|
||||
pub fn translate(&mut self, translation: Vec3) {
|
||||
*self.value.w_axis_mut() += translation.extend(0.0);
|
||||
}
|
||||
|
||||
pub fn rotate(&mut self, rotation: Quat) {
|
||||
self.value = Mat4::from_quat(rotation) * self.value;
|
||||
}
|
||||
|
||||
pub fn apply_scale(&mut self, scale: Vec3) {
|
||||
self.value = Mat4::from_scale(scale) * self.value;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GlobalTransform {
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for GlobalTransform {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.value)
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
use bevy_math::Mat4;
|
||||
use bevy_property::Properties;
|
||||
use std::{
|
||||
fmt,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct LocalTransform(pub Mat4);
|
||||
|
||||
impl LocalTransform {
|
||||
pub fn identity() -> Self {
|
||||
Self(Mat4::identity())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LocalTransform {
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LocalTransform {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for LocalTransform {
|
||||
type Target = Mat4;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for LocalTransform {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
|
@ -1,17 +1,9 @@
|
|||
mod children;
|
||||
mod local_transform;
|
||||
mod non_uniform_scale;
|
||||
mod global_transform;
|
||||
mod parent;
|
||||
mod rotation;
|
||||
mod scale;
|
||||
mod transform;
|
||||
mod translation;
|
||||
|
||||
pub use children::Children;
|
||||
pub use local_transform::*;
|
||||
pub use non_uniform_scale::*;
|
||||
pub use global_transform::*;
|
||||
pub use parent::{Parent, PreviousParent};
|
||||
pub use rotation::*;
|
||||
pub use scale::*;
|
||||
pub use transform::*;
|
||||
pub use translation::*;
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
use bevy_math::Vec3;
|
||||
use bevy_property::Properties;
|
||||
use std::{
|
||||
fmt,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct NonUniformScale(pub Vec3);
|
||||
|
||||
impl NonUniformScale {
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||
Self(Vec3::new(x, y, z))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NonUniformScale {
|
||||
fn default() -> Self {
|
||||
NonUniformScale(Vec3::new(1.0, 1.0, 1.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for NonUniformScale {
|
||||
fn from(scale: Vec3) -> Self {
|
||||
Self(scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Vec3> for NonUniformScale {
|
||||
fn from(scale: &Vec3) -> Self {
|
||||
Self(*scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&mut Vec3> for NonUniformScale {
|
||||
fn from(scale: &mut Vec3) -> Self {
|
||||
Self(*scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NonUniformScale {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (x, y, z) = self.0.into();
|
||||
write!(f, "NonUniformScale({}, {}, {})", x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for NonUniformScale {
|
||||
type Target = Vec3;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for NonUniformScale {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
use bevy_math::Quat;
|
||||
use bevy_property::Properties;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct Rotation(pub Quat);
|
||||
impl Rotation {
|
||||
#[inline(always)]
|
||||
pub fn identity() -> Self {
|
||||
Self(Quat::identity())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_rotation_yxz(yaw: f32, pitch: f32, roll: f32) -> Self {
|
||||
Self(Quat::from_rotation_ypr(yaw, pitch, roll))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_rotation_xyz(x: f32, y: f32, z: f32) -> Self {
|
||||
Self(Quat::from_rotation_ypr(y, x, z))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_rotation_x(x: f32) -> Self {
|
||||
Self(Quat::from_rotation_x(x))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_rotation_y(y: f32) -> Self {
|
||||
Self(Quat::from_rotation_y(y))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_rotation_z(z: f32) -> Self {
|
||||
Self(Quat::from_rotation_z(z))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Rotation {
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Quat> for Rotation {
|
||||
fn from(rotation: Quat) -> Self {
|
||||
Self(rotation)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Rotation {
|
||||
type Target = Quat;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Rotation {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
use bevy_property::Properties;
|
||||
use std::{
|
||||
fmt,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct Scale(pub f32);
|
||||
|
||||
impl From<f32> for Scale {
|
||||
#[inline(always)]
|
||||
fn from(scale: f32) -> Self {
|
||||
Self(scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl Scale {
|
||||
#[inline(always)]
|
||||
pub fn identity() -> Self {
|
||||
Scale(1.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Scale {
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Scale {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Scale({})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Scale {
|
||||
type Target = f32;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Scale {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
|
@ -1,35 +1,108 @@
|
|||
use bevy_math::Mat4;
|
||||
use bevy_math::{Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_property::Properties;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Properties)]
|
||||
pub struct Transform {
|
||||
pub value: Mat4,
|
||||
pub sync: bool, // NOTE: this is hopefully a temporary measure to allow setting the transform directly.
|
||||
// ideally setting the transform automatically propagates back to position / translation / rotation,
|
||||
// but right now they are always considered the source of truth
|
||||
value: Mat4,
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
#[inline(always)]
|
||||
pub fn new(value: Mat4) -> Self {
|
||||
Transform { value }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn identity() -> Self {
|
||||
Transform {
|
||||
value: Mat4::identity(),
|
||||
sync: true,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn new(value: Mat4) -> Self {
|
||||
Transform { value, sync: true }
|
||||
pub fn from_translation(translation: Vec3) -> Self {
|
||||
Transform::new(Mat4::from_translation(translation))
|
||||
}
|
||||
|
||||
/// This creates a new `LocalToWorld` transform with the `sync` field set to `false`.
|
||||
/// While `sync` is false, position, rotation, and scale components will not be synced to the transform.
|
||||
/// This is helpful if you want to manually set the transform to a value (ex: Mat4::face_toward)
|
||||
#[inline(always)]
|
||||
pub fn new_sync_disabled(value: Mat4) -> Self {
|
||||
Transform { value, sync: false }
|
||||
pub fn from_rotation(rotation: Quat) -> Self {
|
||||
Transform::new(Mat4::from_quat(rotation))
|
||||
}
|
||||
|
||||
// TODO: make sure scale is positive
|
||||
pub fn from_scale(scale: Vec3) -> Self {
|
||||
Transform::new(Mat4::from_scale(scale))
|
||||
}
|
||||
|
||||
pub fn with_translation(mut self, translation: Vec3) -> Self {
|
||||
self.translate(translation);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rotation(mut self, rotation: Quat) -> Self {
|
||||
self.rotate(rotation);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_scale(mut self, scale: Vec3) -> Self {
|
||||
self.apply_scale(scale);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &Mat4 {
|
||||
&self.value
|
||||
}
|
||||
|
||||
pub fn value_mut(&mut self) -> &mut Mat4 {
|
||||
&mut self.value
|
||||
}
|
||||
|
||||
pub fn translation(&self) -> Vec3 {
|
||||
Vec3::from(self.value.w_axis().truncate())
|
||||
}
|
||||
|
||||
pub fn rotation(&self) -> Quat {
|
||||
let scale = self.scale();
|
||||
|
||||
Quat::from_rotation_mat3(&Mat3::from_cols(
|
||||
Vec3::from(self.value.x_axis().truncate()) / scale.x(),
|
||||
Vec3::from(self.value.y_axis().truncate()) / scale.y(),
|
||||
Vec3::from(self.value.z_axis().truncate()) / scale.z(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn scale(&self) -> Vec3 {
|
||||
Vec3::new(
|
||||
self.value.x_axis().truncate().length(),
|
||||
self.value.y_axis().truncate().length(),
|
||||
self.value.z_axis().truncate().length(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_translation(&mut self, translation: Vec3) {
|
||||
*self.value.w_axis_mut() = translation.extend(1.0);
|
||||
}
|
||||
|
||||
pub fn set_rotation(&mut self, rotation: Quat) {
|
||||
let rotation = rotation * self.rotation().conjugate();
|
||||
rotation.normalize();
|
||||
self.value = Mat4::from_quat(rotation) * self.value;
|
||||
}
|
||||
|
||||
pub fn set_scale(&mut self, scale: Vec3) {
|
||||
let scale = scale / self.scale();
|
||||
self.value = Mat4::from_scale(scale) * self.value;
|
||||
}
|
||||
|
||||
pub fn translate(&mut self, translation: Vec3) {
|
||||
*self.value.w_axis_mut() += translation.extend(0.0);
|
||||
}
|
||||
|
||||
pub fn rotate(&mut self, rotation: Quat) {
|
||||
self.value = Mat4::from_quat(rotation) * self.value;
|
||||
}
|
||||
|
||||
pub fn apply_scale(&mut self, scale: Vec3) {
|
||||
self.value = Mat4::from_scale(scale) * self.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
use bevy_math::Vec3;
|
||||
use bevy_property::Properties;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Properties)]
|
||||
pub struct Translation(pub Vec3);
|
||||
|
||||
impl Translation {
|
||||
#[inline(always)]
|
||||
pub fn identity() -> Self {
|
||||
Self(Vec3::default())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn new(x: f32, y: f32, z: f32) -> Self {
|
||||
Self(Vec3::new(x, y, z))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Translation {
|
||||
fn default() -> Self {
|
||||
Self::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3> for Translation {
|
||||
fn from(translation: Vec3) -> Self {
|
||||
Self(translation)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Translation {
|
||||
type Target = Vec3;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Translation {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
|
||||
use crate::prelude::{Children, Parent, PreviousParent};
|
||||
use bevy_ecs::{Commands, CommandsInternal, Component, DynamicBundle, Entity, WorldWriter};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -14,11 +14,7 @@ impl WorldWriter for InsertChildren {
|
|||
world
|
||||
.insert(
|
||||
*child,
|
||||
(
|
||||
Parent(self.parent),
|
||||
PreviousParent(Some(self.parent)),
|
||||
LocalTransform::default(),
|
||||
),
|
||||
(Parent(self.parent), PreviousParent(Some(self.parent))),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -55,11 +51,7 @@ impl WorldWriter for PushChildren {
|
|||
world
|
||||
.insert(
|
||||
*child,
|
||||
(
|
||||
Parent(self.parent),
|
||||
PreviousParent(Some(self.parent)),
|
||||
LocalTransform::default(),
|
||||
),
|
||||
(Parent(self.parent), PreviousParent(Some(self.parent))),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -215,7 +207,7 @@ impl<'a> BuildChildren for ChildBuilder<'a> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::BuildChildren;
|
||||
use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
|
||||
use crate::prelude::{Children, Parent, PreviousParent};
|
||||
use bevy_ecs::{Commands, Entity, Resources, World};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
|
@ -261,9 +253,6 @@ mod tests {
|
|||
*world.get::<PreviousParent>(child2).unwrap(),
|
||||
PreviousParent(Some(parent))
|
||||
);
|
||||
|
||||
assert!(world.get::<LocalTransform>(child1).is_ok());
|
||||
assert!(world.get::<LocalTransform>(child2).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -301,9 +290,6 @@ mod tests {
|
|||
PreviousParent(Some(parent))
|
||||
);
|
||||
|
||||
assert!(world.get::<LocalTransform>(child1).is_ok());
|
||||
assert!(world.get::<LocalTransform>(child2).is_ok());
|
||||
|
||||
commands.insert_children(parent, 1, &entities[3..]);
|
||||
commands.apply(&mut world, &mut resources);
|
||||
|
||||
|
@ -322,8 +308,5 @@ mod tests {
|
|||
*world.get::<PreviousParent>(child4).unwrap(),
|
||||
PreviousParent(Some(parent))
|
||||
);
|
||||
|
||||
assert!(world.get::<LocalTransform>(child3).is_ok());
|
||||
assert!(world.get::<LocalTransform>(child4).is_ok());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ mod test {
|
|||
use super::*;
|
||||
use crate::{hierarchy::BuildChildren, transform_systems};
|
||||
use bevy_ecs::{Resources, Schedule, World};
|
||||
use bevy_math::Vec3;
|
||||
|
||||
#[test]
|
||||
fn correct_children() {
|
||||
|
@ -127,13 +128,13 @@ mod test {
|
|||
let mut parent = None;
|
||||
let mut children = Vec::new();
|
||||
commands
|
||||
.spawn((Translation::new(1.0, 0.0, 0.0), Transform::identity()))
|
||||
.spawn((Transform::from_translation(Vec3::new(1.0, 0.0, 0.0)),))
|
||||
.for_current_entity(|entity| parent = Some(entity))
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn((Translation::new(0.0, 2.0, 0.0), Transform::identity()))
|
||||
.spawn((Transform::from_translation(Vec3::new(0.0, 2.0, 0.0)),))
|
||||
.for_current_entity(|entity| children.push(entity))
|
||||
.spawn((Translation::new(0.0, 0.0, 3.0), Transform::identity()))
|
||||
.spawn((Transform::from_translation(Vec3::new(0.0, 0.0, 3.0)),))
|
||||
.for_current_entity(|entity| children.push(entity));
|
||||
});
|
||||
let parent = parent.unwrap();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
|
||||
use crate::prelude::{Children, Parent, PreviousParent};
|
||||
use bevy_ecs::{Component, DynamicBundle, Entity, WorldBuilder};
|
||||
|
||||
pub struct WorldChildBuilder<'a, 'b> {
|
||||
|
@ -23,11 +23,7 @@ impl<'a, 'b> WorldChildBuilder<'a, 'b> {
|
|||
.expect("There should always be a parent at this point.");
|
||||
self.world_builder
|
||||
.spawn_as_entity(entity, components)
|
||||
.with_bundle((
|
||||
Parent(parent_entity),
|
||||
PreviousParent(Some(parent_entity)),
|
||||
LocalTransform::default(),
|
||||
));
|
||||
.with_bundle((Parent(parent_entity), PreviousParent(Some(parent_entity))));
|
||||
{
|
||||
let world = &mut self.world_builder.world;
|
||||
let mut added = false;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
pub mod components;
|
||||
pub mod hierarchy;
|
||||
pub mod local_transform_systems;
|
||||
pub mod transform_propagate_system;
|
||||
pub mod transform_systems;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{components::*, hierarchy::*, TransformPlugin};
|
||||
|
@ -11,16 +9,12 @@ pub mod prelude {
|
|||
use bevy_app::prelude::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_type_registry::RegisterType;
|
||||
use prelude::{
|
||||
Children, LocalTransform, NonUniformScale, Parent, Rotation, Scale, Transform, Translation,
|
||||
};
|
||||
use prelude::{Children, Parent, Transform};
|
||||
|
||||
pub(crate) fn transform_systems() -> Vec<Box<dyn System>> {
|
||||
let mut systems = Vec::with_capacity(5);
|
||||
|
||||
systems.append(&mut hierarchy::hierarchy_maintenance_systems());
|
||||
systems.append(&mut local_transform_systems::local_transform_systems());
|
||||
systems.append(&mut transform_systems::transform_systems());
|
||||
systems.push(transform_propagate_system::transform_propagate_system.system());
|
||||
|
||||
systems
|
||||
|
@ -33,12 +27,7 @@ impl Plugin for TransformPlugin {
|
|||
fn build(&self, app: &mut AppBuilder) {
|
||||
app.register_component::<Children>()
|
||||
.register_component::<Parent>()
|
||||
.register_component::<LocalTransform>()
|
||||
.register_component::<Transform>()
|
||||
.register_component::<Translation>()
|
||||
.register_component::<Rotation>()
|
||||
.register_component::<Scale>()
|
||||
.register_component::<NonUniformScale>()
|
||||
// add transform systems to startup so the first update is "correct"
|
||||
.add_startup_systems(transform_systems())
|
||||
.add_systems_to_stage(stage::POST_UPDATE, transform_systems());
|
||||
|
|
|
@ -1,365 +0,0 @@
|
|||
use crate::components::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, Quat, Vec3};
|
||||
|
||||
// TODO: "on changed" for all of these systems
|
||||
pub fn local_transform_translation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Rotation,
|
||||
Without<Scale, Without<NonUniformScale, (&mut LocalTransform, Changed<Translation>)>>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, translation) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_translation(translation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_rotation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Translation,
|
||||
Without<Scale, Without<NonUniformScale, (&mut LocalTransform, Changed<Rotation>)>>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, rotation) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_quat(rotation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Translation,
|
||||
Without<Rotation, Without<NonUniformScale, (&mut LocalTransform, Changed<Scale>)>>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, scale) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Translation,
|
||||
Without<Rotation, Without<Scale, (&mut LocalTransform, Changed<NonUniformScale>)>>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, non_uniform_scale) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale(non_uniform_scale.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_translation_rotation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Scale,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(Changed<Translation>, Changed<Rotation>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (translation, rotation)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_rotation_translation(rotation.0, translation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_translation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Rotation,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(Changed<Translation>, Changed<Scale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (translation, scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
Quat::default(),
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_translation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Rotation,
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(Changed<Translation>, Changed<NonUniformScale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (translation, non_uniform_scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
Quat::default(),
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_rotation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Translation,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(&mut LocalTransform, Or<(Changed<Rotation>, Changed<Scale>)>),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (rotation, scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
rotation.0,
|
||||
Vec3::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_rotation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Translation,
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(Changed<Rotation>, Changed<NonUniformScale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (rotation, non_uniform_scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
rotation.0,
|
||||
Vec3::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_translation_rotation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(Changed<Translation>, Changed<Rotation>, Changed<Scale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (translation, rotation, scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
rotation.0,
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_translation_rotation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut LocalTransform,
|
||||
Or<(
|
||||
Changed<Translation>,
|
||||
Changed<Rotation>,
|
||||
Changed<NonUniformScale>,
|
||||
)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut local, (translation, rotation, non_uniform_scale)) in &mut query.iter() {
|
||||
*local = LocalTransform(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
rotation.0,
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_transform_systems() -> Vec<Box<dyn System>> {
|
||||
vec![
|
||||
local_transform_translation_system.system(),
|
||||
local_transform_rotation_system.system(),
|
||||
local_transform_scale_system.system(),
|
||||
local_transform_non_uniform_scale_system.system(),
|
||||
local_transform_translation_rotation_system.system(),
|
||||
local_transform_translation_scale_system.system(),
|
||||
local_transform_translation_non_uniform_scale_system.system(),
|
||||
local_transform_rotation_scale_system.system(),
|
||||
local_transform_rotation_non_uniform_scale_system.system(),
|
||||
local_transform_translation_rotation_scale_system.system(),
|
||||
local_transform_translation_rotation_non_uniform_scale_system.system(),
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use bevy_ecs::{Resources, Schedule, World};
|
||||
use bevy_math::{Mat4, Quat, Vec3};
|
||||
|
||||
#[test]
|
||||
fn correct_local_transformation() {
|
||||
let mut world = World::default();
|
||||
let mut resources = Resources::default();
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.add_stage("update");
|
||||
for system in local_transform_systems() {
|
||||
schedule.add_system_to_stage("update", system);
|
||||
}
|
||||
|
||||
let local_transform = LocalTransform::identity();
|
||||
let t = Translation::new(1.0, 2.0, 3.0);
|
||||
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
|
||||
let s = Scale(2.0);
|
||||
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
|
||||
|
||||
// Add every combination of transform types.
|
||||
let translation = world.spawn((local_transform, t));
|
||||
let rotation = world.spawn((local_transform, r));
|
||||
let scale = world.spawn((local_transform, s));
|
||||
let non_uniform_scale = world.spawn((local_transform, nus));
|
||||
let translation_and_rotation = world.spawn((local_transform, t, r));
|
||||
let translation_and_scale = world.spawn((local_transform, t, s));
|
||||
let translation_and_nus = world.spawn((local_transform, t, nus));
|
||||
let rotation_scale = world.spawn((local_transform, r, s));
|
||||
let rotation_nus = world.spawn((local_transform, r, nus));
|
||||
let translation_rotation_scale = world.spawn((local_transform, t, r, s));
|
||||
let translation_rotation_nus = world.spawn((local_transform, t, r, nus));
|
||||
|
||||
// Run the system
|
||||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
// Verify that each was transformed correctly.
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(translation).unwrap().0,
|
||||
Mat4::from_translation(t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(rotation).unwrap().0,
|
||||
Mat4::from_quat(r.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(scale).unwrap().0,
|
||||
Mat4::from_scale(Vec3::new(s.0, s.0, s.0))
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(non_uniform_scale).unwrap().0,
|
||||
Mat4::from_scale(nus.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<LocalTransform>(translation_and_rotation)
|
||||
.unwrap()
|
||||
.0,
|
||||
Mat4::from_rotation_translation(r.0, t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<LocalTransform>(translation_and_scale)
|
||||
.unwrap()
|
||||
.0,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), Quat::default(), t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(translation_and_nus).unwrap().0,
|
||||
Mat4::from_scale_rotation_translation(nus.0, Quat::default(), t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(rotation_scale).unwrap().0,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), r.0, Vec3::default())
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<LocalTransform>(rotation_nus).unwrap().0,
|
||||
Mat4::from_scale_rotation_translation(nus.0, r.0, Vec3::default())
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<LocalTransform>(translation_rotation_scale)
|
||||
.unwrap()
|
||||
.0,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), r.0, t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<LocalTransform>(translation_rotation_nus)
|
||||
.unwrap()
|
||||
.0,
|
||||
Mat4::from_scale_rotation_translation(nus.0, r.0, t.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_propagates_local_transform_on_change() {
|
||||
let mut world = World::default();
|
||||
let mut resources = Resources::default();
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.add_stage("update");
|
||||
for system in local_transform_systems() {
|
||||
schedule.add_system_to_stage("update", system);
|
||||
}
|
||||
|
||||
let local_transform = LocalTransform::identity();
|
||||
let t = Translation::new(1.0, 2.0, 3.0);
|
||||
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
|
||||
let s = Scale(2.0);
|
||||
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
|
||||
|
||||
// Add every combination of transform types.
|
||||
world.spawn((local_transform, t));
|
||||
world.spawn((local_transform, r));
|
||||
world.spawn((local_transform, s));
|
||||
world.spawn((local_transform, nus));
|
||||
world.spawn((local_transform, t, r));
|
||||
world.spawn((local_transform, t, s));
|
||||
world.spawn((local_transform, t, nus));
|
||||
world.spawn((local_transform, r, s));
|
||||
world.spawn((local_transform, r, nus));
|
||||
world.spawn((local_transform, t, r, s));
|
||||
world.spawn((local_transform, t, r, nus));
|
||||
|
||||
// Run the system, local transforms should mutate since they are new
|
||||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
// Verify that the local transform is not mutated on the second frame
|
||||
fn assert_no_local_transforms_changed_system(_: Changed<LocalTransform>) {
|
||||
assert!(false)
|
||||
}
|
||||
|
||||
schedule.add_system_to_stage("update", assert_no_local_transforms_changed_system.system());
|
||||
schedule.run(&mut world, &mut resources);
|
||||
}
|
||||
}
|
|
@ -1,61 +1,49 @@
|
|||
use crate::components::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::Mat4;
|
||||
|
||||
pub fn transform_propagate_system(
|
||||
mut root_query: Query<
|
||||
Without<Parent, (Option<&Children>, &mut Transform, Option<&LocalTransform>)>,
|
||||
>,
|
||||
mut local_transform_query: Query<(&mut Transform, &LocalTransform, Option<&Children>)>,
|
||||
mut root_query: Query<Without<Parent, (Option<&Children>, &Transform, &mut GlobalTransform)>>,
|
||||
mut transform_query: Query<(&Transform, &mut GlobalTransform, Option<&Children>)>,
|
||||
) {
|
||||
for (children, mut transform, local_transform) in &mut root_query.iter() {
|
||||
if let Some(local_transform) = local_transform {
|
||||
transform.value = local_transform.0;
|
||||
}
|
||||
for (children, transform, mut global_transform) in &mut root_query.iter() {
|
||||
*global_transform.value_mut() = *transform.value();
|
||||
|
||||
if let Some(children) = children {
|
||||
for child in children.0.iter() {
|
||||
propagate_recursive(*transform, &mut local_transform_query, *child);
|
||||
propagate_recursive(*global_transform.value(), &mut transform_query, *child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_recursive(
|
||||
parent_local_to_world: Transform,
|
||||
local_transform_query: &mut Query<(&mut Transform, &LocalTransform, Option<&Children>)>,
|
||||
parent: Mat4,
|
||||
transform_query: &mut Query<(&Transform, &mut GlobalTransform, Option<&Children>)>,
|
||||
entity: Entity,
|
||||
) {
|
||||
log::trace!("Updating Transform for {:?}", entity);
|
||||
let local_transform = {
|
||||
if let Ok(local_transform) = local_transform_query.get::<LocalTransform>(entity) {
|
||||
*local_transform
|
||||
|
||||
let global_matrix = {
|
||||
if let (Ok(transform), Ok(mut global_transform)) = (
|
||||
transform_query.get::<Transform>(entity),
|
||||
transform_query.get_mut::<GlobalTransform>(entity),
|
||||
) {
|
||||
*global_transform.value_mut() = parent * *transform.value();
|
||||
*global_transform.value()
|
||||
} else {
|
||||
log::warn!(
|
||||
"Entity {:?} is a child in the hierarchy but does not have a LocalTransform",
|
||||
entity
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let new_transform = Transform {
|
||||
value: parent_local_to_world.value * local_transform.0,
|
||||
sync: true,
|
||||
};
|
||||
|
||||
{
|
||||
let mut transform = local_transform_query.get_mut::<Transform>(entity).unwrap();
|
||||
transform.value = new_transform.value;
|
||||
}
|
||||
|
||||
// Collect children
|
||||
let children = local_transform_query
|
||||
let children = transform_query
|
||||
.get::<Children>(entity)
|
||||
.map(|e| e.0.iter().cloned().collect::<Vec<_>>())
|
||||
.unwrap_or_default();
|
||||
|
||||
for child in children {
|
||||
propagate_recursive(new_transform, local_transform_query, child);
|
||||
propagate_recursive(global_matrix, transform_query, child);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,20 +66,21 @@ mod test {
|
|||
}
|
||||
|
||||
// Root entity
|
||||
let parent = world.spawn((Translation::new(1.0, 0.0, 0.0), Transform::identity()));
|
||||
let parent = world.spawn((
|
||||
Transform::from_translation(Vec3::new(1.0, 0.0, 0.0)),
|
||||
GlobalTransform::identity(),
|
||||
));
|
||||
let children = world
|
||||
.spawn_batch(vec![
|
||||
(
|
||||
Translation::new(0.0, 2.0, 0.0),
|
||||
LocalTransform::identity(),
|
||||
Transform::identity(),
|
||||
Transform::from_translation(Vec3::new(0.0, 2.0, 0.)),
|
||||
Parent(parent),
|
||||
GlobalTransform::identity(),
|
||||
),
|
||||
(
|
||||
Translation::new(0.0, 0.0, 3.0),
|
||||
LocalTransform::identity(),
|
||||
Transform::identity(),
|
||||
Transform::from_translation(Vec3::new(0.0, 0.0, 3.)),
|
||||
Parent(parent),
|
||||
GlobalTransform::identity(),
|
||||
),
|
||||
])
|
||||
.collect::<Vec<Entity>>();
|
||||
|
@ -103,13 +92,13 @@ mod test {
|
|||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
assert_eq!(
|
||||
world.get::<Transform>(children[0]).unwrap().value,
|
||||
*world.get::<GlobalTransform>(children[0]).unwrap().value(),
|
||||
Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
|
||||
* Mat4::from_translation(Vec3::new(0.0, 2.0, 0.0))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
world.get::<Transform>(children[1]).unwrap().value,
|
||||
*world.get::<GlobalTransform>(children[1]).unwrap().value(),
|
||||
Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
|
||||
* Mat4::from_translation(Vec3::new(0.0, 0.0, 3.0))
|
||||
);
|
||||
|
@ -130,25 +119,34 @@ mod test {
|
|||
let mut commands = Commands::default();
|
||||
let mut children = Vec::new();
|
||||
commands
|
||||
.spawn((Translation::new(1.0, 0.0, 0.0), Transform::identity()))
|
||||
.spawn((
|
||||
Transform::from_translation(Vec3::new(1.0, 0.0, 0.0)),
|
||||
GlobalTransform::identity(),
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn((Translation::new(0.0, 2.0, 0.0), Transform::identity()))
|
||||
.spawn((
|
||||
Transform::from_translation(Vec3::new(0.0, 2.0, 0.0)),
|
||||
GlobalTransform::identity(),
|
||||
))
|
||||
.for_current_entity(|entity| children.push(entity))
|
||||
.spawn((Translation::new(0.0, 0.0, 3.0), Transform::identity()))
|
||||
.spawn((
|
||||
Transform::from_translation(Vec3::new(0.0, 0.0, 3.0)),
|
||||
GlobalTransform::identity(),
|
||||
))
|
||||
.for_current_entity(|entity| children.push(entity));
|
||||
});
|
||||
commands.apply(&mut world, &mut resources);
|
||||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
assert_eq!(
|
||||
world.get::<Transform>(children[0]).unwrap().value,
|
||||
*world.get::<GlobalTransform>(children[0]).unwrap().value(),
|
||||
Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
|
||||
* Mat4::from_translation(Vec3::new(0.0, 2.0, 0.0))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
world.get::<Transform>(children[1]).unwrap().value,
|
||||
*world.get::<GlobalTransform>(children[1]).unwrap().value(),
|
||||
Mat4::from_translation(Vec3::new(1.0, 0.0, 0.0))
|
||||
* Mat4::from_translation(Vec3::new(0.0, 0.0, 3.0))
|
||||
);
|
||||
|
|
|
@ -1,433 +0,0 @@
|
|||
use crate::components::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, Quat, Vec3};
|
||||
|
||||
// TODO: on changed for all of these systems
|
||||
pub fn transform_translation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Rotation,
|
||||
Without<Scale, Without<NonUniformScale, (&mut Transform, Changed<Translation>)>>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, translation) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_translation(translation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_rotation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Translation,
|
||||
Without<Scale, Without<NonUniformScale, (&mut Transform, Changed<Rotation>)>>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, rotation) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_quat(rotation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Translation,
|
||||
Without<Rotation, Without<NonUniformScale, (&mut Transform, Changed<Scale>)>>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, scale) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale(Vec3::new(scale.0, scale.0, scale.0)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Translation,
|
||||
Without<Rotation, Without<Scale, (&mut Transform, Changed<NonUniformScale>)>>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, non_uniform_scale) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale(non_uniform_scale.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_translation_rotation_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Scale,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(
|
||||
&mut Transform,
|
||||
Or<(Changed<Translation>, Changed<Rotation>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (translation, rotation)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_rotation_translation(rotation.0, translation.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_translation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Rotation,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(&mut Transform, Or<(Changed<Translation>, Changed<Scale>)>),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (translation, scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
Quat::default(),
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_translation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Rotation,
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut Transform,
|
||||
Or<(Changed<Translation>, Changed<NonUniformScale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (translation, non_uniform_scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
Quat::default(),
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_rotation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Translation,
|
||||
Without<NonUniformScale, (&mut Transform, Or<(Changed<Rotation>, Changed<Scale>)>)>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (rotation, scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
rotation.0,
|
||||
Vec3::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_rotation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Translation,
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut Transform,
|
||||
Or<(Changed<Rotation>, Changed<NonUniformScale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (rotation, non_uniform_scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
rotation.0,
|
||||
Vec3::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_translation_rotation_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
NonUniformScale,
|
||||
(
|
||||
&mut Transform,
|
||||
Or<(Changed<Translation>, Changed<Rotation>, Changed<Scale>)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (translation, rotation, scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
Vec3::new(scale.0, scale.0, scale.0),
|
||||
rotation.0,
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_translation_rotation_non_uniform_scale_system(
|
||||
mut query: Query<
|
||||
Without<
|
||||
LocalTransform,
|
||||
Without<
|
||||
Scale,
|
||||
(
|
||||
&mut Transform,
|
||||
Or<(
|
||||
Changed<Translation>,
|
||||
Changed<Rotation>,
|
||||
Changed<NonUniformScale>,
|
||||
)>,
|
||||
),
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
) {
|
||||
for (mut transform, (translation, rotation, non_uniform_scale)) in &mut query.iter() {
|
||||
if !transform.sync {
|
||||
continue;
|
||||
}
|
||||
|
||||
*transform = Transform::new(Mat4::from_scale_rotation_translation(
|
||||
non_uniform_scale.0,
|
||||
rotation.0,
|
||||
translation.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transform_systems() -> Vec<Box<dyn System>> {
|
||||
vec![
|
||||
transform_translation_system.system(),
|
||||
transform_rotation_system.system(),
|
||||
transform_scale_system.system(),
|
||||
transform_non_uniform_scale_system.system(),
|
||||
transform_translation_rotation_system.system(),
|
||||
transform_translation_scale_system.system(),
|
||||
transform_translation_non_uniform_scale_system.system(),
|
||||
transform_rotation_scale_system.system(),
|
||||
transform_rotation_non_uniform_scale_system.system(),
|
||||
transform_translation_rotation_scale_system.system(),
|
||||
transform_translation_rotation_non_uniform_scale_system.system(),
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use bevy_ecs::{Resources, Schedule, World};
|
||||
use bevy_math::{Mat4, Quat, Vec3};
|
||||
|
||||
#[test]
|
||||
fn correct_world_transformation() {
|
||||
let mut world = World::default();
|
||||
let mut resources = Resources::default();
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.add_stage("update");
|
||||
for system in transform_systems() {
|
||||
schedule.add_system_to_stage("update", system);
|
||||
}
|
||||
|
||||
let transform = Transform::identity();
|
||||
let t = Translation::new(1.0, 2.0, 3.0);
|
||||
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
|
||||
let s = Scale(2.0);
|
||||
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
|
||||
|
||||
// Add every combination of transform types.
|
||||
let translation = world.spawn((transform, t));
|
||||
let rotation = world.spawn((transform, r));
|
||||
let scale = world.spawn((transform, s));
|
||||
let non_uniform_scale = world.spawn((transform, nus));
|
||||
let translation_and_rotation = world.spawn((transform, t, r));
|
||||
let translation_and_scale = world.spawn((transform, t, s));
|
||||
let translation_and_nus = world.spawn((transform, t, nus));
|
||||
let rotation_scale = world.spawn((transform, r, s));
|
||||
let rotation_nus = world.spawn((transform, r, nus));
|
||||
let translation_rotation_scale = world.spawn((transform, t, r, s));
|
||||
let translation_rotation_nus = world.spawn((transform, t, r, nus));
|
||||
|
||||
// Run the system
|
||||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
// Verify that each was transformed correctly.
|
||||
assert_eq!(
|
||||
world.get::<Transform>(translation).unwrap().value,
|
||||
Mat4::from_translation(t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(rotation).unwrap().value,
|
||||
Mat4::from_quat(r.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(scale).unwrap().value,
|
||||
Mat4::from_scale(Vec3::new(s.0, s.0, s.0))
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(non_uniform_scale).unwrap().value,
|
||||
Mat4::from_scale(nus.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<Transform>(translation_and_rotation)
|
||||
.unwrap()
|
||||
.value,
|
||||
Mat4::from_rotation_translation(r.0, t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(translation_and_scale).unwrap().value,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), Quat::default(), t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(translation_and_nus).unwrap().value,
|
||||
Mat4::from_scale_rotation_translation(nus.0, Quat::default(), t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(rotation_scale).unwrap().value,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), r.0, Vec3::default())
|
||||
);
|
||||
assert_eq!(
|
||||
world.get::<Transform>(rotation_nus).unwrap().value,
|
||||
Mat4::from_scale_rotation_translation(nus.0, r.0, Vec3::default())
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<Transform>(translation_rotation_scale)
|
||||
.unwrap()
|
||||
.value,
|
||||
Mat4::from_scale_rotation_translation(Vec3::new(s.0, s.0, s.0), r.0, t.0)
|
||||
);
|
||||
assert_eq!(
|
||||
world
|
||||
.get::<Transform>(translation_rotation_nus)
|
||||
.unwrap()
|
||||
.value,
|
||||
Mat4::from_scale_rotation_translation(nus.0, r.0, t.0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_propagates_transform_on_change() {
|
||||
let mut world = World::default();
|
||||
let mut resources = Resources::default();
|
||||
|
||||
let mut schedule = Schedule::default();
|
||||
schedule.add_stage("update");
|
||||
for system in transform_systems() {
|
||||
schedule.add_system_to_stage("update", system);
|
||||
}
|
||||
|
||||
let transform = Transform::identity();
|
||||
let t = Translation::new(1.0, 2.0, 3.0);
|
||||
let r = Rotation(Quat::from_rotation_ypr(1.0, 2.0, 3.0));
|
||||
let s = Scale(2.0);
|
||||
let nus = NonUniformScale::new(1.0, 2.0, 3.0);
|
||||
|
||||
// Add every combination of transform types.
|
||||
world.spawn((transform, t));
|
||||
world.spawn((transform, r));
|
||||
world.spawn((transform, s));
|
||||
world.spawn((transform, nus));
|
||||
world.spawn((transform, t, r));
|
||||
world.spawn((transform, t, s));
|
||||
world.spawn((transform, t, nus));
|
||||
world.spawn((transform, r, s));
|
||||
world.spawn((transform, r, nus));
|
||||
world.spawn((transform, t, r, s));
|
||||
world.spawn((transform, t, r, nus));
|
||||
|
||||
// Run the system, transforms should mutate since they are new
|
||||
schedule.run(&mut world, &mut resources);
|
||||
|
||||
// Verify that the transform is not mutated on the second frame
|
||||
fn assert_no_transforms_changed_system(_: Changed<Transform>) {
|
||||
assert!(false)
|
||||
}
|
||||
|
||||
schedule.add_system_to_stage("update", assert_no_transforms_changed_system.system());
|
||||
schedule.run(&mut world, &mut resources);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_ecs::Bundle;
|
||||
use bevy_math::Vec3;
|
||||
use bevy_render::{
|
||||
camera::{Camera, OrthographicProjection, VisibleEntities, WindowOrigin},
|
||||
draw::Draw,
|
||||
|
@ -13,10 +14,7 @@ use bevy_render::{
|
|||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||
};
|
||||
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
|
||||
use bevy_transform::{
|
||||
components::LocalTransform,
|
||||
prelude::{Rotation, Scale, Transform, Translation},
|
||||
};
|
||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||
|
||||
#[derive(Bundle, Clone)]
|
||||
pub struct NodeComponents {
|
||||
|
@ -27,7 +25,7 @@ pub struct NodeComponents {
|
|||
pub draw: Draw,
|
||||
pub render_pipelines: RenderPipelines,
|
||||
pub transform: Transform,
|
||||
pub local_transform: LocalTransform,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for NodeComponents {
|
||||
|
@ -57,7 +55,7 @@ impl Default for NodeComponents {
|
|||
material: Default::default(),
|
||||
draw: Default::default(),
|
||||
transform: Default::default(),
|
||||
local_transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +71,7 @@ pub struct ImageComponents {
|
|||
pub draw: Draw,
|
||||
pub render_pipelines: RenderPipelines,
|
||||
pub transform: Transform,
|
||||
pub local_transform: LocalTransform,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for ImageComponents {
|
||||
|
@ -105,7 +103,7 @@ impl Default for ImageComponents {
|
|||
material: Default::default(),
|
||||
draw: Default::default(),
|
||||
transform: Default::default(),
|
||||
local_transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +117,7 @@ pub struct TextComponents {
|
|||
pub calculated_size: CalculatedSize,
|
||||
pub focus_policy: FocusPolicy,
|
||||
pub transform: Transform,
|
||||
pub local_transform: LocalTransform,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for TextComponents {
|
||||
|
@ -135,7 +133,7 @@ impl Default for TextComponents {
|
|||
calculated_size: Default::default(),
|
||||
style: Default::default(),
|
||||
transform: Default::default(),
|
||||
local_transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +150,7 @@ pub struct ButtonComponents {
|
|||
pub draw: Draw,
|
||||
pub render_pipelines: RenderPipelines,
|
||||
pub transform: Transform,
|
||||
pub local_transform: LocalTransform,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for ButtonComponents {
|
||||
|
@ -185,7 +183,7 @@ impl Default for ButtonComponents {
|
|||
material: Default::default(),
|
||||
draw: Default::default(),
|
||||
transform: Default::default(),
|
||||
local_transform: Default::default(),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,9 +194,7 @@ pub struct UiCameraComponents {
|
|||
pub orthographic_projection: OrthographicProjection,
|
||||
pub visible_entities: VisibleEntities,
|
||||
pub transform: Transform,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
pub global_transform: GlobalTransform,
|
||||
}
|
||||
|
||||
impl Default for UiCameraComponents {
|
||||
|
@ -216,11 +212,9 @@ impl Default for UiCameraComponents {
|
|||
window_origin: WindowOrigin::BottomLeft,
|
||||
..Default::default()
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, far - 0.1),
|
||||
visible_entities: Default::default(),
|
||||
transform: Default::default(),
|
||||
rotation: Default::default(),
|
||||
scale: Default::default(),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, far - 0.1)),
|
||||
global_transform: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ mod convert;
|
|||
use crate::{CalculatedSize, Node, Style};
|
||||
use bevy_ecs::{Changed, Entity, Query, Res, ResMut, With, Without};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_transform::prelude::{Children, LocalTransform, Parent};
|
||||
use bevy_transform::prelude::{Children, Parent, Transform};
|
||||
use bevy_utils::HashMap;
|
||||
use bevy_window::{Window, WindowId, Windows};
|
||||
use stretch::{number::Number, Stretch};
|
||||
|
@ -154,7 +154,7 @@ pub fn flex_node_system(
|
|||
mut node_query: Query<With<Node, (Entity, Changed<Style>, Option<&CalculatedSize>)>>,
|
||||
mut changed_size_query: Query<With<Node, (Entity, &Style, Changed<CalculatedSize>)>>,
|
||||
mut children_query: Query<With<Node, (Entity, Changed<Children>)>>,
|
||||
mut node_transform_query: Query<(Entity, &mut Node, &mut LocalTransform, Option<&Parent>)>,
|
||||
mut node_transform_query: Query<(Entity, &mut Node, &mut Transform, Option<&Parent>)>,
|
||||
) {
|
||||
// update window root nodes
|
||||
for window in windows.iter() {
|
||||
|
@ -190,10 +190,10 @@ pub fn flex_node_system(
|
|||
// compute layouts
|
||||
flex_surface.compute_window_layouts();
|
||||
|
||||
for (entity, mut node, mut local, parent) in &mut node_transform_query.iter() {
|
||||
for (entity, mut node, mut transform, parent) in &mut node_transform_query.iter() {
|
||||
let layout = flex_surface.get_layout(entity).unwrap();
|
||||
node.size = Vec2::new(layout.size.width, layout.size.height);
|
||||
let mut position = local.w_axis();
|
||||
let mut position = transform.translation();
|
||||
position.set_x(layout.location.x + layout.size.width / 2.0);
|
||||
position.set_y(layout.location.y + layout.size.height / 2.0);
|
||||
if let Some(parent) = parent {
|
||||
|
@ -203,6 +203,6 @@ pub fn flex_node_system(
|
|||
}
|
||||
}
|
||||
|
||||
local.set_w_axis(position);
|
||||
transform.set_translation(position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy_core::FloatOrd;
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_input::{mouse::MouseButton, Input};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_transform::components::Transform;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_window::CursorMoved;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
|
@ -46,7 +46,7 @@ pub fn ui_focus_system(
|
|||
mut node_query: Query<(
|
||||
Entity,
|
||||
&Node,
|
||||
&Transform,
|
||||
&GlobalTransform,
|
||||
Option<&mut Interaction>,
|
||||
Option<&FocusPolicy>,
|
||||
)>,
|
||||
|
@ -56,7 +56,9 @@ pub fn ui_focus_system(
|
|||
}
|
||||
|
||||
if mouse_button_input.just_released(MouseButton::Left) {
|
||||
for (_entity, _node, _transform, interaction, _focus_policy) in &mut node_query.iter() {
|
||||
for (_entity, _node, _global_transform, interaction, _focus_policy) in
|
||||
&mut node_query.iter()
|
||||
{
|
||||
if let Some(mut interaction) = interaction {
|
||||
if *interaction == Interaction::Clicked {
|
||||
*interaction = Interaction::None;
|
||||
|
@ -72,26 +74,28 @@ pub fn ui_focus_system(
|
|||
let mut query_iter = node_query.iter();
|
||||
let mut moused_over_z_sorted_nodes = query_iter
|
||||
.iter()
|
||||
.filter_map(|(entity, node, transform, interaction, focus_policy)| {
|
||||
let position = transform.value.w_axis();
|
||||
let ui_position = position.truncate().truncate();
|
||||
let extents = node.size / 2.0;
|
||||
let min = ui_position - extents;
|
||||
let max = ui_position + extents;
|
||||
// if the current cursor position is within the bounds of the node, consider it for clicking
|
||||
if (min.x()..max.x()).contains(&state.cursor_position.x())
|
||||
&& (min.y()..max.y()).contains(&state.cursor_position.y())
|
||||
{
|
||||
Some((entity, focus_policy, interaction, FloatOrd(position.z())))
|
||||
} else {
|
||||
if let Some(mut interaction) = interaction {
|
||||
if *interaction == Interaction::Hovered {
|
||||
*interaction = Interaction::None;
|
||||
.filter_map(
|
||||
|(entity, node, global_transform, interaction, focus_policy)| {
|
||||
let position = global_transform.translation();
|
||||
let ui_position = position.truncate();
|
||||
let extents = node.size / 2.0;
|
||||
let min = ui_position - extents;
|
||||
let max = ui_position + extents;
|
||||
// if the current cursor position is within the bounds of the node, consider it for clicking
|
||||
if (min.x()..max.x()).contains(&state.cursor_position.x())
|
||||
&& (min.y()..max.y()).contains(&state.cursor_position.y())
|
||||
{
|
||||
Some((entity, focus_policy, interaction, FloatOrd(position.z())))
|
||||
} else {
|
||||
if let Some(mut interaction) = interaction {
|
||||
if *interaction == Interaction::Hovered {
|
||||
*interaction = Interaction::None;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
moused_over_z_sorted_nodes.sort_by_key(|(_, _, _, z)| -*z);
|
||||
|
|
|
@ -2,14 +2,14 @@ use super::Node;
|
|||
use bevy_ecs::{Entity, Query, With, Without};
|
||||
use bevy_transform::{
|
||||
hierarchy,
|
||||
prelude::{Children, LocalTransform, Parent},
|
||||
prelude::{Children, Parent, Transform},
|
||||
};
|
||||
|
||||
pub const UI_Z_STEP: f32 = 0.001;
|
||||
|
||||
pub fn ui_z_system(
|
||||
mut root_node_query: Query<With<Node, Without<Parent, Entity>>>,
|
||||
mut node_query: Query<(Entity, &Node, &mut LocalTransform)>,
|
||||
mut node_query: Query<(Entity, &Node, &mut Transform)>,
|
||||
children_query: Query<&Children>,
|
||||
) {
|
||||
let mut current_global_z = 0.0;
|
||||
|
@ -34,12 +34,12 @@ pub fn ui_z_system(
|
|||
}
|
||||
|
||||
fn update_node_entity(
|
||||
node_query: &mut Query<(Entity, &Node, &mut LocalTransform)>,
|
||||
node_query: &mut Query<(Entity, &Node, &mut Transform)>,
|
||||
entity: Entity,
|
||||
parent_result: Option<f32>,
|
||||
previous_result: Option<f32>,
|
||||
) -> Option<f32> {
|
||||
let mut transform = node_query.get_mut::<LocalTransform>(entity).ok()?;
|
||||
let mut transform = node_query.get_mut::<Transform>(entity).ok()?;
|
||||
let mut z = UI_Z_STEP;
|
||||
let parent_global_z = parent_result.unwrap();
|
||||
if let Some(previous_global_z) = previous_result {
|
||||
|
@ -47,9 +47,9 @@ fn update_node_entity(
|
|||
};
|
||||
let global_z = z + parent_global_z;
|
||||
|
||||
let mut position = transform.w_axis();
|
||||
let mut position = transform.translation();
|
||||
position.set_z(z);
|
||||
transform.set_w_axis(position);
|
||||
transform.set_translation(position);
|
||||
|
||||
Some(global_z)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use bevy_render::{
|
|||
};
|
||||
use bevy_sprite::TextureAtlas;
|
||||
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
||||
use bevy_transform::prelude::Transform;
|
||||
use bevy_transform::prelude::GlobalTransform;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Text {
|
||||
|
@ -58,11 +58,11 @@ pub fn draw_text_system(
|
|||
texture_atlases: Res<Assets<TextureAtlas>>,
|
||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
|
||||
mut query: Query<(&mut Draw, &Text, &Node, &Transform)>,
|
||||
mut query: Query<(&mut Draw, &Text, &Node, &GlobalTransform)>,
|
||||
) {
|
||||
for (mut draw, text, node, transform) in &mut query.iter() {
|
||||
let position =
|
||||
Vec3::from(transform.value.w_axis().truncate()) - (node.size / 2.0).extend(0.0);
|
||||
for (mut draw, text, node, global_transform) in &mut query.iter() {
|
||||
let position = Vec3::from(global_transform.value().w_axis().truncate())
|
||||
- (node.size / 2.0).extend(0.0);
|
||||
|
||||
let mut drawable_text = DrawableText {
|
||||
font: fonts.get(&text.font).unwrap(),
|
||||
|
|
|
@ -39,7 +39,7 @@ fn setup(
|
|||
.spawn(Camera2dComponents::default())
|
||||
.spawn(SpriteSheetComponents {
|
||||
texture_atlas: texture_atlas_handle,
|
||||
scale: Scale(6.0),
|
||||
transform: Transform::from_scale(Vec3::one() * 6.0),
|
||||
..Default::default()
|
||||
})
|
||||
.with(Timer::from_seconds(0.1, true));
|
||||
|
|
|
@ -61,8 +61,8 @@ fn load_atlas(
|
|||
.spawn(Camera2dComponents::default())
|
||||
// draw a sprite from the atlas
|
||||
.spawn(SpriteSheetComponents {
|
||||
scale: Scale(4.0),
|
||||
translation: Translation(Vec3::new(150.0, 0.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(150.0, 0.0, 0.0))
|
||||
.with_scale(Vec3::one() * 4.0),
|
||||
sprite: TextureAtlasSprite::new(vendor_index as u32),
|
||||
texture_atlas: atlas_handle,
|
||||
..Default::default()
|
||||
|
@ -70,7 +70,7 @@ fn load_atlas(
|
|||
// draw the atlas itself
|
||||
.spawn(SpriteComponents {
|
||||
material: materials.add(texture_atlas_texture.into()),
|
||||
translation: Vec3::new(-300.0, 0., 0.0).into(),
|
||||
transform: Transform::from_translation(Vec3::new(-300.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
||||
translation: Translation::new(0.0, 1.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 1.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// sphere
|
||||
|
@ -36,17 +36,17 @@ fn setup(
|
|||
radius: 0.5,
|
||||
})),
|
||||
material: materials.add(Color::rgb(0.1, 0.4, 0.8).into()),
|
||||
translation: Translation::new(1.5, 1.5, 1.5),
|
||||
transform: Transform::from_translation(Vec3::new(1.5, 1.5, 1.5)),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 8.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(-3.0, 5.0, 8.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -23,7 +23,7 @@ fn setup(
|
|||
.unwrap(),
|
||||
// create a material for the mesh
|
||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
||||
translation: Translation::new(-1.5, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(-1.5, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// mesh
|
||||
|
@ -34,17 +34,17 @@ fn setup(
|
|||
.unwrap(),
|
||||
// create a material for the mesh
|
||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
||||
translation: Translation::new(1.5, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(1.5, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 5.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(-2.0, 2.0, 6.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -27,12 +27,12 @@ fn setup(
|
|||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 8.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(-3.0, 3.0, 5.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -15,9 +15,9 @@ fn main() {
|
|||
struct Rotator;
|
||||
|
||||
/// rotates the parent, which will result in the child also rotating
|
||||
fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Rotation)>) {
|
||||
for (_rotator, mut rotation) in &mut query.iter() {
|
||||
rotation.0 *= Quat::from_rotation_x(3.0 * time.delta_seconds);
|
||||
fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Transform)>) {
|
||||
for (_rotator, mut transform) in &mut query.iter() {
|
||||
transform.rotate(Quat::from_rotation_x(3.0 * time.delta_seconds));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: cube_handle,
|
||||
material: cube_material_handle,
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.with(Rotator)
|
||||
|
@ -47,18 +47,18 @@ fn setup(
|
|||
parent.spawn(PbrComponents {
|
||||
mesh: cube_handle,
|
||||
material: cube_material_handle,
|
||||
translation: Translation::new(0.0, 0.0, 3.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 3.0)),
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 5.0, -4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, -4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(5.0, 10.0, 10.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -21,11 +21,11 @@ fn main() {
|
|||
fn move_cubes(
|
||||
time: Res<Time>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
mut query: Query<(&mut Translation, &Handle<StandardMaterial>)>,
|
||||
mut query: Query<(&mut Transform, &Handle<StandardMaterial>)>,
|
||||
) {
|
||||
for (mut translation, material_handle) in &mut query.iter() {
|
||||
for (mut transform, material_handle) in &mut query.iter() {
|
||||
let material = materials.get_mut(&material_handle).unwrap();
|
||||
translation.0 += Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds;
|
||||
transform.translate(Vec3::new(1.0, 0.0, 0.0) * time.delta_seconds);
|
||||
material.albedo =
|
||||
Color::BLUE * Vec3::splat((3.0 * time.seconds_since_startup as f32).sin());
|
||||
}
|
||||
|
@ -39,12 +39,12 @@ fn setup(
|
|||
commands
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, -4.0, 5.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(0.0, 15.0, 150.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 1.0),
|
||||
|
@ -65,11 +65,11 @@ fn setup(
|
|||
),
|
||||
..Default::default()
|
||||
}),
|
||||
translation: Translation::new(
|
||||
transform: Transform::from_translation(Vec3::new(
|
||||
rng.gen_range(-50.0, 50.0),
|
||||
rng.gen_range(-50.0, 50.0),
|
||||
0.0,
|
||||
),
|
||||
)),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: quad_handle,
|
||||
material: material_handle,
|
||||
translation: Translation::new(0.0, 0.0, 1.5),
|
||||
rotation: Rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.5))
|
||||
.with_rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
draw: Draw {
|
||||
is_transparent: true,
|
||||
..Default::default()
|
||||
|
@ -71,8 +71,8 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: quad_handle,
|
||||
material: red_material_handle,
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
rotation: Rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0))
|
||||
.with_rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
draw: Draw {
|
||||
is_transparent: true,
|
||||
..Default::default()
|
||||
|
@ -83,8 +83,8 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: quad_handle,
|
||||
material: blue_material_handle,
|
||||
translation: Translation::new(0.0, 0.0, -1.5),
|
||||
rotation: Rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -1.5))
|
||||
.with_rotation(Quat::from_rotation_x(-std::f32::consts::PI / 5.0)),
|
||||
draw: Draw {
|
||||
is_transparent: true,
|
||||
..Default::default()
|
||||
|
@ -93,7 +93,7 @@ fn setup(
|
|||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(3.0, 5.0, 8.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -19,9 +19,9 @@ fn main() {
|
|||
struct Rotator;
|
||||
|
||||
/// rotates the parent, which will result in the child also rotating
|
||||
fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Rotation)>) {
|
||||
for (_rotator, mut rotation) in &mut query.iter() {
|
||||
rotation.0 *= Quat::from_rotation_x(3.0 * time.delta_seconds);
|
||||
fn rotator_system(time: Res<Time>, mut query: Query<(&Rotator, &mut Transform)>) {
|
||||
for (_rotator, mut transform) in &mut query.iter() {
|
||||
transform.rotate(Quat::from_rotation_x(3.0 * time.delta_seconds));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ fn setup(
|
|||
shaded: false,
|
||||
..Default::default()
|
||||
}),
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.with(Rotator)
|
||||
|
@ -70,7 +70,7 @@ fn setup(
|
|||
shaded: false,
|
||||
..Default::default()
|
||||
}),
|
||||
translation: Translation::new(0.0, 3.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 3.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.spawn(PbrComponents {
|
||||
|
@ -79,13 +79,13 @@ fn setup(
|
|||
shaded: false,
|
||||
..Default::default()
|
||||
}),
|
||||
translation: Translation::new(0.0, -3.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -3.0, 0.0)),
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(5.0, 10.0, 10.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -49,31 +49,31 @@ fn setup(
|
|||
.spawn(PbrComponents {
|
||||
mesh: monkey_handle,
|
||||
material: material_handle,
|
||||
translation: Translation::new(-3.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(-3.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// cube
|
||||
.spawn(PbrComponents {
|
||||
mesh: cube_handle,
|
||||
material: material_handle,
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// sphere
|
||||
.spawn(PbrComponents {
|
||||
mesh: sphere_handle,
|
||||
material: material_handle,
|
||||
translation: Translation::new(3.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(3.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 5.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(0.0, 3.0, 10.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -42,12 +42,12 @@ fn setup(
|
|||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 5.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(2.0, 2.0, 6.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -15,8 +15,7 @@ fn spawn_system(
|
|||
commands
|
||||
.spawn(SpriteComponents {
|
||||
material,
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
scale: Scale(0.1),
|
||||
transform: Transform::from_scale(Vec3::one() * 0.1),
|
||||
..Default::default()
|
||||
})
|
||||
.with(Velocity(
|
||||
|
@ -26,7 +25,7 @@ fn spawn_system(
|
|||
}
|
||||
|
||||
// Move sprites according to their velocity
|
||||
fn move_system(pool: Res<ComputeTaskPool>, mut sprites: Query<(&mut Translation, &Velocity)>) {
|
||||
fn move_system(pool: Res<ComputeTaskPool>, mut sprites: Query<(&mut Transform, &Velocity)>) {
|
||||
// Compute the new location of each sprite in parallel on the
|
||||
// ComputeTaskPool using batches of 32 sprties
|
||||
//
|
||||
|
@ -35,16 +34,19 @@ fn move_system(pool: Res<ComputeTaskPool>, mut sprites: Query<(&mut Translation,
|
|||
// elements will not typically be faster than just using a normal Iterator.
|
||||
// See the ParallelIterator documentation for more information on when
|
||||
// to use or not use ParallelIterator over a normal Iterator.
|
||||
sprites.iter().par_iter(32).for_each(&pool, |(mut t, v)| {
|
||||
t.0 += v.0.extend(0.0);
|
||||
});
|
||||
sprites
|
||||
.iter()
|
||||
.par_iter(32)
|
||||
.for_each(&pool, |(mut transform, velocity)| {
|
||||
transform.translate(velocity.0.extend(0.0));
|
||||
});
|
||||
}
|
||||
|
||||
// Bounce sprties outside the window
|
||||
fn bounce_system(
|
||||
pool: Res<ComputeTaskPool>,
|
||||
windows: Res<Windows>,
|
||||
mut sprites: Query<(&Translation, &mut Velocity)>,
|
||||
mut sprites: Query<(&Transform, &mut Velocity)>,
|
||||
) {
|
||||
let Window { width, height, .. } = windows.get_primary().expect("No primary window");
|
||||
let left = *width as f32 / -2.0;
|
||||
|
@ -57,7 +59,12 @@ fn bounce_system(
|
|||
// ParallelIterator, since negating a vector is very inexpensive.
|
||||
.par_iter(32)
|
||||
// Filter out sprites that don't need to be bounced
|
||||
.filter(|(t, _)| !(left < t.x() && t.x() < right && bottom < t.y() && t.y() < top))
|
||||
.filter(|(transform, _)| {
|
||||
!(left < transform.translation().x()
|
||||
&& transform.translation().x() < right
|
||||
&& bottom < transform.translation().y()
|
||||
&& transform.translation().y() < top)
|
||||
})
|
||||
// For simplicity, just reverse the velocity; don't use realistic bounces
|
||||
.for_each(&pool, |(_, mut v)| {
|
||||
v.0 = -v.0;
|
||||
|
|
|
@ -48,7 +48,7 @@ fn setup(
|
|||
// paddle
|
||||
.spawn(SpriteComponents {
|
||||
material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()),
|
||||
translation: Translation(Vec3::new(0.0, -215.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -215.0, 0.0)),
|
||||
sprite: Sprite::new(Vec2::new(120.0, 30.0)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -57,7 +57,7 @@ fn setup(
|
|||
// ball
|
||||
.spawn(SpriteComponents {
|
||||
material: materials.add(Color::rgb(0.8, 0.2, 0.2).into()),
|
||||
translation: Translation(Vec3::new(0.0, -50.0, 1.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -50.0, 1.0)),
|
||||
sprite: Sprite::new(Vec2::new(30.0, 30.0)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -95,7 +95,7 @@ fn setup(
|
|||
// left
|
||||
.spawn(SpriteComponents {
|
||||
material: wall_material,
|
||||
translation: Translation(Vec3::new(-bounds.x() / 2.0, 0.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(-bounds.x() / 2.0, 0.0, 0.0)),
|
||||
sprite: Sprite::new(Vec2::new(wall_thickness, bounds.y() + wall_thickness)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -103,7 +103,7 @@ fn setup(
|
|||
// right
|
||||
.spawn(SpriteComponents {
|
||||
material: wall_material,
|
||||
translation: Translation(Vec3::new(bounds.x() / 2.0, 0.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(bounds.x() / 2.0, 0.0, 0.0)),
|
||||
sprite: Sprite::new(Vec2::new(wall_thickness, bounds.y() + wall_thickness)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -111,7 +111,7 @@ fn setup(
|
|||
// bottom
|
||||
.spawn(SpriteComponents {
|
||||
material: wall_material,
|
||||
translation: Translation(Vec3::new(0.0, -bounds.y() / 2.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -bounds.y() / 2.0, 0.0)),
|
||||
sprite: Sprite::new(Vec2::new(bounds.x() + wall_thickness, wall_thickness)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -119,7 +119,7 @@ fn setup(
|
|||
// top
|
||||
.spawn(SpriteComponents {
|
||||
material: wall_material,
|
||||
translation: Translation(Vec3::new(0.0, bounds.y() / 2.0, 0.0)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, bounds.y() / 2.0, 0.0)),
|
||||
sprite: Sprite::new(Vec2::new(bounds.x() + wall_thickness, wall_thickness)),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -147,7 +147,7 @@ fn setup(
|
|||
.spawn(SpriteComponents {
|
||||
material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()),
|
||||
sprite: Sprite::new(brick_size),
|
||||
translation: Translation(brick_position),
|
||||
transform: Transform::from_translation(brick_position),
|
||||
..Default::default()
|
||||
})
|
||||
.with(Collider::Scorable);
|
||||
|
@ -158,9 +158,9 @@ fn setup(
|
|||
fn paddle_movement_system(
|
||||
time: Res<Time>,
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
mut query: Query<(&Paddle, &mut Translation)>,
|
||||
mut query: Query<(&Paddle, &mut Transform)>,
|
||||
) {
|
||||
for (paddle, mut translation) in &mut query.iter() {
|
||||
for (paddle, mut transform) in &mut query.iter() {
|
||||
let mut direction = 0.0;
|
||||
if keyboard_input.pressed(KeyCode::Left) {
|
||||
direction -= 1.0;
|
||||
|
@ -170,19 +170,24 @@ fn paddle_movement_system(
|
|||
direction += 1.0;
|
||||
}
|
||||
|
||||
*translation.0.x_mut() += time.delta_seconds * direction * paddle.speed;
|
||||
transform.translate(Vec3::unit_x() * time.delta_seconds * direction * paddle.speed);
|
||||
|
||||
// bound the paddle within the walls
|
||||
*translation.0.x_mut() = f32::max(-380.0, f32::min(380.0, translation.0.x()));
|
||||
let translation = transform.translation();
|
||||
transform.set_translation(Vec3::new(
|
||||
f32::max(-380.0, f32::min(380.0, translation.x())),
|
||||
translation.y(),
|
||||
translation.z(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn ball_movement_system(time: Res<Time>, mut ball_query: Query<(&Ball, &mut Translation)>) {
|
||||
fn ball_movement_system(time: Res<Time>, mut ball_query: Query<(&Ball, &mut Transform)>) {
|
||||
// clamp the timestep to stop the ball from escaping when the game starts
|
||||
let delta_seconds = f32::min(0.2, time.delta_seconds);
|
||||
|
||||
for (ball, mut translation) in &mut ball_query.iter() {
|
||||
translation.0 += ball.velocity * delta_seconds;
|
||||
for (ball, mut transform) in &mut ball_query.iter() {
|
||||
transform.translate(ball.velocity * delta_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,16 +200,21 @@ fn scoreboard_system(scoreboard: Res<Scoreboard>, mut query: Query<&mut Text>) {
|
|||
fn ball_collision_system(
|
||||
mut commands: Commands,
|
||||
mut scoreboard: ResMut<Scoreboard>,
|
||||
mut ball_query: Query<(&mut Ball, &Translation, &Sprite)>,
|
||||
mut collider_query: Query<(Entity, &Collider, &Translation, &Sprite)>,
|
||||
mut ball_query: Query<(&mut Ball, &Transform, &Sprite)>,
|
||||
mut collider_query: Query<(Entity, &Collider, &Transform, &Sprite)>,
|
||||
) {
|
||||
for (mut ball, ball_translation, sprite) in &mut ball_query.iter() {
|
||||
for (mut ball, ball_transform, sprite) in &mut ball_query.iter() {
|
||||
let ball_size = sprite.size;
|
||||
let velocity = &mut ball.velocity;
|
||||
|
||||
// check collision with walls
|
||||
for (collider_entity, collider, translation, sprite) in &mut collider_query.iter() {
|
||||
let collision = collide(ball_translation.0, ball_size, translation.0, sprite.size);
|
||||
for (collider_entity, collider, transform, sprite) in &mut collider_query.iter() {
|
||||
let collision = collide(
|
||||
ball_transform.translation(),
|
||||
ball_size,
|
||||
transform.translation(),
|
||||
sprite.size,
|
||||
);
|
||||
if let Some(collision) = collision {
|
||||
// scorable colliders should be despawned and increment the scoreboard on collision
|
||||
if let Collider::Scorable = *collider {
|
||||
|
|
|
@ -102,13 +102,13 @@ fn setup(
|
|||
..Default::default()
|
||||
},
|
||||
)]),
|
||||
translation: Translation::new(0.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.with(material)
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(3.0, 5.0, -8.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -123,7 +123,7 @@ fn setup(
|
|||
..Default::default()
|
||||
},
|
||||
)]),
|
||||
translation: Translation::new(-2.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(-2.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.with(green_material)
|
||||
|
@ -149,13 +149,13 @@ fn setup(
|
|||
..Default::default()
|
||||
},
|
||||
)]),
|
||||
translation: Translation::new(2.0, 0.0, 0.0),
|
||||
transform: Transform::from_translation(Vec3::new(2.0, 0.0, 0.0)),
|
||||
..Default::default()
|
||||
})
|
||||
.with(blue_material)
|
||||
// camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(3.0, 5.0, -8.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
|
@ -173,12 +173,12 @@ fn setup(
|
|||
})
|
||||
// light
|
||||
.spawn(LightComponents {
|
||||
translation: Translation::new(4.0, 5.0, 4.0),
|
||||
transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
|
||||
..Default::default()
|
||||
})
|
||||
// main camera
|
||||
.spawn(Camera3dComponents {
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(0.0, 0.0, 6.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
@ -192,7 +192,7 @@ fn setup(
|
|||
window: window_id,
|
||||
..Default::default()
|
||||
},
|
||||
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||
transform: Transform::new(Mat4::face_toward(
|
||||
Vec3::new(6.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 0.0, 0.0),
|
||||
Vec3::new(0.0, 1.0, 0.0),
|
||||
|
|
Loading…
Reference in a new issue