docs: panopticon auto-update for snow_trail
This commit is contained in:
@@ -42,16 +42,24 @@ pub struct CameraTransitionIntent {
|
||||
}
|
||||
|
||||
// systems/camera.rs - consumer
|
||||
pub fn camera_intent_system(world: &mut World) {
|
||||
let transition_entities: Vec<EntityHandle> = world.camera_transition_intents.all();
|
||||
pub fn camera_intent_system(
|
||||
follow_player_intents: &mut Storage<FollowPlayerIntent>,
|
||||
stop_following_intents: &mut Storage<StopFollowingIntent>,
|
||||
camera_transition_intents: &mut Storage<CameraTransitionIntent>,
|
||||
follows: &mut Storage<FollowComponent>,
|
||||
transforms: &mut Storage<Transform>,
|
||||
cameras: &mut Storage<CameraComponent>,
|
||||
player_tags: &Storage<()>,
|
||||
camera_transitions: &mut Storage<CameraTransition>,
|
||||
) {
|
||||
let transition_entities: Vec<EntityHandle> = camera_transition_intents.all();
|
||||
for entity in transition_entities {
|
||||
let duration = world
|
||||
.camera_transition_intents
|
||||
let duration = camera_transition_intents
|
||||
.get(entity)
|
||||
.map(|i| i.duration)
|
||||
.unwrap_or(0.5);
|
||||
start_camera_transition(world, entity, duration);
|
||||
world.camera_transition_intents.remove(entity); // consumed
|
||||
start_camera_transition(camera_transitions, transforms, cameras, entity, duration);
|
||||
camera_transition_intents.remove(entity);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -135,18 +143,17 @@ state_machine.add_transition::<IdleState, WalkingState>(move |world| {
|
||||
|
||||
```rust
|
||||
// systems/spotlight_sync.rs
|
||||
pub fn spotlight_sync_system(world: &World) -> Vec<Spotlight> {
|
||||
let mut spotlights = Vec::new();
|
||||
for entity in world.spotlights.all() {
|
||||
// Closure captures immutably—safe to call multiple times
|
||||
if let Some(spotlight_component) = world.spotlights.get(entity) {
|
||||
if let Some(transform) = world.transforms.get(entity) {
|
||||
pub fn spotlight_sync_system(spotlights: &Storage<SpotlightComponent>, transforms: &Storage<Transform>) -> Vec<Spotlight> {
|
||||
let mut result = Vec::new();
|
||||
for entity in spotlights.all() {
|
||||
if let Some(spotlight_component) = spotlights.get(entity) {
|
||||
if let Some(transform) = transforms.get(entity) {
|
||||
let position = transform.position + spotlight_component.offset;
|
||||
spotlights.push(Spotlight::new(position, ..));
|
||||
result.push(Spotlight::new(position, ..));
|
||||
}
|
||||
}
|
||||
}
|
||||
spotlights
|
||||
result
|
||||
}
|
||||
|
||||
// With mutation
|
||||
@@ -155,25 +162,46 @@ world.movements.with_mut(entity, |movement| {
|
||||
});
|
||||
```
|
||||
|
||||
### System Function Signature
|
||||
**Why**: Pass only the storages (or immutable `World`) that the system needs. Makes data dependencies explicit.
|
||||
### System Function Signature (Explicit Storage Parameters)
|
||||
**Why**: Pass only the specific storages (or read-only `&World`) that the system needs. Makes data dependencies explicit for the reader and borrow checker. **This is the standard pattern—all systems follow this.**
|
||||
|
||||
```rust
|
||||
// Good: explicit dependencies
|
||||
pub fn camera_follow_system(world: &mut World) {
|
||||
let camera_entities: Vec<_> = world.follows.all();
|
||||
pub fn camera_follow_system(
|
||||
follows: &mut Storage<FollowComponent>,
|
||||
cameras: &Storage<CameraComponent>,
|
||||
transforms: &mut Storage<Transform>,
|
||||
) {
|
||||
let camera_entities: Vec<_> = follows.all();
|
||||
for camera_entity in camera_entities {
|
||||
// Access what's needed
|
||||
if let Some(follow) = world.follows.get(camera_entity) {
|
||||
world.transforms.with_mut(camera_entity, |t| {
|
||||
t.position = target_position + new_offset;
|
||||
});
|
||||
if let Some(follow) = follows.get(camera_entity) {
|
||||
if let Some(camera) = cameras.get(camera_entity) {
|
||||
transforms.with_mut(camera_entity, |t| {
|
||||
t.position = follow.target_position + new_offset;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For read-only systems
|
||||
pub fn spotlight_sync_system(world: &World) -> Vec<Spotlight> { .. }
|
||||
// Read-only system
|
||||
pub fn spotlight_sync_system(spotlights: &Storage<SpotlightComponent>, transforms: &Storage<Transform>) -> Vec<Spotlight> { .. }
|
||||
|
||||
// Dialog system example
|
||||
pub fn dialog_system(
|
||||
entities: &mut EntityManager,
|
||||
trigger_events: &[TriggerEvent],
|
||||
dialog_sources: &Storage<DialogSourceComponent>,
|
||||
bubble_tags: &mut Storage<()>,
|
||||
dialog_bubbles: &mut Storage<DialogBubbleComponent>,
|
||||
transforms: &mut Storage<Transform>,
|
||||
names: &mut Storage<String>,
|
||||
player_tags: &Storage<()>,
|
||||
projectile_tags: &mut Storage<()>,
|
||||
dialog_projectiles: &mut Storage<DialogProjectileComponent>,
|
||||
dialog_outcomes: &mut Vec<DialogOutcomeEvent>,
|
||||
delta: f32,
|
||||
) { .. }
|
||||
```
|
||||
|
||||
### Default Trait for Configuration Components
|
||||
@@ -227,14 +255,14 @@ fn system_a(world: &mut World) {
|
||||
**Do this instead:**
|
||||
```rust
|
||||
// ✅ Good: intent in queue, flat pipeline
|
||||
pub fn system_a(world: &mut World) {
|
||||
world.some_intents.insert(entity, MyIntent { .. });
|
||||
pub fn system_a(cameras: &mut Storage<CameraComponent>) {
|
||||
cameras.insert(entity, CameraTransitionIntent { .. });
|
||||
}
|
||||
|
||||
pub fn system_b(world: &mut World) {
|
||||
for entity in world.some_intents.all() {
|
||||
pub fn system_b(camera_transitions: &mut Storage<CameraTransition>) {
|
||||
for entity in camera_transitions.all() {
|
||||
// process
|
||||
world.some_intents.remove(entity);
|
||||
camera_transitions.remove(entity);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -273,46 +301,24 @@ use crate::physics::PhysicsManager;
|
||||
let velocity = *PhysicsManager::with_rigidbody_mut(..);
|
||||
```
|
||||
|
||||
### Global or Context-Based Component Queries
|
||||
**Don't do this:**
|
||||
```rust
|
||||
// ❌ Bad: loses intent, repeats queries
|
||||
for entity in world.meshes.all() {
|
||||
if let Some(mesh) = world.meshes.get(entity) { .. }
|
||||
}
|
||||
for entity in world.meshes.all() {
|
||||
if let Some(mesh) = world.meshes.get(entity) { .. }
|
||||
}
|
||||
```
|
||||
|
||||
**Do this instead:**
|
||||
```rust
|
||||
// ✅ Good: query once, iterate clearly
|
||||
let entities: Vec<_> = world.meshes.all();
|
||||
for entity in entities {
|
||||
if let Some(mesh_comp) = world.meshes.get(entity) {
|
||||
// process
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Overly Generic (World/&mut World) Parameters
|
||||
**Don't do this:**
|
||||
```rust
|
||||
// ❌ Bad: implicit dependencies
|
||||
fn update_position(world: &mut World, entity: EntityHandle) {
|
||||
// What do we actually need?
|
||||
// ❌ Bad: implicit dependencies, breaks borrow checker
|
||||
pub fn camera_follow_system(world: &mut World) {
|
||||
// What storages do we actually need?
|
||||
}
|
||||
```
|
||||
|
||||
**Do this instead:**
|
||||
```rust
|
||||
// ✅ Good: explicit dependencies
|
||||
fn update_position(
|
||||
// ✅ Good: explicit, focused dependencies
|
||||
pub fn camera_follow_system(
|
||||
follows: &mut Storage<FollowComponent>,
|
||||
cameras: &Storage<CameraComponent>,
|
||||
transforms: &mut Storage<Transform>,
|
||||
entity: EntityHandle,
|
||||
) {
|
||||
transforms.with_mut(entity, |t| t.position.y += 1.0);
|
||||
// Clear what data is needed
|
||||
}
|
||||
```
|
||||
|
||||
@@ -351,4 +357,6 @@ cargo test -- --nocapture # Show output
|
||||
- See **CLAUDE.md** in project root for authoritative style rules (no inline comments, doc comments for public APIs only)
|
||||
- See **docs/self-gating-systems.md** for detailed intent-based pipeline patterns
|
||||
- See `src/states/player_states.rs` for canonical State impl examples
|
||||
- See `src/bundles/player.rs` for complete Bundle pattern with state machine setup
|
||||
- See `src/bundles/player.rs` for complete Bundle pattern with state machine setup
|
||||
- See `src/systems/camera.rs` for canonical system function signatures with explicit storage parameters
|
||||
- See `src/systems/dialog_system.rs` for complex multi-storage system example
|
||||
Reference in New Issue
Block a user