pub struct GridTransform {
pub origin: DVec3,
pub rotation: DQuat,
pub voxel_world_size: f64,
}Expand description
f64 world placement of one grid: position + orientation.
origin is the grid’s local-space origin in world coords — a
grid-local point p (in voxel units) maps to
origin + rotation * (p * voxel_world_size).
SC — voxel_world_size is the grid’s world units per voxel
(1.0 = the classic 1:1). A coarse planet grid might use 4.0
(big voxels) and a finely detailed ship 0.25, so they coexist at
the right relative sizes in one scene. The scale enters ONLY at the
world↔grid-local boundary (crate::world_to_grid_local /
crate::grid_local_to_world, Scene::raycast, shadows); the
per-grid voxel storage, marchers and bakes are scale-agnostic. Only
a uniform scalar is supported (anisotropic scale would break the
ray-length invariant the raycast/shadow t conversion relies on).
Fields§
§origin: DVec3The grid’s local-space origin, in world coordinates.
rotation: DQuatThe grid’s orientation about origin.
voxel_world_size: f64SC — world units per voxel (1.0 = 1:1). See the type docs.
#[serde(skip)]: this field is NOT part of GridTransform’s
wire form (which stays frozen for snapshot back-compat). The
snapshot persists it as a trailing field on
crate::snapshot::GridSnapshot instead, so old saves — which
predate it — still load (defaulting to 1.0). A standalone
GridTransform deserialize also defaults it to 1.0.
Implementations§
Source§impl GridTransform
impl GridTransform
Sourcepub fn identity() -> Self
pub fn identity() -> Self
Identity transform at world origin, 1 world unit per voxel. Useful as a default for the first grid added to an otherwise empty scene.
Examples found in repository?
29fn build_world() -> Scene {
30 let mut scene = Scene::new();
31 let id = scene.add_grid(GridTransform::identity());
32 let g = scene.grid_mut(id).expect("grid");
33 // Ground slab: surface plane at z = 100 (+z is down, so the
34 // slab fills downward).
35 g.set_rect(
36 IVec3::new(20, 20, 100),
37 IVec3::new(140, 140, 120),
38 Some(VoxColor::rgb(0x4d, 0x8a, 0x3a)),
39 );
40 // A 1-voxel ledge to step onto, and a wall to slide along.
41 g.set_rect(
42 IVec3::new(90, 20, 99),
43 IVec3::new(140, 140, 99),
44 Some(VoxColor::rgb(0x77, 0x66, 0x55)),
45 );
46 g.set_rect(
47 IVec3::new(60, 70, 60),
48 IVec3::new(62, 140, 99),
49 Some(VoxColor::rgb(0x88, 0x44, 0x44)),
50 );
51 // A water curtain the veto lets the body wade through. Two
52 // format facts (both pinned as engine tests): pass-through
53 // geometry works up to 2 voxels thick — thicker walls grow a
54 // colourless UnexposedSolid core no veto can classify — and
55 // must sit ≥ 1 voxel inside the chunk (edge voxels lose their
56 // side colours).
57 g.set_rect(IVec3::new(40, 40, 80), IVec3::new(41, 60, 99), Some(WATER));
58 scene
59}
60
61fn main() {
62 let scene = build_world();
63
64 // ANCHOR: setup
65 // A walking body: a feet-positioned collision box, f64 world.
66 // Distances are voxels, times seconds; +z is DOWN, so gravity is
67 // positive and a jump impulse negative.
68 let mut body = CharacterBody::new(CharacterDef {
69 radius: 0.4, // xy half-extent of the box
70 height: 1.8, // feet → head (toward -z)
71 eye_height: 1.62, // feet → camera anchor
72 step_up: 1.05, // auto-step ledges up to 1 voxel
73 solidity: Solidity {
74 bedrock_blocks: false, // match your renderer's policy
75 passable: Some(water_passes),
76 },
77 ..CharacterDef::default()
78 });
79 body.teleport(DVec3::new(50.0, 50.0, 95.0)); // FEET position
80 // ANCHOR_END: setup
81
82 // ANCHOR: frame
83 // Per frame: build a wish direction from input (unit-length or
84 // zero — walk() clamps), call walk() EVERY frame (a zero wish is
85 // what stops the body), then anchor the camera at the eye.
86 let dt = 1.0 / 60.0;
87 for frame in 0..480 {
88 let input = WalkInput {
89 wish: DVec3::new(1.0, 0.2, 0.0), // toward the ledge
90 jump: frame == 120, // one hop on the way
91 ..WalkInput::default() // sink (WT.1) + future fields
92 };
93 body.walk(&scene, dt, input);
94 }
95 let eye = body.eye_pos(); // = Camera::from_yaw_pitch(eye.into(), yaw, pitch)
96 // ANCHOR_END: frame
97
98 // The trajectory the walk above promises, pinned:
99 assert!(body.on_ground(), "settled after the hop");
100 // It fell to the floor plane, then stepped up the 1-voxel ledge
101 // (surface z = 99) while walking +x.
102 assert!(body.pos().x > 90.0, "reached the ledge region");
103 assert!(
104 (body.pos().z - 99.0).abs() < 0.01,
105 "standing on the ledge, feet at {}",
106 body.pos().z
107 );
108 assert!(eye.z < body.pos().z, "the eye is above the feet (-z is up)");
109
110 // Fly mode is the demos' free camera: no gravity, full-3D wish,
111 // instant start/stop, still sliding along walls.
112 body.set_mode(MoveMode::Fly);
113 body.walk(&scene, dt, WalkInput::default());
114 assert_eq!(body.vel(), DVec3::ZERO, "fly idles in place");
115
116 // The water curtain from `build_world` is passable: probe the
117 // veto directly (the same query walk() uses).
118 let wading = roxlap_scene::box_overlaps_solid(
119 &scene,
120 DVec3::new(40.2, 50.0, 90.0),
121 DVec3::new(40.8, 50.6, 91.8),
122 body.def().solidity,
123 );
124 assert!(!wading, "water is passable under the veto");
125
126 swim_demo();
127
128 println!("book_controller: all controller assertions hold");
129}
130
131/// WT — the water + swimming section's snippets: a deep pool the body
132/// falls into, floats in, dives through and breaches out of.
133fn swim_demo() {
134 // ANCHOR: water
135 // Physics water is a WaterVolume on the grid — a grid-local voxel
136 // AABB whose TOP face (min z — +z is down) is the surface. It is
137 // independent of the voxels: fill the same region with a
138 // volumetric-material shell for the visuals, or don't.
139 let mut scene = Scene::new();
140 let id = scene.add_grid(GridTransform::identity());
141 let g = scene.grid_mut(id).expect("grid");
142 // Basin floor, then 20 voxels of water above it (surface z = 100).
143 g.set_rect(
144 IVec3::new(20, 20, 120),
145 IVec3::new(140, 140, 130),
146 Some(VoxColor::rgb(0x50, 0x90, 0x50)),
147 );
148 g.add_water_volume(IVec3::new(20, 20, 100), IVec3::new(140, 140, 119));
149
150 // A Walk-mode body dropped in swims AUTOMATICALLY once submerged
151 // past `swim_enter_frac` of its height: buoyancy floats it to a
152 // bob at the surface, `jump` strokes up, `sink` strokes down, and
153 // a jump with the head above water breaches.
154 let mut body = CharacterBody::new(CharacterDef::default());
155 body.teleport(DVec3::new(80.0, 80.0, 115.0)); // deep in the pool
156 for _ in 0..600 {
157 body.walk(&scene, 1.0 / 60.0, WalkInput::default());
158 }
159 assert!(body.is_swimming(), "floated to the surface bob");
160 assert!(!body.eye_in_water(&scene), "bobbing: the camera is dry");
161
162 // Dive: hold `sink`. The submerged EYE is the hook for the
163 // underwater feel — drive the WT.2 frame tint and the WT.3
164 // listener lowpass from this one flag.
165 for _ in 0..90 {
166 body.walk(
167 &scene,
168 1.0 / 60.0,
169 WalkInput {
170 sink: true,
171 ..WalkInput::default()
172 },
173 );
174 }
175 assert!(body.eye_in_water(&scene), "diving: tint + muffle now");
176 // ANCHOR_END: water
177}Sourcepub fn at(origin: DVec3) -> Self
pub fn at(origin: DVec3) -> Self
Axis-aligned grid placed at origin with no rotation, 1 world
unit per voxel.
Examples found in repository?
83fn main() {
84 // ANCHOR: scene_grids
85 let mut scene = Scene::new();
86 // A static "world" grid at the origin…
87 let ground_id = scene.add_grid(GridTransform::at(DVec3::ZERO));
88 // …and a second grid placed and rotated independently — its own
89 // f64 world position + quaternion, same chunked voxel payload.
90 let ship_id = scene.add_grid(GridTransform {
91 origin: DVec3::new(300.0, -80.0, -40.0),
92 rotation: DQuat::from_rotation_z(0.5),
93 voxel_world_size: 1.0,
94 });
95 // Object grids should not paint their own (grid-local, rotating)
96 // sky — leave the sky to the world grid.
97 scene.grid_mut(ship_id).expect("just added").render_sky = false;
98 // ANCHOR_END: scene_grids
99
100 // ANCHOR: edits
101 let ground = scene.grid_mut(ground_id).expect("just added");
102 // Solid slab: grid-local voxel coords, inclusive on both ends,
103 // decomposed across as many chunks as it spans (here 4×4).
104 ground.set_rect(
105 IVec3::new(-200, -200, 200),
106 IVec3::new(199, 199, 254),
107 Some(GRASS),
108 );
109 // `Some(colour)` inserts, `None` carves back to air.
110 ground.set_sphere(IVec3::new(0, 0, 195), 12, Some(STONE));
111 ground.set_rect(IVec3::new(-3, -200, 190), IVec3::new(3, 199, 196), None);
112 // ANCHOR_END: edits
113
114 // ANCHOR: queries
115 // Solid tests: inside the slab, then inside the carved tunnel.
116 assert!(ground.voxel_solid(IVec3::new(0, 0, 210)));
117 assert!(!ground.voxel_solid(IVec3::new(0, 100, 193)));
118 // Colour queries answer on surface voxels; deep interior cells
119 // are untextured in the slab format and read as `None`.
120 assert_eq!(ground.voxel_color(IVec3::new(50, 50, 200)), Some(GRASS));
121 // ANCHOR_END: queries
122
123 // ANCHOR: recolour
124 // GOTCHA: inserting over already-solid voxels does NOT repaint
125 // them — span insertion only fills air. Recolour = carve, then
126 // insert.
127 let (lo, hi) = (IVec3::new(20, 20, 200), IVec3::new(24, 24, 204));
128 ground.set_rect(lo, hi, Some(RED));
129 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(GRASS)); // unchanged!
130 ground.set_rect(lo, hi, None); // carve…
131 ground.set_rect(lo, hi, Some(RED)); // …then insert
132 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
133 // ANCHOR_END: recolour
134
135 // ANCHOR: colfunc
136 // A carve exposes fresh interior walls; the plain edits paint
137 // them colour 0 (black). The `_with_colfunc` variants ask a
138 // closure instead — it sees grid-local coordinates, so gradients
139 // stay continuous across chunk seams. Here: a crater whose walls
140 // darken with depth.
141 ground.set_sphere_with_colfunc(IVec3::new(60, 60, 200), 8, SpanOp::Carve, |_x, _y, z| {
142 let depth = (z - 192).clamp(0, 15) as u8;
143 VoxColor::rgb(0x6b, 0x40 + depth * 3, 0x2f)
144 });
145 // ANCHOR_END: colfunc
146
147 // ANCHOR: snapshot
148 // Name grids before saving: ids survive the round-trip, but the
149 // generator / store hooks are host code and cannot be serialised
150 // — the name is your key for rebinding them after a load.
151 scene.grid_mut(ground_id).expect("ground exists").name = Some("ground".into());
152 let bytes = scene.save_snapshot(); // versioned envelope
153 let restored = Scene::load_snapshot(&bytes).expect("self-authored snapshot");
154 assert_eq!(restored.grid_count(), 2);
155 let (_, ground2) = restored
156 .grids()
157 .find(|(_, g)| g.name.as_deref() == Some("ground"))
158 .expect("rebind by name");
159 assert_eq!(ground2.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
160 // ANCHOR_END: snapshot
161
162 // ANCHOR: streaming
163 // Streaming: attach a generator + radii to a grid, then pump once
164 // per frame with the camera's world position. Chunks within
165 // `r_active` stream in; chunks beyond `r_evict` drop out; the band
166 // between is hysteresis so a camera hovering on a boundary
167 // doesn't thrash.
168 let stream_id = scene.add_grid(GridTransform::at(DVec3::new(0.0, 4096.0, 0.0)));
169 let store = Arc::new(MemoryStore::default());
170 let grid = scene.grid_mut(stream_id).expect("just added");
171 grid.set_generator(Some(Arc::new(FloorGenerator)));
172 grid.set_chunk_store(Some(store));
173 grid.stream_radius = StreamRadius::new(256.0, 384.0);
174
175 let camera_near = DVec3::new(0.0, 4096.0, 100.0);
176 scene.pump_streaming_sync(camera_near); // real games: `pump_streaming`
177 let grid = scene.grid(stream_id).expect("still there");
178 assert!(grid.chunk_count() > 0); // floor streamed in around the camera
179 assert!(grid.voxel_solid(IVec3::new(5, 5, 240)));
180 // ANCHOR_END: streaming
181
182 // ANCHOR: streaming_edit
183 // Edit the streamed floor, walk far away, come back. The active
184 // set follows the camera: the old region evicts (edited chunks
185 // are handed to the ChunkStore first) while a fresh set streams
186 // in around the new position. On return the store wins over the
187 // generator, so the edit survives; without a store, eviction
188 // would silently revert the chunk to generator output.
189 scene
190 .grid_mut(stream_id)
191 .expect("still there")
192 .set_voxel(IVec3::new(5, 5, 240), None); // dig a hole
193 scene.pump_streaming_sync(camera_near + DVec3::new(0.0, 100_000.0, 0.0));
194 let grid = scene.grid(stream_id).expect("still there");
195 assert!(grid.chunk(IVec3::ZERO).is_none()); // home chunk evicted…
196 assert!(grid.chunk_count() > 0); // …but the far region streamed in
197 scene.pump_streaming_sync(camera_near);
198 let grid = scene.grid(stream_id).expect("re-streamed");
199 // The hole survived evict + re-stream.
200 assert!(!grid.voxel_solid(IVec3::new(5, 5, 240)));
201 // ANCHOR_END: streaming_edit
202
203 // ANCHOR: grid_scale
204 // Per-grid scale: `voxel_world_size` is world units per voxel. A grid
205 // built with `at_scale(origin, 2.0)` has voxels twice world size — a
206 // coarse "planet" — while `0.25` gives a fine detail grid; both coexist
207 // at their true relative sizes. Only the world↔grid boundary scales:
208 // edits + queries stay in voxels, unchanged.
209 let mut scaled = Scene::new();
210 let planet = scaled.add_grid(GridTransform::at_scale(DVec3::ZERO, 2.0));
211 scaled
212 .grid_mut(planet)
213 .expect("just added")
214 // Same voxel edit API — grid-local coordinates.
215 .set_voxel(IVec3::new(5, 5, 10), Some(STONE));
216 // Grid-local voxel z=10 sits at WORLD z = 20 (10 voxels × 2.0). A world
217 // raycast down that column reports the grid-local voxel it hit AND a
218 // WORLD-space `t` — so hits across grids of different scale compare
219 // correctly (the raycaster marches voxels but returns world distance).
220 let hit = scaled
221 .raycast(DVec3::new(11.0, 11.0, 0.0), DVec3::new(0.0, 0.0, 1.0), 64.0)
222 .expect("ray hits the scaled voxel");
223 assert_eq!(hit.voxel, IVec3::new(5, 5, 10)); // grid-local, unscaled
224 assert!((hit.t - 20.0).abs() < 1e-4); // WORLD distance: 10 voxels × 2.0
225 // ANCHOR_END: grid_scale
226
227 println!("book_scene_graph: all scene-graph assertions hold");
228}Sourcepub fn at_scale(origin: DVec3, voxel_world_size: f64) -> Self
pub fn at_scale(origin: DVec3, voxel_world_size: f64) -> Self
SC — axis-aligned grid at origin with voxel_world_size world
units per voxel (no rotation). 1.0 = the classic 1:1.
voxel_world_size must be finite and > 0: it scales every
world↔grid boundary, and a 0 collapses the GPU marcher’s
chunk_dim to zero → floor(origin / 0) = NaN (garbage geometry),
worse than the CPU’s divide. Debug-asserted here; release builds
trust the caller.
Examples found in repository?
83fn main() {
84 // ANCHOR: scene_grids
85 let mut scene = Scene::new();
86 // A static "world" grid at the origin…
87 let ground_id = scene.add_grid(GridTransform::at(DVec3::ZERO));
88 // …and a second grid placed and rotated independently — its own
89 // f64 world position + quaternion, same chunked voxel payload.
90 let ship_id = scene.add_grid(GridTransform {
91 origin: DVec3::new(300.0, -80.0, -40.0),
92 rotation: DQuat::from_rotation_z(0.5),
93 voxel_world_size: 1.0,
94 });
95 // Object grids should not paint their own (grid-local, rotating)
96 // sky — leave the sky to the world grid.
97 scene.grid_mut(ship_id).expect("just added").render_sky = false;
98 // ANCHOR_END: scene_grids
99
100 // ANCHOR: edits
101 let ground = scene.grid_mut(ground_id).expect("just added");
102 // Solid slab: grid-local voxel coords, inclusive on both ends,
103 // decomposed across as many chunks as it spans (here 4×4).
104 ground.set_rect(
105 IVec3::new(-200, -200, 200),
106 IVec3::new(199, 199, 254),
107 Some(GRASS),
108 );
109 // `Some(colour)` inserts, `None` carves back to air.
110 ground.set_sphere(IVec3::new(0, 0, 195), 12, Some(STONE));
111 ground.set_rect(IVec3::new(-3, -200, 190), IVec3::new(3, 199, 196), None);
112 // ANCHOR_END: edits
113
114 // ANCHOR: queries
115 // Solid tests: inside the slab, then inside the carved tunnel.
116 assert!(ground.voxel_solid(IVec3::new(0, 0, 210)));
117 assert!(!ground.voxel_solid(IVec3::new(0, 100, 193)));
118 // Colour queries answer on surface voxels; deep interior cells
119 // are untextured in the slab format and read as `None`.
120 assert_eq!(ground.voxel_color(IVec3::new(50, 50, 200)), Some(GRASS));
121 // ANCHOR_END: queries
122
123 // ANCHOR: recolour
124 // GOTCHA: inserting over already-solid voxels does NOT repaint
125 // them — span insertion only fills air. Recolour = carve, then
126 // insert.
127 let (lo, hi) = (IVec3::new(20, 20, 200), IVec3::new(24, 24, 204));
128 ground.set_rect(lo, hi, Some(RED));
129 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(GRASS)); // unchanged!
130 ground.set_rect(lo, hi, None); // carve…
131 ground.set_rect(lo, hi, Some(RED)); // …then insert
132 assert_eq!(ground.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
133 // ANCHOR_END: recolour
134
135 // ANCHOR: colfunc
136 // A carve exposes fresh interior walls; the plain edits paint
137 // them colour 0 (black). The `_with_colfunc` variants ask a
138 // closure instead — it sees grid-local coordinates, so gradients
139 // stay continuous across chunk seams. Here: a crater whose walls
140 // darken with depth.
141 ground.set_sphere_with_colfunc(IVec3::new(60, 60, 200), 8, SpanOp::Carve, |_x, _y, z| {
142 let depth = (z - 192).clamp(0, 15) as u8;
143 VoxColor::rgb(0x6b, 0x40 + depth * 3, 0x2f)
144 });
145 // ANCHOR_END: colfunc
146
147 // ANCHOR: snapshot
148 // Name grids before saving: ids survive the round-trip, but the
149 // generator / store hooks are host code and cannot be serialised
150 // — the name is your key for rebinding them after a load.
151 scene.grid_mut(ground_id).expect("ground exists").name = Some("ground".into());
152 let bytes = scene.save_snapshot(); // versioned envelope
153 let restored = Scene::load_snapshot(&bytes).expect("self-authored snapshot");
154 assert_eq!(restored.grid_count(), 2);
155 let (_, ground2) = restored
156 .grids()
157 .find(|(_, g)| g.name.as_deref() == Some("ground"))
158 .expect("rebind by name");
159 assert_eq!(ground2.voxel_color(IVec3::new(22, 22, 200)), Some(RED));
160 // ANCHOR_END: snapshot
161
162 // ANCHOR: streaming
163 // Streaming: attach a generator + radii to a grid, then pump once
164 // per frame with the camera's world position. Chunks within
165 // `r_active` stream in; chunks beyond `r_evict` drop out; the band
166 // between is hysteresis so a camera hovering on a boundary
167 // doesn't thrash.
168 let stream_id = scene.add_grid(GridTransform::at(DVec3::new(0.0, 4096.0, 0.0)));
169 let store = Arc::new(MemoryStore::default());
170 let grid = scene.grid_mut(stream_id).expect("just added");
171 grid.set_generator(Some(Arc::new(FloorGenerator)));
172 grid.set_chunk_store(Some(store));
173 grid.stream_radius = StreamRadius::new(256.0, 384.0);
174
175 let camera_near = DVec3::new(0.0, 4096.0, 100.0);
176 scene.pump_streaming_sync(camera_near); // real games: `pump_streaming`
177 let grid = scene.grid(stream_id).expect("still there");
178 assert!(grid.chunk_count() > 0); // floor streamed in around the camera
179 assert!(grid.voxel_solid(IVec3::new(5, 5, 240)));
180 // ANCHOR_END: streaming
181
182 // ANCHOR: streaming_edit
183 // Edit the streamed floor, walk far away, come back. The active
184 // set follows the camera: the old region evicts (edited chunks
185 // are handed to the ChunkStore first) while a fresh set streams
186 // in around the new position. On return the store wins over the
187 // generator, so the edit survives; without a store, eviction
188 // would silently revert the chunk to generator output.
189 scene
190 .grid_mut(stream_id)
191 .expect("still there")
192 .set_voxel(IVec3::new(5, 5, 240), None); // dig a hole
193 scene.pump_streaming_sync(camera_near + DVec3::new(0.0, 100_000.0, 0.0));
194 let grid = scene.grid(stream_id).expect("still there");
195 assert!(grid.chunk(IVec3::ZERO).is_none()); // home chunk evicted…
196 assert!(grid.chunk_count() > 0); // …but the far region streamed in
197 scene.pump_streaming_sync(camera_near);
198 let grid = scene.grid(stream_id).expect("re-streamed");
199 // The hole survived evict + re-stream.
200 assert!(!grid.voxel_solid(IVec3::new(5, 5, 240)));
201 // ANCHOR_END: streaming_edit
202
203 // ANCHOR: grid_scale
204 // Per-grid scale: `voxel_world_size` is world units per voxel. A grid
205 // built with `at_scale(origin, 2.0)` has voxels twice world size — a
206 // coarse "planet" — while `0.25` gives a fine detail grid; both coexist
207 // at their true relative sizes. Only the world↔grid boundary scales:
208 // edits + queries stay in voxels, unchanged.
209 let mut scaled = Scene::new();
210 let planet = scaled.add_grid(GridTransform::at_scale(DVec3::ZERO, 2.0));
211 scaled
212 .grid_mut(planet)
213 .expect("just added")
214 // Same voxel edit API — grid-local coordinates.
215 .set_voxel(IVec3::new(5, 5, 10), Some(STONE));
216 // Grid-local voxel z=10 sits at WORLD z = 20 (10 voxels × 2.0). A world
217 // raycast down that column reports the grid-local voxel it hit AND a
218 // WORLD-space `t` — so hits across grids of different scale compare
219 // correctly (the raycaster marches voxels but returns world distance).
220 let hit = scaled
221 .raycast(DVec3::new(11.0, 11.0, 0.0), DVec3::new(0.0, 0.0, 1.0), 64.0)
222 .expect("ray hits the scaled voxel");
223 assert_eq!(hit.voxel, IVec3::new(5, 5, 10)); // grid-local, unscaled
224 assert!((hit.t - 20.0).abs() < 1e-4); // WORLD distance: 10 voxels × 2.0
225 // ANCHOR_END: grid_scale
226
227 println!("book_scene_graph: all scene-graph assertions hold");
228}Trait Implementations§
Source§impl Clone for GridTransform
impl Clone for GridTransform
Source§fn clone(&self) -> GridTransform
fn clone(&self) -> GridTransform
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for GridTransform
Source§impl Debug for GridTransform
impl Debug for GridTransform
Source§impl Default for GridTransform
impl Default for GridTransform
Source§impl<'de> Deserialize<'de> for GridTransform
impl<'de> Deserialize<'de> for GridTransform
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for GridTransform
impl PartialEq for GridTransform
Source§impl Serialize for GridTransform
impl Serialize for GridTransform
impl StructuralPartialEq for GridTransform
Auto Trait Implementations§
impl Freeze for GridTransform
impl RefUnwindSafe for GridTransform
impl Send for GridTransform
impl Sync for GridTransform
impl Unpin for GridTransform
impl UnsafeUnpin for GridTransform
impl UnwindSafe for GridTransform
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more