Bevy Forge 0.1.0: visual scene editor for Bevy 0.20 BSN
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
// compat/bsn-smoke shim: expose crate-root support types (demo custom components).
|
||||
// The generated code below this line is unchanged.
|
||||
#![allow(unused_imports)] // the crate::* glob also provides the Bevy prelude names
|
||||
use crate::*;
|
||||
use bevy::prelude::*;
|
||||
use bevy::scene::bsn_list;
|
||||
|
||||
pub fn scene(
|
||||
meshes: &mut Assets<Mesh>,
|
||||
materials: &mut Assets<StandardMaterial>,
|
||||
) -> impl SceneList {
|
||||
bsn_list! {
|
||||
Name("Camera")
|
||||
Transform {
|
||||
translation: Vec3::new(7.5, 5.0, 12.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, -16.0f32.to_radians(), 30.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Camera3d::default()
|
||||
--
|
||||
Name("Sun")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, -55.0f32.to_radians(), -25.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
DirectionalLight { color: Color::srgba(1.0, 0.95, 0.85, 1.0), illuminance: 11000.0, shadow_maps_enabled: true }
|
||||
--
|
||||
Name("Ground")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Mesh3d({ meshes.add(Plane3d::new(Vec3::Y, Vec2::new(13.0, 13.0))) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.31, 0.48, 0.23, 1.0),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.92,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
--
|
||||
Name("Shrub")
|
||||
Transform {
|
||||
translation: Vec3::new(-3.4, 1.0, 1.8),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.25, 0.9, 1.25),
|
||||
}
|
||||
Mesh3d({ meshes.add(Sphere::new(1.0)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.24, 0.45, 0.22, 1.0),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.85,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
--
|
||||
Name("Flower Stem")
|
||||
Transform {
|
||||
translation: Vec3::new(2.6, 0.75, 1.4),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Mesh3d({ meshes.add(Cylinder::new(0.09, 1.5)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.35, 0.55, 0.27, 1.0),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.8,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Children [
|
||||
Name("Flower Bloom")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 1.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 0.75, 1.0),
|
||||
}
|
||||
Mesh3d({ meshes.add(Sphere::new(0.42)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.91, 0.42, 0.65, 1.0),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.4,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
]
|
||||
--
|
||||
Name("Orbit Crystal")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 2.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Mesh3d({ meshes.add(Sphere::new(0.8)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.27, 0.76, 0.69, 1.0),
|
||||
metallic: 0.15,
|
||||
perceptual_roughness: 0.2,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
forge_demo::Orbit { radius: 2.4, speed: 0.45 }
|
||||
--
|
||||
Name("Lantern Post")
|
||||
Transform {
|
||||
translation: Vec3::new(3.8, 1.2, -1.2),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Mesh3d({ meshes.add(Cylinder::new(0.12, 2.4)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgba(0.18, 0.2, 0.25, 1.0),
|
||||
metallic: 0.6,
|
||||
perceptual_roughness: 0.35,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Children [
|
||||
Name("Lantern Glow")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 1.25, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
PointLight { color: Color::srgba(1.0, 0.82, 0.55, 1.0), intensity: 600.0, range: 12.0, shadow_maps_enabled: true }
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// compat/bsn-smoke shim: expose crate-root support types (demo custom components).
|
||||
// The generated code below this line is unchanged.
|
||||
#![allow(unused_imports)] // the crate::* glob also provides the Bevy prelude names
|
||||
use crate::*;
|
||||
use bevy::prelude::*;
|
||||
use bevy::scene::bsn_list;
|
||||
|
||||
pub fn scene() -> impl SceneList {
|
||||
bsn_list! {
|
||||
Name("Backdrop")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, -30.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/background.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(960.0, 540.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Camera")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 10.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Camera2d
|
||||
--
|
||||
Name("Title")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 214.0, 5.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Text2d("Bevy Forge Platformer")
|
||||
TextFont { font_size: FontSize::Px(44.0) }
|
||||
TextColor(Color::srgba(0.96, 0.94, 0.88, 1.0))
|
||||
--
|
||||
Name("Hint")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 176.0, 5.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Text2d("Collect the coins!")
|
||||
TextFont { font_size: FontSize::Px(20.0) }
|
||||
TextColor(Color::srgba(0.95, 0.67, 0.25, 1.0))
|
||||
--
|
||||
Name("Ground 1")
|
||||
Transform {
|
||||
translation: Vec3::new(-336.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 2")
|
||||
Transform {
|
||||
translation: Vec3::new(-240.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 3")
|
||||
Transform {
|
||||
translation: Vec3::new(-144.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 4")
|
||||
Transform {
|
||||
translation: Vec3::new(-48.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 5")
|
||||
Transform {
|
||||
translation: Vec3::new(48.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 6")
|
||||
Transform {
|
||||
translation: Vec3::new(144.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 7")
|
||||
Transform {
|
||||
translation: Vec3::new(240.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ground 8")
|
||||
Transform {
|
||||
translation: Vec3::new(336.0, -224.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ledge 1")
|
||||
Transform {
|
||||
translation: Vec3::new(-48.0, -64.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ledge 2")
|
||||
Transform {
|
||||
translation: Vec3::new(48.0, -64.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Ledge 3")
|
||||
Transform {
|
||||
translation: Vec3::new(144.0, -64.0, -2.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(96.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Player")
|
||||
Transform {
|
||||
translation: Vec3::new(-192.0, -128.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/player.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(64.0, 96.0)) }, flip_x: false, flip_y: false }
|
||||
Children [
|
||||
Name("Hat")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 42.0, 1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/hat.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(56.0, 28.0)) }, flip_x: false, flip_y: false }
|
||||
]
|
||||
--
|
||||
Name("Coin 1")
|
||||
Transform {
|
||||
translation: Vec3::new(-288.0, -104.0, 1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/coin.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(48.0, 48.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Coin 2")
|
||||
Transform {
|
||||
translation: Vec3::new(48.0, 28.0, 1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/coin.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(48.0, 48.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Coin 3")
|
||||
Transform {
|
||||
translation: Vec3::new(240.0, -96.0, 1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/coin.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(48.0, 48.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Crate")
|
||||
Transform {
|
||||
translation: Vec3::new(352.0, -144.0, -1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/crate.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(64.0, 64.0)) }, flip_x: false, flip_y: false }
|
||||
--
|
||||
Name("Crate 2")
|
||||
Transform {
|
||||
translation: Vec3::new(352.0, -80.0, -1.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0f32.to_radians(), 0.0f32.to_radians(), 0.0f32.to_radians()),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/crate.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0), custom_size: { Some(Vec2::new(64.0, 64.0)) }, flip_x: false, flip_y: false }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
//! Compile-smoke crate for Bevy Forge's generated code.
|
||||
//!
|
||||
//! This crate is intentionally **not** a workspace member: it is the only place
|
||||
//! in the repository that depends on Bevy (0.20.0). It compiles:
|
||||
//!
|
||||
//! * hand-written scenes that mirror `ExportFormat::Bsn` output for every
|
||||
//! supported component, hierarchy shape and asset pattern (this file), and
|
||||
//! * the real files written by `scripts/check-generated-code.sh`
|
||||
//! (`src/generated.rs`, `src/generated_2d.rs`).
|
||||
//!
|
||||
//! See `README.md` for the feature set, commands and expected build cost.
|
||||
//! The generated code targets the compile-verified forms in `.swarm/recon/R02.md`.
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy::scene::bsn;
|
||||
use bevy::scene::bsn_list;
|
||||
|
||||
/// Bevy Forge's BSN export for `examples/demo-project/scenes/garden.forge.ron`.
|
||||
///
|
||||
/// Committed with a harmless starter scene so this crate compiles before the
|
||||
/// end-to-end gate has run; `scripts/check-generated-code.sh` replaces it with
|
||||
/// the real CLI export.
|
||||
#[path = "generated.rs"]
|
||||
pub mod generated;
|
||||
|
||||
/// Bevy Forge's BSN export for `examples/demo-project/scenes/platformer.forge.ron`.
|
||||
#[path = "generated_2d.rs"]
|
||||
pub mod generated_2d;
|
||||
|
||||
/// Imperative `Commands::spawn` export shape (`ExportFormat::Rust`), mirroring
|
||||
/// what the CLI emits. It is compiled here so the secondary export format is
|
||||
/// verified against real Bevy types as well.
|
||||
pub mod rust_export;
|
||||
|
||||
/// A custom component with fields, as emitted for `ComponentData::Custom`.
|
||||
///
|
||||
/// `Component + Default + Clone` is enough for Bevy 0.20's blanket
|
||||
/// `FromTemplate` implementation (see R02 §4), so generated
|
||||
/// `Health { current: 10.0, max: 10.0 }` patches compile.
|
||||
#[derive(Component, Default, Clone)]
|
||||
pub struct Health {
|
||||
pub current: f32,
|
||||
pub max: f32,
|
||||
}
|
||||
|
||||
/// A unit custom component: Bevy Forge emits the bare type path when a custom
|
||||
/// component has no fields.
|
||||
#[derive(Component, Default, Clone)]
|
||||
pub struct Marker;
|
||||
|
||||
/// Support types from `examples/demo-project/src/main.rs`.
|
||||
///
|
||||
/// The demo garden scene carries a custom `forge_demo::Orbit` component, so the
|
||||
/// generated garden BSN references that path. Providing the module here lets the
|
||||
/// export compile in the smoke crate without editing the generated file.
|
||||
pub mod forge_demo {
|
||||
use bevy::prelude::*;
|
||||
|
||||
/// Slowly orbits an entity around the world origin (demo project component).
|
||||
#[derive(Component, Default, Clone)]
|
||||
pub struct Orbit {
|
||||
pub radius: f32,
|
||||
pub speed: f32,
|
||||
}
|
||||
}
|
||||
|
||||
/// 2D scene: single root, `Name`/`Transform`/`Sprite` with image and braced
|
||||
/// `custom_size`, a custom component with fields, a unit custom component, and
|
||||
/// nested `Children` (including a visibility patch on a grandchild).
|
||||
///
|
||||
/// Mirrors the shape generated for a typical platformer root entity.
|
||||
pub fn scene_2d() -> impl Scene {
|
||||
bsn! {
|
||||
Name("Player")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 1.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite {
|
||||
image: "textures/player.png",
|
||||
color: Color::srgba(1.0, 1.0, 1.0, 1.0),
|
||||
custom_size: { Some(Vec2::new(64.0, 64.0)) },
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
}
|
||||
Health { current: 10.0, max: 10.0 }
|
||||
forge_demo::Orbit { radius: 2.5, speed: 0.8 }
|
||||
Children [
|
||||
Name("Hat")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 40.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { color: Color::srgba(1.0, 0.5, 0.2, 1.0) }
|
||||
Marker
|
||||
Children [
|
||||
Name("Glow")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.5, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(0.5, 0.5, 1.0),
|
||||
}
|
||||
Sprite { color: Color::srgba(1.0, 1.0, 0.4, 0.6) }
|
||||
Visibility::Visible
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiple roots: the generator emits `bsn_list!` plus `--` separators and a
|
||||
/// `-> impl SceneList` return type.
|
||||
pub fn scene_2d_list() -> impl SceneList {
|
||||
bsn_list! {
|
||||
Name("Left")
|
||||
Transform {
|
||||
translation: Vec3::new(-2.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { image: "textures/tile.png", color: Color::srgba(1.0, 1.0, 1.0, 1.0) }
|
||||
--
|
||||
Name("Right")
|
||||
Transform {
|
||||
translation: Vec3::new(2.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { color: Color::srgba(0.9, 0.6, 0.3, 1.0) }
|
||||
Children [
|
||||
Name("Right Child")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 1.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Sprite { color: Color::srgba(0.2, 0.8, 0.9, 1.0) }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Text: `Text2d` payload plus `TextFont`/`TextColor` patches.
|
||||
pub fn scene_text() -> impl Scene {
|
||||
bsn! {
|
||||
Name("Title")
|
||||
Text2d("Bevy Forge\nHello \"BSN\"")
|
||||
TextFont { font_size: FontSize::Px(32.0) }
|
||||
TextColor(Color::srgba(1.0, 0.9, 0.8, 1.0))
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 200.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Bare `Camera2d` patch, as emitted for 2D scenes.
|
||||
pub fn scene_camera_2d() -> impl Scene {
|
||||
bsn! {
|
||||
Name("Main Camera")
|
||||
Camera2d
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 999.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 3D stage: `Camera3d::default()`, both light types and the `Visibility`
|
||||
/// variants on children (a single-root scene with three child entities).
|
||||
pub fn scene_3d_stage() -> impl Scene {
|
||||
bsn! {
|
||||
Name("Stage")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Children [
|
||||
Name("Main Camera")
|
||||
Camera3d::default()
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 4.0, 10.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, -0.35, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
--
|
||||
Name("Sun")
|
||||
DirectionalLight {
|
||||
color: Color::srgb(1.0, 0.95, 0.9),
|
||||
illuminance: 10000.0,
|
||||
shadow_maps_enabled: true,
|
||||
}
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 8.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, -0.8, 0.4, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Visibility::Visible
|
||||
--
|
||||
Name("Lantern")
|
||||
PointLight {
|
||||
color: Color::srgb(1.0, 0.6, 0.25),
|
||||
intensity: 800.0,
|
||||
range: 20.0,
|
||||
shadow_maps_enabled: true,
|
||||
}
|
||||
Transform {
|
||||
translation: Vec3::new(1.5, 1.0, 1.5),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Visibility::Inherited
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// 3D primitives and inline materials: the generated function takes the
|
||||
/// `meshes`/`materials` asset parameters when a scene contains meshes.
|
||||
///
|
||||
/// Covers all five `PrimitiveShape` variants from the codegen contract.
|
||||
pub fn scene_3d_primitives(
|
||||
meshes: &mut Assets<Mesh>,
|
||||
materials: &mut Assets<StandardMaterial>,
|
||||
) -> impl Scene {
|
||||
bsn! {
|
||||
Name("Primitives")
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
Children [
|
||||
Name("Cube")
|
||||
Mesh3d({ meshes.add(Cuboid::new(1.0, 1.0, 1.0)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.9, 0.35, 0.3),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.5,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(-2.0, 0.5, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
--
|
||||
Name("Sphere")
|
||||
Mesh3d({ meshes.add(Sphere::new(0.5)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.3, 0.6, 0.9),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.5,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(-1.0, 0.5, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
--
|
||||
Name("Plane")
|
||||
Mesh3d({ meshes.add(Plane3d::new(Vec3::Y, Vec2::new(6.0, 6.0))) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.35, 0.5, 0.3),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.9,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.0, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
--
|
||||
Name("Cylinder")
|
||||
Mesh3d({ meshes.add(Cylinder::new(0.4, 1.6)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.8, 0.7, 0.25),
|
||||
metallic: 0.1,
|
||||
perceptual_roughness: 0.4,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(1.0, 0.8, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
--
|
||||
Name("Capsule")
|
||||
Mesh3d({ meshes.add(Capsule3d::new(0.3, 1.0)) })
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.55, 0.4, 0.8),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.6,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(2.0, 0.8, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Asset mesh: `Mesh3d("<path>")` uses a path handle while the material is an
|
||||
/// inline `materials.add(..)` handle (the generator never emits asset material
|
||||
/// paths, which would need a project-registered loader at runtime).
|
||||
pub fn scene_asset_mesh(materials: &mut Assets<StandardMaterial>) -> impl Scene {
|
||||
bsn! {
|
||||
Name("Crate")
|
||||
Mesh3d("models/crate.gltf#Mesh0/Primitive0")
|
||||
MeshMaterial3d::<StandardMaterial>({ materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.6, 0.45, 0.3),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.8,
|
||||
unlit: false,
|
||||
..default()
|
||||
}) })
|
||||
Transform {
|
||||
translation: Vec3::new(0.0, 0.5, 0.0),
|
||||
rotation: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0),
|
||||
scale: Vec3::new(1.0, 1.0, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
//! Compile check for Bevy Forge's secondary export format: imperative
|
||||
//! `Commands::spawn` code (`ExportFormat::Rust`, contract §3.2).
|
||||
//!
|
||||
//! This mirrors what a user gets when pasting the Rust export into a system.
|
||||
//! It is hand-written from the contract shape (A04's generator output is
|
||||
//! verified separately by its tests); the value here is that every Bevy API call
|
||||
//! the exporter emits is checked against real Bevy 0.20.0.
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::Health;
|
||||
|
||||
/// Representative Rust export: a 2D sprite with a child and a custom component,
|
||||
/// a primitive mesh with an inline material, text and a 3D camera + light.
|
||||
///
|
||||
/// The parameter set matches the contract: `commands` always, `asset_server`
|
||||
/// only because a sprite image is loaded, `meshes`/`materials` only because a
|
||||
/// primitive mesh is spawned.
|
||||
pub fn scene(
|
||||
commands: &mut Commands,
|
||||
asset_server: &AssetServer,
|
||||
meshes: &mut Assets<Mesh>,
|
||||
materials: &mut Assets<StandardMaterial>,
|
||||
) {
|
||||
commands
|
||||
.spawn((
|
||||
Name::new("Player"),
|
||||
Transform::from_xyz(0.0, 1.0, 0.0)
|
||||
.with_rotation(Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, 0.0))
|
||||
.with_scale(Vec3::new(1.0, 1.0, 1.0)),
|
||||
Sprite {
|
||||
image: asset_server.load("textures/player.png"),
|
||||
color: Color::srgba(1.0, 1.0, 1.0, 1.0),
|
||||
custom_size: Some(Vec2::new(64.0, 64.0)),
|
||||
..default()
|
||||
},
|
||||
Health {
|
||||
current: 10.0,
|
||||
max: 10.0,
|
||||
},
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
Name::new("Hat"),
|
||||
Transform::from_xyz(0.0, 40.0, 0.0),
|
||||
Sprite {
|
||||
color: Color::srgba(1.0, 0.5, 0.2, 1.0),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
});
|
||||
|
||||
commands.spawn((
|
||||
Name::new("Cube"),
|
||||
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||
MeshMaterial3d(materials.add(StandardMaterial {
|
||||
base_color: Color::srgb(0.9, 0.35, 0.3),
|
||||
metallic: 0.0,
|
||||
perceptual_roughness: 0.5,
|
||||
unlit: false,
|
||||
..default()
|
||||
})),
|
||||
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
Name::new("Title"),
|
||||
Text2d::new("Bevy Forge"),
|
||||
TextFont {
|
||||
font_size: FontSize::Px(32.0),
|
||||
..default()
|
||||
},
|
||||
TextColor(Color::WHITE),
|
||||
Transform::from_xyz(0.0, 2.0, 0.0),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
Name::new("Main Camera"),
|
||||
Camera3d::default(),
|
||||
Transform::from_xyz(0.0, 4.0, 10.0),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
Name::new("Sun"),
|
||||
DirectionalLight {
|
||||
illuminance: 10000.0,
|
||||
shadow_maps_enabled: true,
|
||||
..default()
|
||||
},
|
||||
Transform::default(),
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
Name::new("Hidden Helper"),
|
||||
Transform::default(),
|
||||
Visibility::Hidden,
|
||||
));
|
||||
}
|
||||
Reference in New Issue
Block a user