mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-12-22 23:54:10 +00:00
refactor(examples): started simplifying & restructuring examples
This commit is contained in:
parent
b25fc56ea6
commit
7acb1f3a57
@ -1,12 +1,10 @@
|
||||
[package]
|
||||
name = "bevy_gltf_blueprints_animation_example"
|
||||
version = "0.3.0"
|
||||
name = "blenvy_animation_example"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.13", features = ["dynamic_linking"] }
|
||||
bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" }
|
||||
bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" }
|
||||
bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||
rand = "0.8.5"
|
||||
bevy = { version = "0.14", features = ["dynamic_linking"] }
|
||||
blenvy = { path = "../../../crates/blenvy" }
|
||||
rand = "0.8.5"
|
Binary file not shown.
@ -1,6 +0,0 @@
|
||||
({
|
||||
"world":File (path: "models/Level1.glb"),
|
||||
"models": Folder (
|
||||
path: "models/library",
|
||||
),
|
||||
})
|
Binary file not shown.
BIN
examples/blenvy/animation/assets/blueprints/Player.glb
Normal file
BIN
examples/blenvy/animation/assets/blueprints/Player.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/animation/assets/blueprints/Wheelbot.glb
Normal file
BIN
examples/blenvy/animation/assets/blueprints/Wheelbot.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/animation/assets/levels/World.glb
Normal file
BIN
examples/blenvy/animation/assets/levels/World.glb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
14115
examples/blenvy/animation/assets/registry.json
Normal file
14115
examples/blenvy/animation/assets/registry.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,8 +60,8 @@ pub enum EnumTest {
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct ComponentsTestPlugin;
|
||||
impl Plugin for ComponentsTestPlugin {
|
||||
pub struct ComponentsExamplesPlugin;
|
||||
impl Plugin for ComponentsExamplesPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<BasicTest>()
|
||||
.register_type::<UnitTest>()
|
@ -1,12 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
pub struct CorePlugin;
|
||||
impl Plugin for CorePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins((BlueprintsPlugin {
|
||||
aabbs: true,
|
||||
..Default::default()
|
||||
},));
|
||||
}
|
||||
}
|
@ -1,320 +0,0 @@
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{
|
||||
assets::GameAssets, GameState, InAppRunning, Player,
|
||||
};
|
||||
use bevy_rapier3d::prelude::Velocity;
|
||||
use rand::Rng;
|
||||
use std::time::Duration;
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
use bevy_gltf_blueprints::{
|
||||
BluePrintBundle, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, GameWorldTag,
|
||||
};
|
||||
|
||||
use super::{Fox, Robot};
|
||||
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
game_assets: Res<GameAssets>,
|
||||
models: Res<Assets<bevy::gltf::Gltf>>,
|
||||
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.2,
|
||||
});
|
||||
// here we actually spawn our game world/level
|
||||
|
||||
commands.spawn((
|
||||
SceneBundle {
|
||||
// note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene
|
||||
scene: models
|
||||
.get(game_assets.world.clone().unwrap().id())
|
||||
.expect("main level should have been loaded")
|
||||
.scenes[0]
|
||||
.clone(),
|
||||
..default()
|
||||
},
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyT) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 8.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Fox".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("Spawned{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 0.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
||||
|
||||
// example of changing animation of entities based on proximity to the player, for "fox" entities (Tag component)
|
||||
pub fn animation_change_on_proximity_foxes(
|
||||
players: Query<&GlobalTransform, With<Player>>,
|
||||
animated_foxes: Query<
|
||||
(
|
||||
&GlobalTransform,
|
||||
&BlueprintAnimationPlayerLink,
|
||||
&BlueprintAnimations,
|
||||
),
|
||||
With<Fox>,
|
||||
>,
|
||||
|
||||
mut animation_players: Query<&mut AnimationPlayer>,
|
||||
) {
|
||||
for player_transforms in players.iter() {
|
||||
for (fox_tranforms, link, animations) in animated_foxes.iter() {
|
||||
let distance = player_transforms
|
||||
.translation()
|
||||
.distance(fox_tranforms.translation());
|
||||
let mut anim_name = "Walk";
|
||||
if distance < 8.5 {
|
||||
anim_name = "Run";
|
||||
} else if (8.5..10.0).contains(&distance) {
|
||||
anim_name = "Walk";
|
||||
} else if (10.0..15.0).contains(&distance) {
|
||||
anim_name = "Survey";
|
||||
}
|
||||
// now play the animation based on the chosen animation name
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(3),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// example of changing animation of entities based on proximity to the player, this time for the "robot" entities (Tag component)
|
||||
pub fn animation_change_on_proximity_robots(
|
||||
players: Query<&GlobalTransform, With<Player>>,
|
||||
animated_robots: Query<
|
||||
(
|
||||
&GlobalTransform,
|
||||
&BlueprintAnimationPlayerLink,
|
||||
&BlueprintAnimations,
|
||||
),
|
||||
With<Robot>,
|
||||
>,
|
||||
|
||||
mut animation_players: Query<&mut AnimationPlayer>,
|
||||
) {
|
||||
for player_transforms in players.iter() {
|
||||
for (robot_tranforms, link, animations) in animated_robots.iter() {
|
||||
let distance = player_transforms
|
||||
.translation()
|
||||
.distance(robot_tranforms.translation());
|
||||
|
||||
let mut anim_name = "Idle";
|
||||
if distance < 8.5 {
|
||||
anim_name = "Jump";
|
||||
} else if (8.5..10.0).contains(&distance) {
|
||||
anim_name = "Scan";
|
||||
} else if (10.0..15.0).contains(&distance) {
|
||||
anim_name = "Idle";
|
||||
}
|
||||
|
||||
// now play the animation based on the chosen animation name
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(3),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn animation_control(
|
||||
animated_enemies: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<Robot>>,
|
||||
animated_foxes: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<Fox>>,
|
||||
|
||||
mut animation_players: Query<&mut AnimationPlayer>,
|
||||
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
// mut entities_with_animations : Query<(&mut AnimationPlayer, &mut BlueprintAnimations)>,
|
||||
) {
|
||||
// robots
|
||||
if keycode.just_pressed(KeyCode::KeyB) {
|
||||
for (link, animations) in animated_enemies.iter() {
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Scan";
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
// foxes
|
||||
if keycode.just_pressed(KeyCode::KeyW) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Walk";
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyX) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Run";
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyC) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let mut animation_player = animation_players.get_mut(link.0).unwrap();
|
||||
let anim_name = "Survey";
|
||||
animation_player
|
||||
.play_with_transition(
|
||||
animations
|
||||
.named_animations
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
/* Improveement ideas for the future
|
||||
// a bit more ideal API
|
||||
if keycode.just_pressed(KeyCode::B) {
|
||||
for (animation_player, animations) in animated_enemies.iter() {
|
||||
let anim_name = "Scan";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
animation_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// even better API
|
||||
if keycode.just_pressed(KeyCode::B) {
|
||||
for (animation_player, animations) in animated_enemies.iter() {
|
||||
animation_player.play_with_transition("Scan", Duration::from_secs(5)).repeat(); // with a merged animationPlayer + animations storage
|
||||
// alternative, perhaps more realistic, and better seperation of concerns
|
||||
animation_player.play_with_transition(animations, "Scan", Duration::from_secs(5)).repeat();
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
/*for (mut anim_player, animations) in entities_with_animations.iter_mut(){
|
||||
|
||||
if keycode.just_pressed(KeyCode::W) {
|
||||
let anim_name = "Walk";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::X) {
|
||||
let anim_name = "Run";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::C) {
|
||||
let anim_name = "Survey";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if keycode.just_pressed(KeyCode::S) {
|
||||
let anim_name = "Scan";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::I) {
|
||||
let anim_name = "Idle";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, InMainMenu};
|
||||
|
||||
pub fn setup_main_menu(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
Camera2dBundle {
|
||||
camera: Camera {
|
||||
order: 102, // needed because of this: https://github.com/jakobhellermann/bevy_editor_pls/blob/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs#L213C9-L213C28
|
||||
..default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"SOME GAME TITLE !!",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(100.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(200.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
/*
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Load Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(250.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Exit Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(300.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));*/
|
||||
}
|
||||
|
||||
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands) {
|
||||
for bli in bla.iter() {
|
||||
commands.entity(bli).despawn_recursive();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_menu(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut next_app_state: ResMut<NextState<AppState>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::Enter) {
|
||||
next_app_state.set(AppState::AppLoading);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
pub mod in_game;
|
||||
pub use in_game::*;
|
||||
|
||||
pub mod in_main_menu;
|
||||
pub use in_main_menu::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// Demo marker component
|
||||
pub struct Fox;
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// Demo marker component
|
||||
pub struct Robot;
|
||||
|
||||
pub struct GamePlugin;
|
||||
impl Plugin for GamePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<Robot>()
|
||||
.register_type::<Fox>()
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
spawn_test,
|
||||
animation_control,
|
||||
animation_change_on_proximity_foxes,
|
||||
animation_change_on_proximity_robots,
|
||||
)
|
||||
.run_if(in_state(GameState::InGame)),
|
||||
)
|
||||
.add_systems(OnEnter(AppState::MenuRunning), setup_main_menu)
|
||||
.add_systems(OnExit(AppState::MenuRunning), teardown_main_menu)
|
||||
.add_systems(Update, main_menu.run_if(in_state(AppState::MenuRunning)))
|
||||
.add_systems(OnEnter(AppState::AppRunning), setup_game);
|
||||
}
|
||||
}
|
@ -1,24 +1,217 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::CommonPlugin;
|
||||
use blenvy::{AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
use rand::Rng;
|
||||
|
||||
mod core;
|
||||
use crate::core::*;
|
||||
mod component_examples;
|
||||
use component_examples::*;
|
||||
|
||||
mod game;
|
||||
use game::*;
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// Demo marker component
|
||||
pub struct Player;
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// Demo marker component
|
||||
pub struct Fox;
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
/// Demo marker component
|
||||
pub struct Robot;
|
||||
|
||||
mod test_components;
|
||||
use test_components::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
CommonPlugin,
|
||||
CorePlugin, // reusable plugins
|
||||
GamePlugin, // specific to our game
|
||||
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||
BlenvyPlugin::default()
|
||||
))
|
||||
.register_type::<Player>()
|
||||
.register_type::<Fox>()
|
||||
.register_type::<Robot>()
|
||||
|
||||
.add_systems(Startup, setup_game)
|
||||
.add_systems(Update,
|
||||
(animation_control,)
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
// this is how you setup & spawn a level from a blueprint
|
||||
fn setup_game(
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
// here we actually spawn our game world/level
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
|
||||
pub fn animation_control(
|
||||
animated_robots: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<Robot>>,
|
||||
animated_foxes: Query<(&BlueprintAnimationPlayerLink, &BlueprintAnimations), With<Fox>>,
|
||||
|
||||
mut animation_players: Query<(&mut AnimationPlayer, &mut AnimationTransitions)>,
|
||||
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
// mut entities_with_animations : Query<(&mut AnimationPlayer, &mut BlueprintAnimations)>,
|
||||
) {
|
||||
// robots
|
||||
if keycode.just_pressed(KeyCode::KeyB) {
|
||||
println!("scan animation for robots");
|
||||
for (link, animations) in animated_robots.iter() {
|
||||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
println!("got some animations");
|
||||
let anim_name = "Scan";
|
||||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
// foxes
|
||||
if keycode.just_pressed(KeyCode::KeyW) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Walk";
|
||||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyX) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Run";
|
||||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyC) {
|
||||
for (link, animations) in animated_foxes.iter() {
|
||||
let (mut animation_player, mut animation_transitions) =
|
||||
animation_players.get_mut(link.0).unwrap();
|
||||
|
||||
let anim_name = "Survey";
|
||||
animation_transitions
|
||||
.play(
|
||||
&mut animation_player,
|
||||
animations
|
||||
.named_indices
|
||||
.get(anim_name)
|
||||
.expect("animation name should be in the list")
|
||||
.clone(),
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.repeat();
|
||||
}
|
||||
}
|
||||
|
||||
/* Improveement ideas for the future
|
||||
// a bit more ideal API
|
||||
if keycode.just_pressed(KeyCode::B) {
|
||||
for (animation_player, animations) in animated_robots.iter() {
|
||||
let anim_name = "Scan";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
animation_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// even better API
|
||||
if keycode.just_pressed(KeyCode::B) {
|
||||
for (animation_player, animations) in animated_robots.iter() {
|
||||
animation_player.play_with_transition("Scan", Duration::from_secs(5)).repeat(); // with a merged animationPlayer + animations storage
|
||||
// alternative, perhaps more realistic, and better seperation of concerns
|
||||
animation_player.play_with_transition(animations, "Scan", Duration::from_secs(5)).repeat();
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
/*for (mut anim_player, animations) in entities_with_animations.iter_mut(){
|
||||
|
||||
if keycode.just_pressed(KeyCode::W) {
|
||||
let anim_name = "Walk";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::X) {
|
||||
let anim_name = "Run";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::C) {
|
||||
let anim_name = "Survey";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if keycode.just_pressed(KeyCode::S) {
|
||||
let anim_name = "Scan";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
if keycode.just_pressed(KeyCode::I) {
|
||||
let anim_name = "Idle";
|
||||
if animations.named_animations.contains_key(anim_name) {
|
||||
let clip = animations.named_animations.get(anim_name).unwrap();
|
||||
anim_player.play_with_transition(clip.clone(), Duration::from_secs(5)).repeat();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
use bevy::app::AppExit;
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||
pub enum AppState {
|
||||
#[default]
|
||||
CoreLoading,
|
||||
MenuRunning,
|
||||
AppLoading,
|
||||
AppRunning,
|
||||
AppEnding,
|
||||
|
||||
// FIXME: not sure
|
||||
LoadingGame,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||
pub enum GameState {
|
||||
#[default]
|
||||
None,
|
||||
|
||||
InMenu,
|
||||
InGame,
|
||||
|
||||
InGameOver,
|
||||
|
||||
InSaving,
|
||||
InLoading,
|
||||
}
|
||||
|
||||
// tag components for all entities within a certain state (for despawning them if needed) , FIXME: seems kinda hack-ish
|
||||
#[derive(Component)]
|
||||
pub struct InCoreLoading;
|
||||
#[derive(Component, Default)]
|
||||
pub struct InMenuRunning;
|
||||
#[derive(Component)]
|
||||
pub struct InAppLoading;
|
||||
#[derive(Component)]
|
||||
pub struct InAppRunning;
|
||||
|
||||
// components for tagging in game vs in game menu stuff
|
||||
#[derive(Component, Default)]
|
||||
pub struct InMainMenu;
|
||||
#[derive(Component, Default)]
|
||||
pub struct InMenu;
|
||||
#[derive(Component, Default)]
|
||||
pub struct InGame;
|
||||
|
||||
pub struct StatePlugin;
|
||||
impl Plugin for StatePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_state::<AppState>().add_state::<GameState>();
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
[package]
|
||||
name = "bevy_gltf_blueprints_basic_example"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.13", features = ["dynamic_linking"] }
|
||||
bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" }
|
||||
bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" }
|
||||
bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||
rand = "0.8.5"
|
@ -1 +0,0 @@
|
||||
({})
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,12 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
pub struct CorePlugin;
|
||||
impl Plugin for CorePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins((BlueprintsPlugin {
|
||||
aabbs: true,
|
||||
..Default::default()
|
||||
},));
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, GameWorldTag};
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning};
|
||||
use bevy_rapier3d::prelude::Velocity;
|
||||
use rand::Rng;
|
||||
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
game_assets: Res<GameAssets>,
|
||||
models: Res<Assets<bevy::gltf::Gltf>>,
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.2,
|
||||
});
|
||||
// here we actually spawn our game world/level
|
||||
|
||||
commands.spawn((
|
||||
SceneBundle {
|
||||
// note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene
|
||||
scene: models
|
||||
.get(game_assets.world.clone().unwrap().id())
|
||||
.expect("main level should have been loaded")
|
||||
.scenes[0]
|
||||
.clone(),
|
||||
..default()
|
||||
},
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct UnregisteredComponent;
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyT) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Health_Pickup".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_test_unregisted_components(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyU) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Health_Pickup".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
UnregisteredComponent,
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, InMainMenu};
|
||||
|
||||
pub fn setup_main_menu(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
Camera2dBundle {
|
||||
camera: Camera {
|
||||
order: 102, // needed because of this: https://github.com/jakobhellermann/bevy_editor_pls/blob/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs#L213C9-L213C28
|
||||
..default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"SOME GAME TITLE !!",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(100.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(200.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
/*
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Load Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(250.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Exit Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(300.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));*/
|
||||
}
|
||||
|
||||
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands) {
|
||||
for bli in bla.iter() {
|
||||
commands.entity(bli).despawn_recursive();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_menu(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
|
||||
mut next_app_state: ResMut<NextState<AppState>>,
|
||||
// mut next_game_state: ResMut<NextState<GameState>>,
|
||||
// mut save_requested_events: EventWriter<SaveRequest>,
|
||||
// mut load_requested_events: EventWriter<LoadRequest>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::Enter) {
|
||||
next_app_state.set(AppState::AppLoading);
|
||||
// next_game_state.set(GameState::None);
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyL) {
|
||||
next_app_state.set(AppState::AppLoading);
|
||||
// load_requested_events.send(LoadRequest { path: "toto".into() })
|
||||
}
|
||||
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
// save_requested_events.send(SaveRequest { path: "toto".into() })
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
pub mod in_game;
|
||||
pub use in_game::*;
|
||||
|
||||
pub mod in_main_menu;
|
||||
pub use in_main_menu::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
|
||||
|
||||
pub struct GamePlugin;
|
||||
impl Plugin for GamePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(
|
||||
Update,
|
||||
(spawn_test, spawn_test_unregisted_components).run_if(in_state(GameState::InGame)),
|
||||
)
|
||||
.add_systems(OnEnter(AppState::MenuRunning), setup_main_menu)
|
||||
.add_systems(OnExit(AppState::MenuRunning), teardown_main_menu)
|
||||
.add_systems(Update, main_menu.run_if(in_state(AppState::MenuRunning)))
|
||||
.add_systems(OnEnter(AppState::AppRunning), setup_game);
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::CommonPlugin;
|
||||
|
||||
mod core;
|
||||
use crate::core::*;
|
||||
|
||||
mod game;
|
||||
use game::*;
|
||||
|
||||
mod test_components;
|
||||
use test_components::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
CommonPlugin,
|
||||
CorePlugin, // reusable plugins
|
||||
GamePlugin, // specific to our game
|
||||
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||
))
|
||||
.run();
|
||||
}
|
@ -1 +0,0 @@
|
||||
({})
|
@ -1,6 +0,0 @@
|
||||
({
|
||||
"world":File (path: "models/World.glb"),
|
||||
"models": Folder (
|
||||
path: "models/library",
|
||||
),
|
||||
})
|
10
examples/blenvy/blueprints/Cargo.toml
Normal file
10
examples/blenvy/blueprints/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "blenvy_blueprints_example"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.14", features = ["dynamic_linking"] }
|
||||
blenvy = { path = "../../../crates/blenvy" }
|
||||
rand = "0.8.5"
|
BIN
examples/blenvy/blueprints/art/blueprints.blend
Normal file
BIN
examples/blenvy/blueprints/art/blueprints.blend
Normal file
Binary file not shown.
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 243 KiB |
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 174 KiB |
@ -56,8 +56,8 @@ pub enum EnumTest {
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct ComponentsTestPlugin;
|
||||
impl Plugin for ComponentsTestPlugin {
|
||||
pub struct ComponentsExamplesPlugin;
|
||||
impl Plugin for ComponentsExamplesPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<BasicTest>()
|
||||
.register_type::<TupleTestF32>()
|
76
examples/blenvy/blueprints/src/main.rs
Normal file
76
examples/blenvy/blueprints/src/main.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use bevy::prelude::*;
|
||||
use blenvy::{AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
use rand::Rng;
|
||||
|
||||
mod component_examples;
|
||||
use component_examples::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||
BlenvyPlugin::default()
|
||||
))
|
||||
|
||||
.add_systems(Startup, setup_game)
|
||||
.add_systems(Update, spawn_blueprint_instance)
|
||||
|
||||
.run();
|
||||
}
|
||||
|
||||
// this is how you setup & spawn a level from a blueprint
|
||||
fn setup_game(
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
// here we spawn our game world/level, which is also a blueprint !
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// you can also spawn blueprint instances at runtime
|
||||
pub fn spawn_blueprint_instance(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyS) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintInfo {
|
||||
name: "spawned".into(),
|
||||
path: "blueprints/Blueprint 3.gltf".into(),
|
||||
}, // FIXME
|
||||
..Default::default()
|
||||
},
|
||||
DynamicBlueprintInstance,
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
HideUntilReady,
|
||||
AddToGameWorld,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
|
||||
))
|
||||
.id();
|
||||
// commands.entity(world).add_child(new_entity);
|
||||
|
||||
}
|
||||
}
|
10
examples/blenvy/components/Cargo.toml
Normal file
10
examples/blenvy/components/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "blenvy_components_example"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.14", features = ["dynamic_linking"] }
|
||||
blenvy = { path = "../../../crates/blenvy" }
|
||||
#bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" }
|
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Container.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Container.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Enemy.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Enemy.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Finger.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Finger.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Hand.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Hand.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Health_Pickup.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Health_Pickup.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Humanoid_cactus.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Humanoid_cactus.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/MagicTeapot.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/MagicTeapot.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Pillar.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Pillar.glb
Normal file
Binary file not shown.
BIN
examples/blenvy/components/assets/blueprints/Player.glb
Normal file
BIN
examples/blenvy/components/assets/blueprints/Player.glb
Normal file
Binary file not shown.
Binary file not shown.
BIN
examples/blenvy/components/assets/levels/World.glb
Normal file
BIN
examples/blenvy/components/assets/levels/World.glb
Normal file
Binary file not shown.
14082
examples/blenvy/components/assets/registry.json
Normal file
14082
examples/blenvy/components/assets/registry.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,8 +60,8 @@ pub enum EnumTest {
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct ComponentsTestPlugin;
|
||||
impl Plugin for ComponentsTestPlugin {
|
||||
pub struct ComponentsExamplesPlugin;
|
||||
impl Plugin for ComponentsExamplesPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<BasicTest>()
|
||||
.register_type::<UnitTest>()
|
32
examples/blenvy/components/src/main.rs
Normal file
32
examples/blenvy/components/src/main.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use bevy::prelude::*;
|
||||
use blenvy::{BlenvyPlugin, BlueprintInfo, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
||||
|
||||
mod component_examples;
|
||||
use component_examples::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||
BlenvyPlugin::default()
|
||||
))
|
||||
|
||||
.add_systems(Startup, setup_game)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
||||
fn setup_game(
|
||||
mut commands: Commands,
|
||||
) {
|
||||
|
||||
// here we actually spawn our game world/level
|
||||
commands.spawn((
|
||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||
SpawnBlueprint, // and spawnblueprint to tell blenvy to spawn the blueprint now
|
||||
HideUntilReady, // only reveal the level once it is ready
|
||||
GameWorldTag,
|
||||
));
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
[package]
|
||||
name = "bevy_gltf_blueprints_materials_example"
|
||||
version = "0.3.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
bevy = { version = "0.13", features = ["dynamic_linking"] }
|
||||
bevy_gltf_blueprints = { path = "../../../crates/bevy_gltf_blueprints" }
|
||||
bevy_gltf_worlflow_examples_common_rapier = { path = "../../common_rapier" }
|
||||
bevy_rapier3d = { version = "0.25.0", features = ["serde-serialize", "debug-render-3d", "enhanced-determinism"] }
|
||||
rand = "0.8.5"
|
@ -1 +0,0 @@
|
||||
({})
|
@ -1,9 +0,0 @@
|
||||
({
|
||||
"world":File (path: "models/Level1.glb"),
|
||||
"models": Folder (
|
||||
path: "models/library",
|
||||
),
|
||||
"materials": Folder (
|
||||
path: "materials",
|
||||
),
|
||||
})
|
Binary file not shown.
@ -1,12 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::*;
|
||||
|
||||
pub struct CorePlugin;
|
||||
impl Plugin for CorePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_plugins((BlueprintsPlugin {
|
||||
material_library: true,
|
||||
..Default::default()
|
||||
},));
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_blueprints::{BluePrintBundle, BlueprintName, GameWorldTag};
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning};
|
||||
|
||||
use bevy_rapier3d::prelude::Velocity;
|
||||
use rand::Rng;
|
||||
|
||||
pub fn setup_game(
|
||||
mut commands: Commands,
|
||||
game_assets: Res<GameAssets>,
|
||||
models: Res<Assets<bevy::gltf::Gltf>>,
|
||||
mut next_game_state: ResMut<NextState<GameState>>,
|
||||
) {
|
||||
commands.insert_resource(AmbientLight {
|
||||
color: Color::WHITE,
|
||||
brightness: 0.2,
|
||||
});
|
||||
// here we actually spawn our game world/level
|
||||
|
||||
commands.spawn((
|
||||
SceneBundle {
|
||||
// note: because of this issue https://github.com/bevyengine/bevy/issues/10436, "world" is now a gltf file instead of a scene
|
||||
scene: models
|
||||
.get(game_assets.world.clone().unwrap().id())
|
||||
.expect("main level should have been loaded")
|
||||
.scenes[0]
|
||||
.clone(),
|
||||
..default()
|
||||
},
|
||||
bevy::prelude::Name::from("world"),
|
||||
GameWorldTag,
|
||||
InAppRunning,
|
||||
));
|
||||
|
||||
next_game_state.set(GameState::InGame)
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Default, Debug)]
|
||||
#[reflect(Component)]
|
||||
struct UnregisteredComponent;
|
||||
|
||||
pub fn spawn_test(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut commands: Commands,
|
||||
|
||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::KeyT) {
|
||||
let world = game_world.single_mut();
|
||||
let world = world.1[0];
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 5.5;
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = 0.8;
|
||||
let vel_x: f32 = rng.gen_range(-range..range);
|
||||
let vel_y: f32 = rng.gen_range(2.0..2.5);
|
||||
let vel_z: f32 = rng.gen_range(-range..range);
|
||||
|
||||
let name_index: u64 = rng.gen();
|
||||
|
||||
let new_entity = commands
|
||||
.spawn((
|
||||
BluePrintBundle {
|
||||
blueprint: BlueprintName("Watermelon2".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||
// BlueprintName("Health_Pickup".to_string()),
|
||||
// SpawnHere,
|
||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||
Velocity {
|
||||
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||
},
|
||||
))
|
||||
.id();
|
||||
commands.entity(world).add_child(new_entity);
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, InMainMenu};
|
||||
|
||||
pub fn setup_main_menu(mut commands: Commands) {
|
||||
commands.spawn((
|
||||
Camera2dBundle {
|
||||
camera: Camera {
|
||||
order: 102, // needed because of this: https://github.com/jakobhellermann/bevy_editor_pls/blob/crates/bevy_editor_pls_default_windows/src/cameras/mod.rs#L213C9-L213C28
|
||||
..default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"SOME GAME TITLE !!",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(100.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(200.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu,
|
||||
));
|
||||
|
||||
/*
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Load Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(250.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));
|
||||
|
||||
commands.spawn((
|
||||
TextBundle::from_section(
|
||||
"Exit Game",
|
||||
TextStyle {
|
||||
//font: asset_server.load("fonts/FiraMono-Medium.ttf"),
|
||||
font_size: 18.0,
|
||||
color: Color::WHITE,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.with_style(Style {
|
||||
position_type: PositionType::Absolute,
|
||||
top: Val::Px(300.0),
|
||||
left: Val::Px(200.0),
|
||||
..default()
|
||||
}),
|
||||
InMainMenu
|
||||
));*/
|
||||
}
|
||||
|
||||
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands) {
|
||||
for bli in bla.iter() {
|
||||
commands.entity(bli).despawn_recursive();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_menu(
|
||||
keycode: Res<ButtonInput<KeyCode>>,
|
||||
mut next_app_state: ResMut<NextState<AppState>>,
|
||||
) {
|
||||
if keycode.just_pressed(KeyCode::Enter) {
|
||||
next_app_state.set(AppState::AppLoading);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
pub mod in_game;
|
||||
pub use in_game::*;
|
||||
|
||||
pub mod in_main_menu;
|
||||
pub use in_main_menu::*;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::{AppState, GameState};
|
||||
|
||||
pub struct GamePlugin;
|
||||
impl Plugin for GamePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(Update, (spawn_test).run_if(in_state(GameState::InGame)))
|
||||
.add_systems(OnEnter(AppState::MenuRunning), setup_main_menu)
|
||||
.add_systems(OnExit(AppState::MenuRunning), teardown_main_menu)
|
||||
.add_systems(Update, main_menu.run_if(in_state(AppState::MenuRunning)))
|
||||
.add_systems(OnEnter(AppState::AppRunning), setup_game);
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
use bevy_gltf_worlflow_examples_common_rapier::CommonPlugin;
|
||||
|
||||
mod core;
|
||||
use crate::core::*;
|
||||
|
||||
mod game;
|
||||
use game::*;
|
||||
|
||||
mod test_components;
|
||||
use test_components::*;
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(AssetPlugin::default()),
|
||||
// our custom plugins
|
||||
CommonPlugin,
|
||||
CorePlugin, // reusable plugins
|
||||
GamePlugin, // specific to our game
|
||||
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||
))
|
||||
.run();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user