symtropy-bevy-core 0.1.1

Permissively-licensed Bevy plugin for symtropy-physics N-dimensional physics. Generic over PhysicsCallback.
Documentation
# symtropy-bevy-core

Permissively-licensed Bevy plugin for [`symtropy-physics`](https://crates.io/crates/symtropy-physics) N-dimensional physics.

**Zero AGPL dependencies.** Safe for proprietary projects.

## What you get

- `BevyPhysics<D>` — Bevy `Resource` wrapping a `PhysicsWorld<D>`.
- `PhysicsBody` — Bevy `Component` linking an entity to a physics body.
- `NoCouplingResource` — identity-modulation `PhysicsCallback` for physics-only usage.
- `BevyPhysicsPlugin<D>` — drop-in plugin with `NoCoupling` step (2D / 3D / 4D).
- `BevyPhysicsCorePlugin<D>` — minimal plugin without a step system (users add their own).
- `step_physics<D, C>` — generic step system for any `PhysicsCallback + Resource`.
- `sync_transforms<D>` — write physics positions to Bevy `Transform`.

## Quickstart

```rust
use bevy::prelude::*;
use symtropy_bevy_core::{BevyPhysicsPlugin, BevyPhysics, PhysicsBody};
use symtropy_physics::body::Point;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(BevyPhysicsPlugin::<3>::with_gravity([0.0, -9.81, 0.0]))
        .add_systems(Startup, spawn_ball)
        .run();
}

fn spawn_ball(
    mut commands: Commands,
    mut physics: ResMut<BevyPhysics<3>>,
) {
    let handle = physics.world.add_sphere(Point::new([0.0, 10.0, 0.0]), 1.0, 1.0);
    commands.spawn((
        PhysicsBody::new(handle, 1.0),
        Transform::default(),
    ));
}
```

## Bring your own coupling

If you want to couple a custom per-body metric (health, trust, skill, wealth, …) to physics, implement `PhysicsCallback<D>` on your own Resource type:

```rust
use bevy::prelude::*;
use nalgebra::SVector;
use symtropy_physics::{BodyHandle, CollisionEvent, PhysicsCallback};
use symtropy_bevy_core::{BevyPhysicsCorePlugin, step_physics, sync_transforms};
use std::collections::HashMap;

#[derive(Resource, Default)]
struct HealthField(HashMap<BodyHandle, f64>);

impl<const D: usize> PhysicsCallback<D> for HealthField {
    fn modulate_force(&self, body: BodyHandle, force: &SVector<f64, D>) -> SVector<f64, D> {
        let hp = self.0.get(&body).copied().unwrap_or(1.0);
        force * hp  // low HP → weaker motor authority
    }
    fn modulate_impulse(&self, impulse: f64, _: &SVector<f64, D>) -> f64 { impulse }
    fn friction_multiplier(&self, _: &SVector<f64, D>, _: BodyHandle) -> f64 { 1.0 }
    fn on_collision(&mut self, _: &CollisionEvent<D>) {}
    fn record_dissipation(&mut self, _: f64) {}
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(BevyPhysicsCorePlugin::<3>::with_gravity([0.0, -9.81, 0.0]))
        .insert_resource(HealthField::default())
        .add_systems(FixedUpdate, (
            step_physics::<3, HealthField>,
            sync_transforms::<3>,
        ).chain())
        .run();
}
```

## For Φ-coupling (IIT research)

Use the AGPL sibling crate `symtropy-bevy`, which wires `ConsciousnessField` from [`symtropy-consciousness-physics`](https://crates.io/crates/symtropy-consciousness-physics). Same plugin API, adds 5-channel Φ coupling, biometrics integration, and macro-world modifiers.

## Status

Phase 0.5 of the [Symtropy roadmap](https://github.com/luminous-dynamics/symtropy/blob/main/ROADMAP.md). First release extracts the physics-only Bevy plumbing into a permissively-licensed crate so game studios can adopt Symtropy without AGPL obligations.