fmc/bevy_extensions/f64_transform/mod.rs
1#![warn(missing_docs)]
2/// The basic components of the transform crate
3mod components;
4mod systems;
5
6use bevy::hierarchy::ValidParentCheckPlugin;
7use bevy::prelude::*;
8pub use components::{GlobalTransform, Transform};
9
10/// A [`Bundle`] of the [`Transform`] and [`GlobalTransform`]
11/// [`Component`](bevy_ecs::component::Component)s, which describe the position of an entity.
12///
13/// * To place or move an entity, you should set its [`Transform`].
14/// * To get the global transform of an entity, you should get its [`GlobalTransform`].
15/// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
16/// * You may use the [`TransformBundle`] to guarantee this.
17///
18/// ## [`Transform`] and [`GlobalTransform`]
19///
20/// [`Transform`] is the position of an entity relative to its parent position, or the reference
21/// frame if it doesn't have a parent.
22///
23/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
24///
25/// [`GlobalTransform`] is updated from [`Transform`] in the system
26/// [`transform_propagate_system`].
27///
28/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
29/// update the [`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
30/// before the [`GlobalTransform`] is updated.
31#[derive(Bundle, Clone, Copy, Debug, Default)]
32pub struct TransformBundle {
33 /// The transform of the entity.
34 pub local: Transform,
35 /// The global transform of the entity.
36 pub global: GlobalTransform,
37}
38
39impl TransformBundle {
40 /// An identity [`TransformBundle`] with no translation, rotation, and a scale of 1 on all axes.
41 pub const IDENTITY: Self = TransformBundle {
42 local: Transform::IDENTITY,
43 global: GlobalTransform::IDENTITY,
44 };
45
46 /// Creates a new [`TransformBundle`] from a [`Transform`].
47 ///
48 /// This initializes [`GlobalTransform`] as identity, to be updated later by the
49 /// [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate) stage.
50 #[inline]
51 pub const fn from_transform(transform: Transform) -> Self {
52 TransformBundle {
53 local: transform,
54 ..Self::IDENTITY
55 }
56 }
57}
58
59impl From<Transform> for TransformBundle {
60 #[inline]
61 fn from(transform: Transform) -> Self {
62 Self::from_transform(transform)
63 }
64}
65/// Label enum for the systems relating to transform propagation
66#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
67pub enum TransformSystem {
68 /// Propagates changes in transform to children's [`GlobalTransform`](crate::components::GlobalTransform)
69 TransformPropagate,
70}
71
72/// The base plugin for handling [`Transform`] components
73#[derive(Default)]
74pub struct TransformPlugin;
75
76impl Plugin for TransformPlugin {
77 fn build(&self, app: &mut App) {
78 // A set for `propagate_transforms` to mark it as ambiguous with `sync_simple_transforms`.
79 // Used instead of the `SystemTypeSet` as that would not allow multiple instances of the system.
80 #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
81 struct PropagateTransformsSet;
82
83 app.register_type::<Transform>()
84 .register_type::<GlobalTransform>()
85 .add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
86 .configure_sets(
87 PostStartup,
88 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
89 )
90 // add transform systems to startup so the first update is "correct"
91 .add_systems(
92 PostStartup,
93 (
94 systems::sync_simple_transforms
95 .in_set(TransformSystem::TransformPropagate)
96 // FIXME: https://github.com/bevyengine/bevy/issues/4381
97 // These systems cannot access the same entities,
98 // due to subtle query filtering that is not yet correctly computed in the ambiguity detector
99 .ambiguous_with(PropagateTransformsSet),
100 systems::propagate_transforms.in_set(PropagateTransformsSet),
101 ),
102 )
103 .configure_sets(
104 PostUpdate,
105 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),
106 )
107 .add_systems(
108 PostUpdate,
109 (
110 systems::sync_simple_transforms
111 .in_set(TransformSystem::TransformPropagate)
112 .ambiguous_with(PropagateTransformsSet),
113 systems::propagate_transforms.in_set(PropagateTransformsSet),
114 ),
115 );
116 }
117}