mirror of
https://github.com/kaosat-dev/Blender_bevy_components_workflow.git
synced 2024-11-22 11:50:53 +00:00
chore(): cargo fmt (#21)
This commit is contained in:
parent
a1c32ae1d6
commit
f41a315563
@ -1,66 +1,66 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
use bevy::ecs::system::Command;
|
use bevy::ecs::system::Command;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
// modified version from https://github.com/bevyengine/bevy/issues/1515,
|
// modified version from https://github.com/bevyengine/bevy/issues/1515,
|
||||||
// more specifically https://gist.github.com/nwtnni/85d6b87ae75337a522166c500c9a8418
|
// more specifically https://gist.github.com/nwtnni/85d6b87ae75337a522166c500c9a8418
|
||||||
// to work with Bevy 0.11
|
// to work with Bevy 0.11
|
||||||
pub struct CloneEntity {
|
pub struct CloneEntity {
|
||||||
pub source: Entity,
|
pub source: Entity,
|
||||||
pub destination: Entity,
|
pub destination: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CloneEntity {
|
impl CloneEntity {
|
||||||
// Copy all components from an entity to another.
|
// Copy all components from an entity to another.
|
||||||
// Using an entity with no components as the destination creates a copy of the source entity.
|
// Using an entity with no components as the destination creates a copy of the source entity.
|
||||||
// Panics if:
|
// Panics if:
|
||||||
// - the components are not registered in the type registry,
|
// - the components are not registered in the type registry,
|
||||||
// - the world does not have a type registry
|
// - the world does not have a type registry
|
||||||
// - the source or destination entity do not exist
|
// - the source or destination entity do not exist
|
||||||
fn clone_entity(self, world: &mut World) {
|
fn clone_entity(self, world: &mut World) {
|
||||||
let components = {
|
let components = {
|
||||||
let registry = world.get_resource::<AppTypeRegistry>().unwrap().read();
|
let registry = world.get_resource::<AppTypeRegistry>().unwrap().read();
|
||||||
|
|
||||||
world
|
world
|
||||||
.get_entity(self.source)
|
.get_entity(self.source)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.archetype()
|
.archetype()
|
||||||
.components()
|
.components()
|
||||||
.map(|component_id| {
|
.map(|component_id| {
|
||||||
world
|
world
|
||||||
.components()
|
.components()
|
||||||
.get_info(component_id)
|
.get_info(component_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.type_id()
|
.type_id()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
.map(|type_id| {
|
.map(|type_id| {
|
||||||
// println!("type_id {:?}", type_id);
|
// println!("type_id {:?}", type_id);
|
||||||
registry
|
registry
|
||||||
.get(type_id)
|
.get(type_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.data::<ReflectComponent>()
|
.data::<ReflectComponent>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
for component in components {
|
for component in components {
|
||||||
let source = component
|
let source = component
|
||||||
.reflect(world.get_entity(self.source).unwrap())
|
.reflect(world.get_entity(self.source).unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone_value();
|
.clone_value();
|
||||||
|
|
||||||
let mut destination = world.get_entity_mut(self.destination).unwrap();
|
let mut destination = world.get_entity_mut(self.destination).unwrap();
|
||||||
|
|
||||||
component.apply_or_insert(&mut destination, &*source);
|
component.apply_or_insert(&mut destination, &*source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This allows the command to be used in systems
|
// This allows the command to be used in systems
|
||||||
impl Command for CloneEntity {
|
impl Command for CloneEntity {
|
||||||
fn apply(self, world: &mut World) {
|
fn apply(self, world: &mut World) {
|
||||||
self.clone_entity(world)
|
self.clone_entity(world)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
pub mod spawn_from_blueprints;
|
pub mod spawn_from_blueprints;
|
||||||
pub use spawn_from_blueprints::*;
|
pub use spawn_from_blueprints::*;
|
||||||
|
|
||||||
@ -16,28 +14,27 @@ use bevy_gltf_components::GltfComponentsSet;
|
|||||||
|
|
||||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
/// set for the two stages of blueprint based spawning :
|
/// set for the two stages of blueprint based spawning :
|
||||||
pub enum GltfBlueprintsSet{
|
pub enum GltfBlueprintsSet {
|
||||||
Spawn,
|
Spawn,
|
||||||
AfterSpawn,
|
AfterSpawn,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct BluePrintBundle {
|
pub struct BluePrintBundle {
|
||||||
pub blueprint: BlueprintName,
|
pub blueprint: BlueprintName,
|
||||||
pub spawn_here: SpawnHere,
|
pub spawn_here: SpawnHere,
|
||||||
pub transform: TransformBundle
|
pub transform: TransformBundle,
|
||||||
}
|
}
|
||||||
impl Default for BluePrintBundle {
|
impl Default for BluePrintBundle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
BluePrintBundle {
|
BluePrintBundle {
|
||||||
blueprint: BlueprintName("default".into()),
|
blueprint: BlueprintName("default".into()),
|
||||||
spawn_here: SpawnHere,
|
spawn_here: SpawnHere,
|
||||||
transform: TransformBundle::default()
|
transform: TransformBundle::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Resource)]
|
#[derive(Clone, Resource)]
|
||||||
pub(crate) struct BluePrintsConfig {
|
pub(crate) struct BluePrintsConfig {
|
||||||
pub(crate) library_folder: PathBuf,
|
pub(crate) library_folder: PathBuf,
|
||||||
@ -45,49 +42,49 @@ pub(crate) struct BluePrintsConfig {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BlueprintsPlugin {
|
pub struct BlueprintsPlugin {
|
||||||
/// The base folder where library/blueprints assets are loaded from, relative to the executable.
|
/// The base folder where library/blueprints assets are loaded from, relative to the executable.
|
||||||
pub library_folder: PathBuf,
|
pub library_folder: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BlueprintsPlugin {
|
impl Default for BlueprintsPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
library_folder: PathBuf::from("assets/models/library"),
|
library_folder: PathBuf::from("assets/models/library"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for BlueprintsPlugin {
|
impl Plugin for BlueprintsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<BlueprintName>()
|
||||||
.register_type::<BlueprintName>()
|
.register_type::<SpawnHere>()
|
||||||
.register_type::<SpawnHere>()
|
.insert_resource(BluePrintsConfig {
|
||||||
.insert_resource(BluePrintsConfig{library_folder: self.library_folder.clone()})
|
library_folder: self.library_folder.clone(),
|
||||||
|
})
|
||||||
.configure_sets(
|
.configure_sets(
|
||||||
Update,
|
Update,
|
||||||
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn).chain().after(GltfComponentsSet::Injection)
|
(GltfBlueprintsSet::Spawn, GltfBlueprintsSet::AfterSpawn)
|
||||||
)
|
.chain()
|
||||||
|
.after(GltfComponentsSet::Injection),
|
||||||
.add_systems(Update,
|
)
|
||||||
(spawn_from_blueprints)
|
.add_systems(
|
||||||
// .run_if(in_state(AppState::AppRunning).or_else(in_state(AppState::LoadingGame))) // FIXME: how to replace this with a crate compatible version ?
|
Update,
|
||||||
.in_set(GltfBlueprintsSet::Spawn),
|
(spawn_from_blueprints)
|
||||||
)
|
// .run_if(in_state(AppState::AppRunning).or_else(in_state(AppState::LoadingGame))) // FIXME: how to replace this with a crate compatible version ?
|
||||||
|
.in_set(GltfBlueprintsSet::Spawn),
|
||||||
.add_systems(
|
)
|
||||||
Update,
|
.add_systems(
|
||||||
(
|
Update,
|
||||||
// spawn_entities,
|
(
|
||||||
update_spawned_root_first_child,
|
// spawn_entities,
|
||||||
apply_deferred,
|
update_spawned_root_first_child,
|
||||||
cleanup_scene_instances,
|
apply_deferred,
|
||||||
apply_deferred,
|
cleanup_scene_instances,
|
||||||
)
|
apply_deferred,
|
||||||
.chain()
|
)
|
||||||
// .run_if(in_state(AppState::LoadingGame).or_else(in_state(AppState::AppRunning))) // FIXME: how to replace this with a crate compatible version ?
|
.chain()
|
||||||
.in_set(GltfBlueprintsSet::AfterSpawn),
|
// .run_if(in_state(AppState::LoadingGame).or_else(in_state(AppState::AppRunning))) // FIXME: how to replace this with a crate compatible version ?
|
||||||
)
|
.in_set(GltfBlueprintsSet::AfterSpawn),
|
||||||
;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use bevy::{prelude::*, gltf::Gltf};
|
use bevy::{gltf::Gltf, prelude::*};
|
||||||
|
|
||||||
use crate::BluePrintsConfig;
|
use crate::BluePrintsConfig;
|
||||||
|
|
||||||
@ -9,12 +9,12 @@ use crate::BluePrintsConfig;
|
|||||||
pub struct GameWorldTag;
|
pub struct GameWorldTag;
|
||||||
|
|
||||||
/// Main component for the blueprints
|
/// Main component for the blueprints
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BlueprintName(pub String);
|
pub struct BlueprintName(pub String);
|
||||||
|
|
||||||
/// flag component needed to signify the intent to spawn a Blueprint
|
/// flag component needed to signify the intent to spawn a Blueprint
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct SpawnHere;
|
pub struct SpawnHere;
|
||||||
|
|
||||||
@ -22,7 +22,6 @@ pub struct SpawnHere;
|
|||||||
/// FlagComponent for spawned entity
|
/// FlagComponent for spawned entity
|
||||||
pub struct Spawned;
|
pub struct Spawned;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
/// helper component, just to transfer some data
|
/// helper component, just to transfer some data
|
||||||
pub(crate) struct Original(pub Entity);
|
pub(crate) struct Original(pub Entity);
|
||||||
@ -34,53 +33,66 @@ pub struct SpawnedRoot;
|
|||||||
/// main spawning functions,
|
/// main spawning functions,
|
||||||
/// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint
|
/// * also takes into account the already exisiting "override" components, ie "override components" > components from blueprint
|
||||||
pub(crate) fn spawn_from_blueprints(
|
pub(crate) fn spawn_from_blueprints(
|
||||||
spawn_placeholders: Query<(Entity, &Name, &BlueprintName, &Transform), (Added<BlueprintName>, Added<SpawnHere>, Without<Spawned>, Without<SpawnedRoot>)>,
|
spawn_placeholders: Query<
|
||||||
|
(Entity, &Name, &BlueprintName, &Transform),
|
||||||
|
(
|
||||||
|
Added<BlueprintName>,
|
||||||
|
Added<SpawnHere>,
|
||||||
|
Without<Spawned>,
|
||||||
|
Without<SpawnedRoot>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||||
|
|
||||||
assets_gltf: Res<Assets<Gltf>>,
|
assets_gltf: Res<Assets<Gltf>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
blueprints_config: Res<BluePrintsConfig>
|
blueprints_config: Res<BluePrintsConfig>,
|
||||||
){
|
) {
|
||||||
|
|
||||||
for (entity, name, blupeprint_name, global_transform) in spawn_placeholders.iter() {
|
for (entity, name, blupeprint_name, global_transform) in spawn_placeholders.iter() {
|
||||||
info!("need to spawn {:?}", blupeprint_name.0);
|
info!("need to spawn {:?}", blupeprint_name.0);
|
||||||
let what = &blupeprint_name.0;
|
let what = &blupeprint_name.0;
|
||||||
let model_file_name = format!("{}.glb",&what);
|
let model_file_name = format!("{}.glb", &what);
|
||||||
let model_path = Path::new(&blueprints_config.library_folder)
|
let model_path =
|
||||||
.join(Path::new(model_file_name.as_str()));
|
Path::new(&blueprints_config.library_folder).join(Path::new(model_file_name.as_str()));
|
||||||
|
|
||||||
info!("attempting to spawn {:?}",model_path);
|
info!("attempting to spawn {:?}", model_path);
|
||||||
let scene:Handle<Gltf> = asset_server.load(model_path);
|
let scene: Handle<Gltf> = asset_server.load(model_path);
|
||||||
// let scene = game_assets.models.get(&model_path).expect(&format!("no matching model {:?} found", model_path));
|
// let scene = game_assets.models.get(&model_path).expect(&format!("no matching model {:?} found", model_path));
|
||||||
|
|
||||||
let world = game_world.single_mut();
|
let world = game_world.single_mut();
|
||||||
let world = world.1[0]; // FIXME: dangerous hack because our gltf data have a single child like this, but might not always be the case
|
let world = world.1[0]; // FIXME: dangerous hack because our gltf data have a single child like this, but might not always be the case
|
||||||
|
|
||||||
let gltf = assets_gltf.get(&scene).expect("this gltf should have been loaded");
|
let gltf = assets_gltf
|
||||||
|
.get(&scene)
|
||||||
|
.expect("this gltf should have been loaded");
|
||||||
// WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one
|
// WARNING we work under the assumtion that there is ONLY ONE named scene, and that the first one is the right one
|
||||||
let main_scene_name =gltf.named_scenes.keys().nth(0).expect("there should be at least one named scene in the gltf file to spawn");
|
let main_scene_name = gltf
|
||||||
|
.named_scenes
|
||||||
|
.keys()
|
||||||
|
.nth(0)
|
||||||
|
.expect("there should be at least one named scene in the gltf file to spawn");
|
||||||
let scene = &gltf.named_scenes[main_scene_name];
|
let scene = &gltf.named_scenes[main_scene_name];
|
||||||
|
|
||||||
|
|
||||||
//spawn_requested_events.send(SpawnRequestedEvent { what: "enemy".into(), position, amount: 1, spawner_id: None });
|
//spawn_requested_events.send(SpawnRequestedEvent { what: "enemy".into(), position, amount: 1, spawner_id: None });
|
||||||
let child_scene = commands.spawn(
|
let child_scene = commands
|
||||||
(
|
.spawn((
|
||||||
SceneBundle {
|
SceneBundle {
|
||||||
scene: scene.clone(),
|
scene: scene.clone(),
|
||||||
transform: global_transform.clone(),
|
transform: global_transform.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
bevy::prelude::Name::from(["scene_wrapper", &name.clone()].join("_") ),
|
bevy::prelude::Name::from(["scene_wrapper", &name.clone()].join("_")),
|
||||||
// Parent(world) // FIXME/ would be good if this worked directly
|
// Parent(world) // FIXME/ would be good if this worked directly
|
||||||
SpawnedRoot,
|
SpawnedRoot,
|
||||||
/*AnimationHelper{ // TODO: insert this at the ENTITY level, not the scene level
|
/*AnimationHelper{ // TODO: insert this at the ENTITY level, not the scene level
|
||||||
named_animations: gltf.named_animations.clone(),
|
named_animations: gltf.named_animations.clone(),
|
||||||
// animations: gltf.named_animations.values().clone()
|
// animations: gltf.named_animations.values().clone()
|
||||||
},*/
|
},*/
|
||||||
Original(entity)
|
Original(entity),
|
||||||
)).id();
|
))
|
||||||
commands.entity(world).add_child(child_scene);
|
.id();
|
||||||
|
commands.entity(world).add_child(child_scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,20 +4,17 @@ use bevy::utils::HashMap;
|
|||||||
use super::{CloneEntity, SpawnHere};
|
use super::{CloneEntity, SpawnHere};
|
||||||
use super::{Original, SpawnedRoot};
|
use super::{Original, SpawnedRoot};
|
||||||
|
|
||||||
|
|
||||||
// FIXME: move to more relevant module
|
// FIXME: move to more relevant module
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct AnimationHelper {
|
pub struct AnimationHelper {
|
||||||
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
pub named_animations: HashMap<String, Handle<AnimationClip>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
/// FlagComponent for dynamically spawned scenes
|
/// FlagComponent for dynamically spawned scenes
|
||||||
pub(crate) struct SpawnedRootProcessed;
|
pub(crate) struct SpawnedRootProcessed;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// this system updates the first (and normally only) child of a scene flaged SpawnedRoot
|
/// this system updates the first (and normally only) child of a scene flaged SpawnedRoot
|
||||||
/// - adds a name based on parent component (spawned scene) which is named on the scene name/prefab to be instanciated
|
/// - adds a name based on parent component (spawned scene) which is named on the scene name/prefab to be instanciated
|
||||||
/// - adds the initial physics impulse (FIXME: we would need to add a temporary physics component to those who do not have it)
|
/// - adds the initial physics impulse (FIXME: we would need to add a temporary physics component to those who do not have it)
|
||||||
@ -26,15 +23,18 @@ pub(crate) struct SpawnedRootProcessed;
|
|||||||
// - scene instance -> does not work
|
// - scene instance -> does not work
|
||||||
// it might be due to how we add components to the PARENT item in gltf to components
|
// it might be due to how we add components to the PARENT item in gltf to components
|
||||||
pub(crate) fn update_spawned_root_first_child(
|
pub(crate) fn update_spawned_root_first_child(
|
||||||
// all_children: Query<(Entity, &Children)>,
|
// all_children: Query<(Entity, &Children)>,
|
||||||
unprocessed_entities :Query<(Entity, &Children, &Name, &Parent, &Original ), (With<SpawnedRoot>, Without<SpawnedRootProcessed>)>,
|
unprocessed_entities: Query<
|
||||||
mut commands: Commands,
|
(Entity, &Children, &Name, &Parent, &Original),
|
||||||
|
(With<SpawnedRoot>, Without<SpawnedRootProcessed>),
|
||||||
|
>,
|
||||||
|
mut commands: Commands,
|
||||||
|
|
||||||
// FIXME: should be done at a more generic gltf level
|
// FIXME: should be done at a more generic gltf level
|
||||||
animation_helpers: Query<&AnimationHelper>,
|
animation_helpers: Query<&AnimationHelper>,
|
||||||
added_animation_helpers : Query<(Entity, &AnimationPlayer), Added<AnimationPlayer>>
|
added_animation_helpers: Query<(Entity, &AnimationPlayer), Added<AnimationPlayer>>,
|
||||||
){
|
) {
|
||||||
/*
|
/*
|
||||||
currently we have
|
currently we have
|
||||||
- scene instance
|
- scene instance
|
||||||
- root node ?
|
- root node ?
|
||||||
@ -56,82 +56,80 @@ pub(crate) fn update_spawned_root_first_child(
|
|||||||
FIME: this is all highly dependent on the hierachy ;..
|
FIME: this is all highly dependent on the hierachy ;..
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (scene_instance, children, name, parent, original) in unprocessed_entities.iter() {
|
for (scene_instance, children, name, parent, original) in unprocessed_entities.iter() {
|
||||||
//
|
//
|
||||||
if children.len() == 0 {
|
if children.len() == 0 {
|
||||||
warn!("timing issue ! no children found, please restart your bevy app (bug being investigated)");
|
warn!("timing issue ! no children found, please restart your bevy app (bug being investigated)");
|
||||||
// println!("children of scene {:?}", children);
|
// println!("children of scene {:?}", children);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
// the root node is the first & normally only child inside a scene, it is the one that has all relevant components
|
|
||||||
let root_entity = children.first().unwrap(); //FIXME: and what about childless ones ?? => should not be possible normally
|
|
||||||
// let root_entity_data = all_children.get(*root_entity).unwrap();
|
|
||||||
|
|
||||||
// fixme : randomization should be controlled via parameters, perhaps even the seed could be specified ?
|
|
||||||
// use this https://rust-random.github.io/book/guide-seeding.html#a-simple-number, blenders seeds are also uInts
|
|
||||||
// also this is not something we want every time, this should be a settable parameter when requesting a spawn
|
|
||||||
|
|
||||||
|
|
||||||
// add missing name of entity, based on the wrapper's name
|
|
||||||
let name= name.clone().replace("scene_wrapper_", "");
|
|
||||||
|
|
||||||
// this is our new actual entity
|
|
||||||
commands.entity(*root_entity).insert((
|
|
||||||
bevy::prelude::Name::from(name.clone()),
|
|
||||||
// ItemType {name},
|
|
||||||
// Spawned, // FIXME: not sure
|
|
||||||
));
|
|
||||||
|
|
||||||
// flag the spawned_root as being processed
|
|
||||||
commands.entity(scene_instance).insert(SpawnedRootProcessed);
|
|
||||||
|
|
||||||
|
|
||||||
// let original_transforms =
|
|
||||||
// parent is either the world or an entity with a marker (BlueprintName)
|
|
||||||
commands.entity(parent.get()).add_child(*root_entity);
|
|
||||||
// commands.entity(*root_entity).despawn_recursive();
|
|
||||||
// commands.entity(parent.get()).push_children(&actual_stuff);
|
|
||||||
//commands.entity(*root_entity).log_components();
|
|
||||||
|
|
||||||
let matching_animation_helper = animation_helpers.get(scene_instance);
|
|
||||||
|
|
||||||
// println!("WE HAVE SOME ADDED ANIMATION PLAYERS {:?}", matching_animation_helper);
|
|
||||||
if let Ok(anim_helper) = matching_animation_helper{
|
|
||||||
for (added, _) in added_animation_helpers.iter(){
|
|
||||||
commands.entity(added).insert(
|
|
||||||
AnimationHelper{ // TODO: insert this at the ENTITY level, not the scene level
|
|
||||||
named_animations: anim_helper.named_animations.clone(),
|
|
||||||
// animations: gltf.named_animations.values().clone()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
// the root node is the first & normally only child inside a scene, it is the one that has all relevant components
|
||||||
|
let root_entity = children.first().unwrap(); //FIXME: and what about childless ones ?? => should not be possible normally
|
||||||
|
// let root_entity_data = all_children.get(*root_entity).unwrap();
|
||||||
|
|
||||||
commands.add(CloneEntity {
|
// fixme : randomization should be controlled via parameters, perhaps even the seed could be specified ?
|
||||||
source: original.0,
|
// use this https://rust-random.github.io/book/guide-seeding.html#a-simple-number, blenders seeds are also uInts
|
||||||
destination: *root_entity,
|
// also this is not something we want every time, this should be a settable parameter when requesting a spawn
|
||||||
});
|
|
||||||
|
|
||||||
// remove the original entity, now that we have cloned it into the spawned scenes first child
|
// add missing name of entity, based on the wrapper's name
|
||||||
commands.entity(original.0).despawn_recursive();
|
let name = name.clone().replace("scene_wrapper_", "");
|
||||||
commands.entity(*root_entity).remove::<SpawnHere>();
|
|
||||||
}
|
// this is our new actual entity
|
||||||
|
commands.entity(*root_entity).insert((
|
||||||
|
bevy::prelude::Name::from(name.clone()),
|
||||||
|
// ItemType {name},
|
||||||
|
// Spawned, // FIXME: not sure
|
||||||
|
));
|
||||||
|
|
||||||
|
// flag the spawned_root as being processed
|
||||||
|
commands.entity(scene_instance).insert(SpawnedRootProcessed);
|
||||||
|
|
||||||
|
// let original_transforms =
|
||||||
|
// parent is either the world or an entity with a marker (BlueprintName)
|
||||||
|
commands.entity(parent.get()).add_child(*root_entity);
|
||||||
|
// commands.entity(*root_entity).despawn_recursive();
|
||||||
|
// commands.entity(parent.get()).push_children(&actual_stuff);
|
||||||
|
//commands.entity(*root_entity).log_components();
|
||||||
|
|
||||||
|
let matching_animation_helper = animation_helpers.get(scene_instance);
|
||||||
|
|
||||||
|
// println!("WE HAVE SOME ADDED ANIMATION PLAYERS {:?}", matching_animation_helper);
|
||||||
|
if let Ok(anim_helper) = matching_animation_helper {
|
||||||
|
for (added, _) in added_animation_helpers.iter() {
|
||||||
|
commands.entity(added).insert(AnimationHelper {
|
||||||
|
// TODO: insert this at the ENTITY level, not the scene level
|
||||||
|
named_animations: anim_helper.named_animations.clone(),
|
||||||
|
// animations: gltf.named_animations.values().clone()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.add(CloneEntity {
|
||||||
|
source: original.0,
|
||||||
|
destination: *root_entity,
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove the original entity, now that we have cloned it into the spawned scenes first child
|
||||||
|
commands.entity(original.0).despawn_recursive();
|
||||||
|
commands.entity(*root_entity).remove::<SpawnHere>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// cleans up dynamically spawned scenes so that they get despawned if they have no more children
|
/// cleans up dynamically spawned scenes so that they get despawned if they have no more children
|
||||||
pub(crate) fn cleanup_scene_instances(
|
pub(crate) fn cleanup_scene_instances(
|
||||||
scene_instances: Query<(Entity, &Children), With<SpawnedRootProcessed>>,
|
scene_instances: Query<(Entity, &Children), With<SpawnedRootProcessed>>,
|
||||||
without_children: Query<Entity, (With<SpawnedRootProcessed>, Without<Children>)>,// if there are not children left, bevy removes Children ?
|
without_children: Query<Entity, (With<SpawnedRootProcessed>, Without<Children>)>, // if there are not children left, bevy removes Children ?
|
||||||
mut commands: Commands
|
mut commands: Commands,
|
||||||
){
|
) {
|
||||||
for (entity, children) in scene_instances.iter(){
|
for (entity, children) in scene_instances.iter() {
|
||||||
if children.len() == 0{ // it seems this does not happen ?
|
if children.len() == 0 {
|
||||||
info!("cleaning up emptied spawned scene instance");
|
// it seems this does not happen ?
|
||||||
commands.entity(entity).despawn_recursive();
|
info!("cleaning up emptied spawned scene instance");
|
||||||
}
|
commands.entity(entity).despawn_recursive();
|
||||||
}
|
}
|
||||||
for entity in without_children.iter() {
|
}
|
||||||
info!("cleaning up emptied spawned scene instance");
|
for entity in without_children.iter() {
|
||||||
commands.entity(entity).despawn_recursive();
|
info!("cleaning up emptied spawned scene instance");
|
||||||
}
|
commands.entity(entity).despawn_recursive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,13 @@ use core::ops::Deref;
|
|||||||
use ron::Value;
|
use ron::Value;
|
||||||
use serde::de::DeserializeSeed;
|
use serde::de::DeserializeSeed;
|
||||||
|
|
||||||
use bevy::prelude::{ResMut, Assets, info, debug, Name, Parent, warn};
|
|
||||||
use bevy::ecs::{entity::Entity, reflect::ReflectComponent};
|
use bevy::ecs::{entity::Entity, reflect::ReflectComponent};
|
||||||
|
use bevy::gltf::{Gltf, GltfExtras};
|
||||||
|
use bevy::prelude::{debug, info, warn, Assets, Name, Parent, ResMut};
|
||||||
|
use bevy::reflect::serde::UntypedReflectDeserializer;
|
||||||
|
use bevy::reflect::{Reflect, TypeInfo, TypeRegistryInternal};
|
||||||
use bevy::scene::Scene;
|
use bevy::scene::Scene;
|
||||||
use bevy::utils::HashMap;
|
use bevy::utils::HashMap;
|
||||||
use bevy::reflect::serde::UntypedReflectDeserializer;
|
|
||||||
use bevy::reflect::{TypeRegistryInternal, TypeInfo, Reflect};
|
|
||||||
use bevy::gltf::{Gltf, GltfExtras};
|
|
||||||
|
|
||||||
use super::capitalize_first_letter;
|
use super::capitalize_first_letter;
|
||||||
|
|
||||||
@ -18,216 +18,227 @@ pub fn gltf_extras_to_components(
|
|||||||
gltf: &mut Gltf,
|
gltf: &mut Gltf,
|
||||||
scenes: &mut ResMut<Assets<Scene>>,
|
scenes: &mut ResMut<Assets<Scene>>,
|
||||||
type_registry: impl Deref<Target = TypeRegistryInternal>,
|
type_registry: impl Deref<Target = TypeRegistryInternal>,
|
||||||
gltf_name: &str
|
gltf_name: &str,
|
||||||
){
|
) {
|
||||||
let mut added_components = 0;
|
let mut added_components = 0;
|
||||||
for (_name, scene) in &gltf.named_scenes {
|
for (_name, scene) in &gltf.named_scenes {
|
||||||
debug!("gltf: {:?} scene name {:?}", gltf_name, _name);
|
debug!("gltf: {:?} scene name {:?}", gltf_name, _name);
|
||||||
|
|
||||||
let scene = scenes.get_mut(scene).unwrap();
|
let scene = scenes.get_mut(scene).unwrap();
|
||||||
|
|
||||||
let mut query = scene.world.query::<(Entity, &Name, &GltfExtras, &Parent)>();
|
let mut query = scene.world.query::<(Entity, &Name, &GltfExtras, &Parent)>();
|
||||||
let mut entity_components: HashMap<Entity, Vec<Box<dyn Reflect>> > = HashMap::new();
|
let mut entity_components: HashMap<Entity, Vec<Box<dyn Reflect>>> = HashMap::new();
|
||||||
for (entity, name, extras, parent) in query.iter(&scene.world) {
|
for (entity, name, extras, parent) in query.iter(&scene.world) {
|
||||||
debug!("Name: {}, entity {:?}, parent: {:?}", name, entity, parent);
|
debug!("Name: {}, entity {:?}, parent: {:?}", name, entity, parent);
|
||||||
let reflect_components = ronstring_to_reflect_component(&extras.value, &type_registry);
|
let reflect_components = ronstring_to_reflect_component(&extras.value, &type_registry);
|
||||||
added_components = reflect_components.len();
|
added_components = reflect_components.len();
|
||||||
debug!("Found components {}", added_components);
|
debug!("Found components {}", added_components);
|
||||||
|
|
||||||
// we assign the components specified /xxx_components objects to their parent node
|
// we assign the components specified /xxx_components objects to their parent node
|
||||||
let mut target_entity = entity;
|
let mut target_entity = entity;
|
||||||
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
// if the node contains "components" or ends with "_pa" (ie add to parent), the components will not be added to the entity itself but to its parent
|
||||||
// this is mostly used for Blender collections
|
// this is mostly used for Blender collections
|
||||||
if name.as_str().contains("components") || name.as_str().ends_with("_pa") {
|
if name.as_str().contains("components") || name.as_str().ends_with("_pa") {
|
||||||
debug!("adding components to parent");
|
debug!("adding components to parent");
|
||||||
target_entity = parent.get();
|
target_entity = parent.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("adding to {:?}", target_entity);
|
||||||
|
|
||||||
|
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
||||||
|
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
||||||
|
if entity_components.contains_key(&target_entity) {
|
||||||
|
let mut updated_components: Vec<Box<dyn Reflect>> = Vec::new();
|
||||||
|
let current_components = &entity_components[&target_entity];
|
||||||
|
// first inject the current components
|
||||||
|
for component in current_components {
|
||||||
|
updated_components.push(component.clone_value());
|
||||||
|
}
|
||||||
|
// then inject the new components: this also enables overwrite components set in the collection
|
||||||
|
for component in reflect_components {
|
||||||
|
updated_components.push(component.clone_value());
|
||||||
|
}
|
||||||
|
entity_components.insert(target_entity, updated_components);
|
||||||
|
} else {
|
||||||
|
entity_components.insert(target_entity, reflect_components);
|
||||||
|
}
|
||||||
|
// shorthand, did not manage to get it working
|
||||||
|
/* entity_components.insert(
|
||||||
|
target_entity,
|
||||||
|
if entity_components.contains_key(&target_entity) {
|
||||||
|
entity_components[&target_entity].push(reflect_components) } else { reflect_components }
|
||||||
|
);*/
|
||||||
|
|
||||||
|
debug!("-----value {:?}", &extras.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("adding to {:?}", target_entity);
|
// GltfNode
|
||||||
|
// find a way to link this name to the current entity ? => WOULD BE VERY USEFULL for animations & co !!
|
||||||
|
debug!("done pre-processing components, now adding them to entities");
|
||||||
|
for (entity, components) in entity_components {
|
||||||
|
if !components.is_empty() {
|
||||||
|
debug!("--entity {:?}, components {}", entity, components.len());
|
||||||
|
}
|
||||||
|
for component in components {
|
||||||
|
let mut entity_mut = scene.world.entity_mut(entity);
|
||||||
|
debug!("------adding {} {:?}", component.type_name(), component);
|
||||||
|
|
||||||
// if there where already components set to be added to this entity (for example when entity_data was refering to a parent), update the vec of entity_components accordingly
|
type_registry
|
||||||
// this allows for example blender collection to provide basic ecs data & the instances to override/ define their own values
|
.get_with_name(component.type_name())
|
||||||
if entity_components.contains_key(&target_entity) {
|
.unwrap() // Component was successfully deserialized, it has to be in the registry
|
||||||
let mut updated_components: Vec<Box<dyn Reflect>> = Vec::new();
|
.data::<ReflectComponent>()
|
||||||
let current_components = &entity_components[&target_entity];
|
.unwrap() // Hopefully, the component deserializer ensures those are components
|
||||||
// first inject the current components
|
.insert(&mut entity_mut, &*component);
|
||||||
for component in current_components {
|
|
||||||
updated_components.push(component.clone_value());
|
|
||||||
}
|
|
||||||
// then inject the new components: this also enables overwrite components set in the collection
|
|
||||||
for component in reflect_components {
|
|
||||||
updated_components.push(component.clone_value());
|
|
||||||
}
|
|
||||||
entity_components.insert(target_entity, updated_components);
|
|
||||||
|
|
||||||
|
// info!("all components {:?}", scene.world.entity(entity).archetype().components());
|
||||||
}else {
|
// scene.world.components().
|
||||||
entity_components.insert(target_entity, reflect_components);
|
|
||||||
}
|
|
||||||
// shorthand, did not manage to get it working
|
|
||||||
/* entity_components.insert(
|
|
||||||
target_entity,
|
|
||||||
if entity_components.contains_key(&target_entity) {
|
|
||||||
entity_components[&target_entity].push(reflect_components) } else { reflect_components }
|
|
||||||
);*/
|
|
||||||
|
|
||||||
debug!("-----value {:?}", &extras.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GltfNode
|
|
||||||
// find a way to link this name to the current entity ? => WOULD BE VERY USEFULL for animations & co !!
|
|
||||||
debug!("done pre-processing components, now adding them to entities");
|
|
||||||
for (entity, components) in entity_components {
|
|
||||||
if !components.is_empty() {
|
|
||||||
debug!("--entity {:?}, components {}", entity, components.len());
|
|
||||||
}
|
|
||||||
for component in components {
|
|
||||||
let mut entity_mut = scene.world.entity_mut(entity);
|
|
||||||
debug!("------adding {} {:?}", component.type_name(), component);
|
|
||||||
|
|
||||||
type_registry
|
|
||||||
.get_with_name(component.type_name())
|
|
||||||
.unwrap() // Component was successfully deserialized, it has to be in the registry
|
|
||||||
.data::<ReflectComponent>()
|
|
||||||
.unwrap() // Hopefully, the component deserializer ensures those are components
|
|
||||||
.insert(&mut entity_mut, &*component)
|
|
||||||
;
|
|
||||||
|
|
||||||
// info!("all components {:?}", scene.world.entity(entity).archetype().components());
|
|
||||||
// scene.world.components().
|
|
||||||
// TODO: how can we insert any additional components "by hand" here ?
|
// TODO: how can we insert any additional components "by hand" here ?
|
||||||
}
|
}
|
||||||
// let entity_mut = scene.world.entity_mut(entity);
|
// let entity_mut = scene.world.entity_mut(entity);
|
||||||
// let archetype = entity_mut.archetype().clone();
|
// let archetype = entity_mut.archetype().clone();
|
||||||
// let _all_components = archetype.components();
|
// let _all_components = archetype.components();
|
||||||
|
|
||||||
if added_components > 0 {
|
if added_components > 0 {
|
||||||
debug!("------done adding {} components", added_components);
|
debug!("------done adding {} components", added_components);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
info!("done extracting gltf_extras /n");
|
info!("done extracting gltf_extras /n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ronstring_to_reflect_component(
|
pub fn ronstring_to_reflect_component(
|
||||||
ron_string: &String,
|
ron_string: &String,
|
||||||
type_registry: &TypeRegistryInternal
|
type_registry: &TypeRegistryInternal,
|
||||||
) -> Vec<Box<dyn Reflect>> {
|
) -> Vec<Box<dyn Reflect>> {
|
||||||
let lookup: HashMap<String, Value> = ron::from_str(ron_string.as_str()).unwrap();
|
let lookup: HashMap<String, Value> = ron::from_str(ron_string.as_str()).unwrap();
|
||||||
let mut components: Vec<Box<dyn Reflect>> = Vec::new();
|
let mut components: Vec<Box<dyn Reflect>> = Vec::new();
|
||||||
for (key, value) in lookup.into_iter() {
|
for (key, value) in lookup.into_iter() {
|
||||||
let type_string = key.replace("component: ", "").trim().to_string();
|
let type_string = key.replace("component: ", "").trim().to_string();
|
||||||
let capitalized_type_name = capitalize_first_letter(type_string.as_str());
|
let capitalized_type_name = capitalize_first_letter(type_string.as_str());
|
||||||
|
|
||||||
let mut parsed_value:String;
|
|
||||||
match value.clone() {
|
|
||||||
Value::String(str) => {
|
|
||||||
parsed_value = str;
|
|
||||||
}
|
|
||||||
_=> {
|
|
||||||
parsed_value = ron::to_string(&value).unwrap().to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(type_registration) = type_registry.get_with_short_name(capitalized_type_name.as_str()) {
|
|
||||||
// println!("TYPE INFO {:?}", type_registration.type_info());
|
|
||||||
match type_registration.type_info() {
|
|
||||||
TypeInfo::TupleStruct (info) => {
|
|
||||||
// we handle tupple strucs with only one field differently, as Blender's custom properties with custom ui (float, int, bool, etc) always give us a tupple struct
|
|
||||||
if info.field_len() == 1 {
|
|
||||||
let field = info.field_at(0).expect("we should always have at least one field here");
|
|
||||||
let field_name = field.type_name();
|
|
||||||
// TODO: find a way to cast with typeId instead of this matching
|
|
||||||
/*match field.type_id(){
|
|
||||||
TypeId::of::<f32>() => {
|
|
||||||
println!("WE HAVE A f32");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vec3 => {
|
|
||||||
println!("WE HAVE A VEC3");
|
|
||||||
let bla:Vec3 = ron::from_str(&parsed_value).unwrap();
|
|
||||||
println!("bla {}", bla)
|
|
||||||
}
|
|
||||||
_ =>{}
|
|
||||||
}*/
|
|
||||||
let mut formated = parsed_value.clone();
|
|
||||||
match field_name {
|
|
||||||
"f32" => {
|
|
||||||
formated = parsed_value.parse::<f32>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"f64" => {
|
|
||||||
formated = parsed_value.parse::<f64>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"u8" => {
|
|
||||||
formated = parsed_value.parse::<u8>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"u16" => {
|
|
||||||
formated = parsed_value.parse::<u16>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"u32" => {
|
|
||||||
formated = parsed_value.parse::<u32>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"u64" => {
|
|
||||||
formated = parsed_value.parse::<u64>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"u128" => {
|
|
||||||
formated = parsed_value.parse::<u128>().unwrap().to_string();
|
|
||||||
}
|
|
||||||
"glam::f32::vec2::Vec2" => {
|
|
||||||
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
|
||||||
formated = format!("(x:{},y:{})", parsed[0], parsed[1]);
|
|
||||||
}
|
|
||||||
"glam::f32::vec3::Vec3" => {
|
|
||||||
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
|
||||||
formated = format!("(x:{},y:{},z:{})", parsed[0], parsed[1], parsed[2]);
|
|
||||||
},
|
|
||||||
"bevy_render::color::Color" => {
|
|
||||||
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
|
||||||
if parsed.len() == 3 {
|
|
||||||
formated = format!("Rgba(red:{},green:{},blue:{}, alpha: 1.0)", parsed[0], parsed[1], parsed[2]);
|
|
||||||
}
|
|
||||||
if parsed.len() == 4 {
|
|
||||||
formated = format!("Rgba(red:{},green:{},blue:{}, alpha:{})", parsed[0], parsed[1], parsed[2], parsed[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed_value = format!("({formated})");
|
|
||||||
|
|
||||||
|
let mut parsed_value: String;
|
||||||
|
match value.clone() {
|
||||||
|
Value::String(str) => {
|
||||||
|
parsed_value = str;
|
||||||
}
|
}
|
||||||
}
|
_ => parsed_value = ron::to_string(&value).unwrap().to_string(),
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("parsed value {}",parsed_value);
|
if let Some(type_registration) =
|
||||||
if parsed_value.is_empty() {
|
type_registry.get_with_short_name(capitalized_type_name.as_str())
|
||||||
parsed_value = "()".to_string();
|
{
|
||||||
|
// println!("TYPE INFO {:?}", type_registration.type_info());
|
||||||
|
match type_registration.type_info() {
|
||||||
|
TypeInfo::TupleStruct(info) => {
|
||||||
|
// we handle tupple strucs with only one field differently, as Blender's custom properties with custom ui (float, int, bool, etc) always give us a tupple struct
|
||||||
|
if info.field_len() == 1 {
|
||||||
|
let field = info
|
||||||
|
.field_at(0)
|
||||||
|
.expect("we should always have at least one field here");
|
||||||
|
let field_name = field.type_name();
|
||||||
|
// TODO: find a way to cast with typeId instead of this matching
|
||||||
|
/*match field.type_id(){
|
||||||
|
TypeId::of::<f32>() => {
|
||||||
|
println!("WE HAVE A f32");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Vec3 => {
|
||||||
|
println!("WE HAVE A VEC3");
|
||||||
|
let bla:Vec3 = ron::from_str(&parsed_value).unwrap();
|
||||||
|
println!("bla {}", bla)
|
||||||
|
}
|
||||||
|
_ =>{}
|
||||||
|
}*/
|
||||||
|
let mut formated = parsed_value.clone();
|
||||||
|
match field_name {
|
||||||
|
"f32" => {
|
||||||
|
formated = parsed_value.parse::<f32>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"f64" => {
|
||||||
|
formated = parsed_value.parse::<f64>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"u8" => {
|
||||||
|
formated = parsed_value.parse::<u8>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"u16" => {
|
||||||
|
formated = parsed_value.parse::<u16>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"u32" => {
|
||||||
|
formated = parsed_value.parse::<u32>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"u64" => {
|
||||||
|
formated = parsed_value.parse::<u64>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"u128" => {
|
||||||
|
formated = parsed_value.parse::<u128>().unwrap().to_string();
|
||||||
|
}
|
||||||
|
"glam::f32::vec2::Vec2" => {
|
||||||
|
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
||||||
|
formated = format!("(x:{},y:{})", parsed[0], parsed[1]);
|
||||||
|
}
|
||||||
|
"glam::f32::vec3::Vec3" => {
|
||||||
|
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
||||||
|
formated =
|
||||||
|
format!("(x:{},y:{},z:{})", parsed[0], parsed[1], parsed[2]);
|
||||||
|
}
|
||||||
|
"bevy_render::color::Color" => {
|
||||||
|
let parsed: Vec<f32> = ron::from_str(&parsed_value).unwrap();
|
||||||
|
if parsed.len() == 3 {
|
||||||
|
formated = format!(
|
||||||
|
"Rgba(red:{},green:{},blue:{}, alpha: 1.0)",
|
||||||
|
parsed[0], parsed[1], parsed[2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if parsed.len() == 4 {
|
||||||
|
formated = format!(
|
||||||
|
"Rgba(red:{},green:{},blue:{}, alpha:{})",
|
||||||
|
parsed[0], parsed[1], parsed[2], parsed[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed_value = format!("({formated})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// println!("parsed value {}",parsed_value);
|
||||||
|
if parsed_value.is_empty() {
|
||||||
|
parsed_value = "()".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
let ron_string = format!(
|
||||||
|
"{{ \"{}\":{} }}",
|
||||||
|
type_registration.type_name(),
|
||||||
|
parsed_value
|
||||||
|
);
|
||||||
|
|
||||||
|
// usefull to determine what an entity looks like Serialized
|
||||||
|
/*let test_struct = TuppleTestStr::default();
|
||||||
|
let serializer = ReflectSerializer::new(&test_struct, &type_registry);
|
||||||
|
let serialized =
|
||||||
|
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
||||||
|
println!("serialized Component {}", serialized);*/
|
||||||
|
|
||||||
|
// println!("component data ron string {}", ron_string);
|
||||||
|
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str()).unwrap();
|
||||||
|
let reflect_deserializer = UntypedReflectDeserializer::new(type_registry);
|
||||||
|
let component = reflect_deserializer.deserialize(&mut deserializer).expect(
|
||||||
|
format!(
|
||||||
|
"failed to deserialize component {} with value: {:?}",
|
||||||
|
key, value
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
|
||||||
|
components.push(component);
|
||||||
|
debug!("found type registration for {}", capitalized_type_name);
|
||||||
|
} else {
|
||||||
|
warn!("no type registration for {}", capitalized_type_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ron_string = format!("{{ \"{}\":{} }}",
|
|
||||||
type_registration.type_name(),
|
|
||||||
parsed_value
|
|
||||||
);
|
|
||||||
|
|
||||||
// usefull to determine what an entity looks like Serialized
|
|
||||||
/*let test_struct = TuppleTestStr::default();
|
|
||||||
let serializer = ReflectSerializer::new(&test_struct, &type_registry);
|
|
||||||
let serialized =
|
|
||||||
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
|
||||||
println!("serialized Component {}", serialized);*/
|
|
||||||
|
|
||||||
// println!("component data ron string {}", ron_string);
|
|
||||||
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str()).unwrap();
|
|
||||||
let reflect_deserializer = UntypedReflectDeserializer::new(type_registry);
|
|
||||||
let component = reflect_deserializer.deserialize(&mut deserializer).expect(format!("failed to deserialize component {} with value: {:?}", key, value).as_str());
|
|
||||||
|
|
||||||
components.push(component);
|
|
||||||
debug!("found type registration for {}", capitalized_type_name);
|
|
||||||
} else {
|
|
||||||
warn!("no type registration for {}", capitalized_type_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
components
|
components
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,7 @@ pub use gltf_to_components::*;
|
|||||||
pub mod process_gltfs;
|
pub mod process_gltfs;
|
||||||
pub use process_gltfs::*;
|
pub use process_gltfs::*;
|
||||||
|
|
||||||
use bevy::prelude::{
|
use bevy::prelude::{App, IntoSystemConfigs, Plugin, SystemSet, Update};
|
||||||
App,Plugin, Update, SystemSet, IntoSystemConfigs
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// A Bevy plugin for extracting components from gltf files and automatically adding them to the relevant entities
|
/// A Bevy plugin for extracting components from gltf files and automatically adding them to the relevant entities
|
||||||
/// It will automatically run every time you load a gltf file
|
/// It will automatically run every time you load a gltf file
|
||||||
@ -45,30 +42,21 @@ use bevy::prelude::{
|
|||||||
///}
|
///}
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
|
|
||||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
/// systemset to order your systems after the component injection when needed
|
/// systemset to order your systems after the component injection when needed
|
||||||
pub enum GltfComponentsSet{
|
pub enum GltfComponentsSet {
|
||||||
Injection,
|
Injection,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ComponentsFromGltfPlugin;
|
pub struct ComponentsFromGltfPlugin;
|
||||||
impl Plugin for ComponentsFromGltfPlugin {
|
impl Plugin for ComponentsFromGltfPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.insert_resource(GltfLoadingTracker::new())
|
||||||
.insert_resource(GltfLoadingTracker::new())
|
.add_systems(Update, (track_new_gltf, process_loaded_scenes))
|
||||||
|
.add_systems(
|
||||||
.add_systems(Update, (
|
Update,
|
||||||
track_new_gltf,
|
(process_loaded_scenes).in_set(GltfComponentsSet::Injection),
|
||||||
process_loaded_scenes,
|
);
|
||||||
))
|
}
|
||||||
|
|
||||||
.add_systems(Update,
|
|
||||||
(process_loaded_scenes)
|
|
||||||
.in_set(GltfComponentsSet::Injection)
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,32 @@
|
|||||||
use bevy::utils::HashSet;
|
|
||||||
use bevy::{prelude::*, asset::LoadState};
|
|
||||||
use bevy::gltf::Gltf;
|
use bevy::gltf::Gltf;
|
||||||
|
use bevy::utils::HashSet;
|
||||||
|
use bevy::{asset::LoadState, prelude::*};
|
||||||
|
|
||||||
use super::gltf_extras_to_components;
|
use super::gltf_extras_to_components;
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
/// component to keep track of gltfs' loading state
|
/// component to keep track of gltfs' loading state
|
||||||
pub struct GltfLoadingTracker{
|
pub struct GltfLoadingTracker {
|
||||||
pub loading_gltfs: HashSet<Handle<Gltf>>,
|
pub loading_gltfs: HashSet<Handle<Gltf>>,
|
||||||
pub loaded_gltfs: HashSet<Handle<Gltf>>
|
pub loaded_gltfs: HashSet<Handle<Gltf>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GltfLoadingTracker {
|
impl GltfLoadingTracker {
|
||||||
pub fn new() -> GltfLoadingTracker {
|
pub fn new() -> GltfLoadingTracker {
|
||||||
GltfLoadingTracker {
|
GltfLoadingTracker {
|
||||||
loaded_gltfs : HashSet::new(),
|
loaded_gltfs: HashSet::new(),
|
||||||
loading_gltfs: HashSet::new()
|
loading_gltfs: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add_scene(&mut self, handle: Handle<Gltf>) {
|
pub fn add_scene(&mut self, handle: Handle<Gltf>) {
|
||||||
self.loading_gltfs.insert(handle);
|
self.loading_gltfs.insert(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn track_new_gltf(
|
||||||
pub fn track_new_gltf(
|
|
||||||
mut tracker: ResMut<GltfLoadingTracker>,
|
mut tracker: ResMut<GltfLoadingTracker>,
|
||||||
mut events: EventReader<AssetEvent<Gltf>>,
|
mut events: EventReader<AssetEvent<Gltf>>,
|
||||||
) {
|
) {
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
if let AssetEvent::Created { handle } = event {
|
if let AssetEvent::Created { handle } = event {
|
||||||
tracker.add_scene(handle.clone());
|
tracker.add_scene(handle.clone());
|
||||||
@ -37,21 +36,22 @@ pub struct GltfLoadingTracker{
|
|||||||
events.clear();
|
events.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_loaded_scenes(
|
pub fn process_loaded_scenes(
|
||||||
mut gltfs: ResMut<Assets<Gltf>>,
|
mut gltfs: ResMut<Assets<Gltf>>,
|
||||||
mut scenes: ResMut<Assets<Scene>>,
|
mut scenes: ResMut<Assets<Scene>>,
|
||||||
mut tracker: ResMut<GltfLoadingTracker>,
|
mut tracker: ResMut<GltfLoadingTracker>,
|
||||||
app_type_registry: Res<AppTypeRegistry>,
|
app_type_registry: Res<AppTypeRegistry>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
) {
|
||||||
) {
|
|
||||||
|
|
||||||
let mut loaded_gltfs = Vec::new();
|
let mut loaded_gltfs = Vec::new();
|
||||||
for gltf in &tracker.loading_gltfs {
|
for gltf in &tracker.loading_gltfs {
|
||||||
info!("checking for loaded gltfs {:?}", asset_server.get_load_state(gltf));
|
info!(
|
||||||
|
"checking for loaded gltfs {:?}",
|
||||||
|
asset_server.get_load_state(gltf)
|
||||||
|
);
|
||||||
|
|
||||||
if asset_server.get_load_state(gltf.clone()) == LoadState::Loaded {
|
if asset_server.get_load_state(gltf.clone()) == LoadState::Loaded {
|
||||||
debug!("Adding scene to processing list");
|
debug!("Adding scene to processing list");
|
||||||
loaded_gltfs.push(gltf.clone());
|
loaded_gltfs.push(gltf.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,21 +60,17 @@ pub struct GltfLoadingTracker{
|
|||||||
|
|
||||||
for gltf_handle in &loaded_gltfs {
|
for gltf_handle in &loaded_gltfs {
|
||||||
if let Some(gltf) = gltfs.get_mut(gltf_handle) {
|
if let Some(gltf) = gltfs.get_mut(gltf_handle) {
|
||||||
|
// TODO this is a temporary workaround for library management
|
||||||
// TODO this is a temporary workaround for library management
|
if let Some(asset_path) = asset_server.get_handle_path(gltf_handle) {
|
||||||
if let Some(asset_path) = asset_server.get_handle_path(gltf_handle) {
|
let gltf_name = asset_path.path().file_stem().unwrap().to_str().unwrap();
|
||||||
let gltf_name = asset_path.path().file_stem().unwrap().to_str().unwrap();
|
gltf_extras_to_components(gltf, &mut scenes, &*type_registry, gltf_name);
|
||||||
gltf_extras_to_components(gltf, &mut scenes, &*type_registry, gltf_name);
|
//gltf_extras_to_prefab_infos(gltf, &mut scenes, &*type_registry, gltf_name);
|
||||||
//gltf_extras_to_prefab_infos(gltf, &mut scenes, &*type_registry, gltf_name);
|
} else {
|
||||||
}
|
gltf_extras_to_components(gltf, &mut scenes, &*type_registry, "");
|
||||||
else {
|
}
|
||||||
gltf_extras_to_components(gltf, &mut scenes, &*type_registry, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tracker.loading_gltfs.remove(gltf_handle);
|
tracker.loading_gltfs.remove(gltf_handle);
|
||||||
tracker.loaded_gltfs.insert(gltf_handle.clone());
|
tracker.loaded_gltfs.insert(gltf_handle.clone());
|
||||||
debug!("Done loading scene");
|
debug!("Done loading scene");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
pub fn capitalize_first_letter(s: &str) -> String {
|
pub fn capitalize_first_letter(s: &str) -> String {
|
||||||
s[0..1].to_uppercase() + &s[1..]
|
s[0..1].to_uppercase() + &s[1..]
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,4 @@ use bevy::prelude::*;
|
|||||||
use bevy_asset_loader::prelude::*;
|
use bevy_asset_loader::prelude::*;
|
||||||
|
|
||||||
#[derive(AssetCollection, Resource)]
|
#[derive(AssetCollection, Resource)]
|
||||||
pub struct CoreAssets {
|
pub struct CoreAssets {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -7,28 +7,29 @@ pub use assets_game::*;
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_asset_loader::prelude::*;
|
use bevy_asset_loader::prelude::*;
|
||||||
|
|
||||||
use crate::state::{AppState};
|
use crate::state::AppState;
|
||||||
|
|
||||||
pub struct AssetsPlugin;
|
pub struct AssetsPlugin;
|
||||||
impl Plugin for AssetsPlugin {
|
impl Plugin for AssetsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app
|
||||||
// load core assets (ie assets needed in the main menu, and everywhere else before loading more assets in game)
|
// load core assets (ie assets needed in the main menu, and everywhere else before loading more assets in game)
|
||||||
.add_loading_state(LoadingState::new(AppState::CoreLoading).continue_to_state(AppState::MenuRunning))
|
.add_loading_state(
|
||||||
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
|
LoadingState::new(AppState::CoreLoading).continue_to_state(AppState::MenuRunning),
|
||||||
AppState::CoreLoading,
|
)
|
||||||
"advanced/assets_core.assets.ron",
|
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
|
||||||
)
|
AppState::CoreLoading,
|
||||||
.add_collection_to_loading_state::<_, CoreAssets>(AppState::CoreLoading)
|
"advanced/assets_core.assets.ron",
|
||||||
|
)
|
||||||
// load game assets
|
.add_collection_to_loading_state::<_, CoreAssets>(AppState::CoreLoading)
|
||||||
.add_loading_state(LoadingState::new(AppState::AppLoading).continue_to_state(AppState::AppRunning))
|
// load game assets
|
||||||
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
|
.add_loading_state(
|
||||||
AppState::AppLoading,
|
LoadingState::new(AppState::AppLoading).continue_to_state(AppState::AppRunning),
|
||||||
"advanced/assets_game.assets.ron",
|
)
|
||||||
)
|
.add_dynamic_collection_to_loading_state::<_, StandardDynamicAssetCollection>(
|
||||||
.add_collection_to_loading_state::<_, GameAssets>(AppState::AppLoading)
|
AppState::AppLoading,
|
||||||
|
"advanced/assets_game.assets.ron",
|
||||||
;
|
)
|
||||||
|
.add_collection_to_loading_state::<_, GameAssets>(AppState::AppLoading);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,34 +1,24 @@
|
|||||||
|
use bevy::core_pipeline::bloom::{BloomCompositeMode, BloomSettings};
|
||||||
|
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::core_pipeline::bloom::{BloomSettings, BloomCompositeMode};
|
|
||||||
use bevy::core_pipeline::tonemapping::{Tonemapping, DebandDither};
|
|
||||||
|
|
||||||
use super::CameraTrackingOffset;
|
use super::CameraTrackingOffset;
|
||||||
|
|
||||||
pub fn camera_replace_proxies (
|
pub fn camera_replace_proxies(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut added_cameras: Query<(Entity, &mut Camera), (Added<Camera>, With<CameraTrackingOffset>)>,
|
mut added_cameras: Query<(Entity, &mut Camera), (Added<Camera>, With<CameraTrackingOffset>)>,
|
||||||
) {
|
) {
|
||||||
|
for (entity, mut camera) in added_cameras.iter_mut() {
|
||||||
for (entity, mut camera) in added_cameras.iter_mut(){
|
|
||||||
info!("detected added camera, updating proxy");
|
info!("detected added camera, updating proxy");
|
||||||
camera.hdr = true;
|
camera.hdr = true;
|
||||||
commands.entity(entity)
|
commands
|
||||||
.insert(
|
.entity(entity)
|
||||||
DebandDither::Enabled
|
.insert(DebandDither::Enabled)
|
||||||
)
|
.insert(Tonemapping::BlenderFilmic)
|
||||||
.insert(
|
.insert(BloomSettings {
|
||||||
Tonemapping::BlenderFilmic
|
intensity: 0.01,
|
||||||
)
|
composite_mode: BloomCompositeMode::Additive,
|
||||||
.insert(
|
..default()
|
||||||
BloomSettings{
|
});
|
||||||
intensity: 0.01,
|
}
|
||||||
composite_mode:BloomCompositeMode::Additive,
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Component for cameras, with an offset from the Trackable target
|
/// Component for cameras, with an offset from the Trackable target
|
||||||
///
|
///
|
||||||
pub struct CameraTracking{
|
pub struct CameraTracking {
|
||||||
pub offset: Vec3
|
pub offset: Vec3,
|
||||||
}
|
}
|
||||||
impl Default for CameraTracking {
|
impl Default for CameraTracking {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CameraTracking { offset: Vec3::new(0.0, 6.0, 8.0) }
|
CameraTracking {
|
||||||
|
offset: Vec3::new(0.0, 6.0, 8.0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug, Deref, DerefMut)]
|
#[derive(Component, Reflect, Debug, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Component for cameras, with an offset from the Trackable target
|
/// Component for cameras, with an offset from the Trackable target
|
||||||
@ -26,32 +26,33 @@ impl Default for CameraTrackingOffset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CameraTrackingOffset {
|
impl CameraTrackingOffset {
|
||||||
fn new (input: Vec3) -> Self {
|
fn new(input: Vec3) -> Self {
|
||||||
CameraTrackingOffset(input)
|
CameraTrackingOffset(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Add this component to an entity if you want it to be tracked by a Camera
|
/// Add this component to an entity if you want it to be tracked by a Camera
|
||||||
pub struct CameraTrackable;
|
pub struct CameraTrackable;
|
||||||
|
|
||||||
pub fn camera_track(
|
pub fn camera_track(
|
||||||
mut tracking_cameras: Query<(&mut Transform, &CameraTrackingOffset), (With<Camera>, With<CameraTrackingOffset>, Without<CameraTrackable>)>,
|
mut tracking_cameras: Query<
|
||||||
|
(&mut Transform, &CameraTrackingOffset),
|
||||||
|
(
|
||||||
|
With<Camera>,
|
||||||
|
With<CameraTrackingOffset>,
|
||||||
|
Without<CameraTrackable>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
camera_tracked: Query<&Transform, With<CameraTrackable>>,
|
camera_tracked: Query<&Transform, With<CameraTrackable>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
for (mut camera_transform, tracking_offset) in tracking_cameras.iter_mut() {
|
for (mut camera_transform, tracking_offset) in tracking_cameras.iter_mut() {
|
||||||
for tracked_transform in camera_tracked.iter(){
|
for tracked_transform in camera_tracked.iter() {
|
||||||
|
|
||||||
let target_position = tracked_transform.translation + tracking_offset.0;
|
let target_position = tracked_transform.translation + tracking_offset.0;
|
||||||
let eased_position = camera_transform.translation.lerp(target_position, 0.1);
|
let eased_position = camera_transform.translation.lerp(target_position, 0.1);
|
||||||
camera_transform.translation = eased_position;// + tracking.offset;// tracked_transform.translation + tracking.offset;
|
camera_transform.translation = eased_position; // + tracking.offset;// tracked_transform.translation + tracking.offset;
|
||||||
*camera_transform = camera_transform.looking_at(tracked_transform.translation, Vec3::Y);
|
*camera_transform = camera_transform.looking_at(tracked_transform.translation, Vec3::Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,18 +9,16 @@ use bevy_gltf_blueprints::GltfBlueprintsSet;
|
|||||||
|
|
||||||
pub struct CameraPlugin;
|
pub struct CameraPlugin;
|
||||||
impl Plugin for CameraPlugin {
|
impl Plugin for CameraPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<CameraTrackable>()
|
||||||
.register_type::<CameraTrackable>()
|
.register_type::<CameraTracking>()
|
||||||
.register_type::<CameraTracking>()
|
.register_type::<CameraTrackingOffset>()
|
||||||
.register_type::<CameraTrackingOffset>()
|
.add_systems(
|
||||||
|
Update,
|
||||||
.add_systems(Update,
|
(
|
||||||
(
|
camera_replace_proxies.after(GltfBlueprintsSet::AfterSpawn),
|
||||||
camera_replace_proxies.after(GltfBlueprintsSet::AfterSpawn),
|
camera_track,
|
||||||
camera_track,
|
),
|
||||||
)
|
);
|
||||||
)
|
}
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,29 +1,25 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use bevy::pbr::{CascadeShadowConfigBuilder, CascadeShadowConfig};
|
use bevy::pbr::{CascadeShadowConfig, CascadeShadowConfigBuilder};
|
||||||
|
|
||||||
// fixme might be too specific to might needs, should it be moved out ? also these are all for lights, not models
|
// fixme might be too specific to might needs, should it be moved out ? also these are all for lights, not models
|
||||||
pub fn lighting_replace_proxies(
|
pub fn lighting_replace_proxies(
|
||||||
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
||||||
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
){
|
for (entity, mut light) in added_dirights.iter_mut() {
|
||||||
|
light.illuminance *= 5.0;
|
||||||
for (entity, mut light) in added_dirights.iter_mut(){
|
light.shadows_enabled = true;
|
||||||
light.illuminance *= 5.0;
|
let shadow_config: CascadeShadowConfig = CascadeShadowConfigBuilder {
|
||||||
light.shadows_enabled = true;
|
first_cascade_far_bound: 15.0,
|
||||||
let shadow_config:CascadeShadowConfig = CascadeShadowConfigBuilder {
|
maximum_distance: 135.0,
|
||||||
first_cascade_far_bound: 15.0,
|
..default()
|
||||||
maximum_distance: 135.0,
|
}
|
||||||
..default()
|
.into();
|
||||||
}
|
commands.entity(entity).insert(shadow_config);
|
||||||
.into();
|
}
|
||||||
commands.entity(entity)
|
for mut light in added_spotlights.iter_mut() {
|
||||||
.insert(shadow_config);
|
light.shadows_enabled = true;
|
||||||
}
|
}
|
||||||
for mut light in added_spotlights.iter_mut(){
|
|
||||||
light.shadows_enabled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
mod lighting_replace_proxies;
|
mod lighting_replace_proxies;
|
||||||
use lighting_replace_proxies::*;
|
use lighting_replace_proxies::*;
|
||||||
|
|
||||||
|
use bevy::pbr::{DirectionalLightShadowMap, NotShadowCaster};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::pbr::{NotShadowCaster, DirectionalLightShadowMap};
|
|
||||||
|
|
||||||
pub struct LightingPlugin;
|
pub struct LightingPlugin;
|
||||||
impl Plugin for LightingPlugin {
|
impl Plugin for LightingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app
|
||||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||||
// FIXME: adding these since they are missing
|
// FIXME: adding these since they are missing
|
||||||
.register_type::<NotShadowCaster>()
|
.register_type::<NotShadowCaster>()
|
||||||
|
|
||||||
.add_systems(PreUpdate, lighting_replace_proxies) // FIXME: you should actually run this in a specific state most likely
|
.add_systems(PreUpdate, lighting_replace_proxies) // FIXME: you should actually run this in a specific state most likely
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,73 +22,63 @@ use bevy_gltf_blueprints::*;
|
|||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
|
|
||||||
fn spawn_test(
|
fn spawn_test(
|
||||||
keycode: Res<Input<KeyCode>>,
|
keycode: Res<Input<KeyCode>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
|
||||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
|
||||||
|
|
||||||
|
|
||||||
|
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||||
) {
|
) {
|
||||||
if keycode.just_pressed(KeyCode::T) {
|
if keycode.just_pressed(KeyCode::T) {
|
||||||
let world = game_world.single_mut();
|
let world = game_world.single_mut();
|
||||||
let world = world.1[0];
|
let world = world.1[0];
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let range = 5.5;
|
let range = 5.5;
|
||||||
let x: f32 = rng.gen_range(-range..range);
|
let x: f32 = rng.gen_range(-range..range);
|
||||||
let y: 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 mut rng = rand::thread_rng();
|
let name_index: u64 = rng.gen();
|
||||||
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 new_entity = commands
|
||||||
let name_index:u64 = rng.gen();
|
.spawn((
|
||||||
|
BluePrintBundle {
|
||||||
let new_entity = commands.spawn((
|
blueprint: BlueprintName("Health_Pickup".to_string()),
|
||||||
BluePrintBundle{
|
transform: TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
blueprint: BlueprintName("Health_Pickup".to_string()),
|
..Default::default()
|
||||||
transform: TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
},
|
||||||
..Default::default()
|
bevy::prelude::Name::from(format!("test{}", name_index)),
|
||||||
},
|
// BlueprintName("Health_Pickup".to_string()),
|
||||||
bevy::prelude::Name::from(format!("test{}", name_index)),
|
// SpawnHere,
|
||||||
// BlueprintName("Health_Pickup".to_string()),
|
// TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
// SpawnHere,
|
Velocity {
|
||||||
// TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
linvel: Vec3::new(vel_x, vel_y, vel_z),
|
||||||
|
angvel: Vec3::new(0.0, 0.0, 0.0),
|
||||||
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);
|
||||||
)).id();
|
}
|
||||||
commands.entity(world).add_child(new_entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CorePlugin;
|
pub struct CorePlugin;
|
||||||
impl Plugin for CorePlugin {
|
impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.add_plugins((
|
||||||
.add_plugins((
|
|
||||||
LightingPlugin,
|
LightingPlugin,
|
||||||
CameraPlugin,
|
CameraPlugin,
|
||||||
PhysicsPlugin,
|
PhysicsPlugin,
|
||||||
SaveLoadPlugin,
|
SaveLoadPlugin,
|
||||||
BlueprintsPlugin{
|
BlueprintsPlugin {
|
||||||
library_folder: "advanced/models/library".into()
|
library_folder: "advanced/models/library".into(),
|
||||||
}
|
},
|
||||||
))
|
))
|
||||||
|
// just for testing
|
||||||
// just for testing
|
.add_systems(Update, spawn_test);
|
||||||
.add_systems(
|
}
|
||||||
Update,
|
|
||||||
spawn_test
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use bevy::prelude::{ResMut, info};
|
use bevy::prelude::{info, ResMut};
|
||||||
use bevy_rapier3d::prelude::RapierConfiguration;
|
use bevy_rapier3d::prelude::RapierConfiguration;
|
||||||
|
|
||||||
pub fn pause_physics(mut physics_config: ResMut<RapierConfiguration>){
|
pub fn pause_physics(mut physics_config: ResMut<RapierConfiguration>) {
|
||||||
info!("pausing physics");
|
info!("pausing physics");
|
||||||
physics_config.physics_pipeline_active = false;
|
physics_config.physics_pipeline_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resume_physics(mut physics_config: ResMut<RapierConfiguration>){
|
pub fn resume_physics(mut physics_config: ResMut<RapierConfiguration>) {
|
||||||
info!("unpausing physics");
|
info!("unpausing physics");
|
||||||
physics_config.physics_pipeline_active = true;
|
physics_config.physics_pipeline_active = true;
|
||||||
}
|
}
|
@ -6,33 +6,24 @@ pub mod utils;
|
|||||||
pub mod controls;
|
pub mod controls;
|
||||||
pub use controls::*;
|
pub use controls::*;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use crate::state::GameState;
|
use crate::state::GameState;
|
||||||
|
use bevy::prelude::*;
|
||||||
// use super::blueprints::GltfBlueprintsSet;
|
// use super::blueprints::GltfBlueprintsSet;
|
||||||
use bevy_gltf_blueprints::GltfBlueprintsSet;
|
use bevy_gltf_blueprints::GltfBlueprintsSet;
|
||||||
// use crate::Collider;
|
// use crate::Collider;
|
||||||
pub struct PhysicsPlugin;
|
pub struct PhysicsPlugin;
|
||||||
impl Plugin for PhysicsPlugin {
|
impl Plugin for PhysicsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<AutoAABBCollider>()
|
||||||
.register_type::<AutoAABBCollider>()
|
.register_type::<physics_replace_proxies::Collider>()
|
||||||
.register_type::<physics_replace_proxies::Collider>()
|
// find a way to make serde's stuff serializable
|
||||||
|
// .register_type::<bevy_rapier3d::dynamics::CoefficientCombineRule>()
|
||||||
// find a way to make serde's stuff serializable
|
//bevy_rapier3d::dynamics::CoefficientCombineRule
|
||||||
// .register_type::<bevy_rapier3d::dynamics::CoefficientCombineRule>()
|
.add_systems(
|
||||||
//bevy_rapier3d::dynamics::CoefficientCombineRule
|
Update,
|
||||||
|
physics_replace_proxies.after(GltfBlueprintsSet::AfterSpawn),
|
||||||
.add_systems(Update, physics_replace_proxies.after(GltfBlueprintsSet::AfterSpawn))
|
)
|
||||||
|
.add_systems(OnEnter(GameState::InGame), resume_physics)
|
||||||
.add_systems(
|
.add_systems(OnExit(GameState::InGame), pause_physics);
|
||||||
OnEnter(GameState::InGame),
|
}
|
||||||
resume_physics
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
OnExit(GameState::InGame),
|
|
||||||
pause_physics
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
// use bevy::render::primitives::Aabb;
|
// use bevy::render::primitives::Aabb;
|
||||||
use bevy_rapier3d::geometry::Collider as RapierCollider;
|
use bevy_rapier3d::geometry::Collider as RapierCollider;
|
||||||
use bevy_rapier3d::prelude::{ComputedColliderShape, ActiveEvents, ActiveCollisionTypes};
|
use bevy_rapier3d::prelude::{ActiveCollisionTypes, ActiveEvents, ComputedColliderShape};
|
||||||
|
|
||||||
use super::utils::*;
|
use super::utils::*;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum Collider {
|
pub enum Collider {
|
||||||
Ball(f32),
|
Ball(f32),
|
||||||
@ -15,21 +15,23 @@ pub enum Collider {
|
|||||||
Mesh,
|
Mesh,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum AutoAABBCollider {
|
pub enum AutoAABBCollider {
|
||||||
#[default]
|
#[default]
|
||||||
Cuboid,
|
Cuboid,
|
||||||
Ball,
|
Ball,
|
||||||
Capsule
|
Capsule,
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces all physics stand-ins with the actual rapier types
|
// replaces all physics stand-ins with the actual rapier types
|
||||||
pub fn physics_replace_proxies (
|
pub fn physics_replace_proxies(
|
||||||
meshes: Res<Assets<Mesh>>,
|
meshes: Res<Assets<Mesh>>,
|
||||||
mesh_handles: Query<&Handle<Mesh>>,
|
mesh_handles: Query<&Handle<Mesh>>,
|
||||||
mut proxy_colliders: Query<(Entity, &Collider, &Name, &mut Visibility), (Without<RapierCollider>, Added<Collider>)>,
|
mut proxy_colliders: Query<
|
||||||
|
(Entity, &Collider, &Name, &mut Visibility),
|
||||||
|
(Without<RapierCollider>, Added<Collider>),
|
||||||
|
>,
|
||||||
// needed for tri meshes
|
// needed for tri meshes
|
||||||
children: Query<&Children>,
|
children: Query<&Children>,
|
||||||
|
|
||||||
@ -38,12 +40,12 @@ pub fn physics_replace_proxies (
|
|||||||
for proxy_colider in proxy_colliders.iter_mut() {
|
for proxy_colider in proxy_colliders.iter_mut() {
|
||||||
let (entity, collider_proxy, name, mut visibility) = proxy_colider;
|
let (entity, collider_proxy, name, mut visibility) = proxy_colider;
|
||||||
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
||||||
if name.ends_with( "_collider" ) || name.ends_with( "_sensor" ) {
|
if name.ends_with("_collider") || name.ends_with("_sensor") {
|
||||||
*visibility = Visibility::Hidden;
|
*visibility = Visibility::Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rapier_collider:RapierCollider;
|
let mut rapier_collider: RapierCollider;
|
||||||
match collider_proxy{
|
match collider_proxy {
|
||||||
Collider::Ball(radius) => {
|
Collider::Ball(radius) => {
|
||||||
info!("generating collider from proxy: ball");
|
info!("generating collider from proxy: ball");
|
||||||
rapier_collider = RapierCollider::ball(*radius);
|
rapier_collider = RapierCollider::ball(*radius);
|
||||||
@ -70,15 +72,25 @@ pub fn physics_replace_proxies (
|
|||||||
}
|
}
|
||||||
Collider::Mesh => {
|
Collider::Mesh => {
|
||||||
info!("generating collider from proxy: mesh");
|
info!("generating collider from proxy: mesh");
|
||||||
for (_, collider_mesh) in Mesh::search_in_children(entity, &children, &meshes, &mesh_handles)
|
for (_, collider_mesh) in
|
||||||
|
Mesh::search_in_children(entity, &children, &meshes, &mesh_handles)
|
||||||
{
|
{
|
||||||
rapier_collider = RapierCollider::from_bevy_mesh(collider_mesh, &ComputedColliderShape::TriMesh).unwrap();
|
rapier_collider = RapierCollider::from_bevy_mesh(
|
||||||
commands.entity(entity)
|
collider_mesh,
|
||||||
|
&ComputedColliderShape::TriMesh,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
.insert(rapier_collider)
|
.insert(rapier_collider)
|
||||||
// FIXME: this is just for demo purposes !!!
|
// FIXME: this is just for demo purposes !!!
|
||||||
.insert(ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC | ActiveCollisionTypes::STATIC_STATIC | ActiveCollisionTypes::DYNAMIC_STATIC)
|
.insert(
|
||||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
ActiveCollisionTypes::default()
|
||||||
;
|
| ActiveCollisionTypes::KINEMATIC_STATIC
|
||||||
|
| ActiveCollisionTypes::STATIC_STATIC
|
||||||
|
| ActiveCollisionTypes::DYNAMIC_STATIC,
|
||||||
|
)
|
||||||
|
.insert(ActiveEvents::COLLISION_EVENTS);
|
||||||
// .insert(ActiveEvents::COLLISION_EVENTS)
|
// .insert(ActiveEvents::COLLISION_EVENTS)
|
||||||
// break;
|
// break;
|
||||||
// RapierCollider::convex_hull(points)
|
// RapierCollider::convex_hull(points)
|
||||||
|
@ -5,7 +5,7 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
pub struct EcsRelationshipsPlugin;
|
pub struct EcsRelationshipsPlugin;
|
||||||
impl Plugin for EcsRelationshipsPlugin {
|
impl Plugin for EcsRelationshipsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app;
|
app;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,15 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub fn insert_dependant_component<Dependant: Component, Dependency: Component+ std::default::Default>(
|
pub fn insert_dependant_component<
|
||||||
|
Dependant: Component,
|
||||||
|
Dependency: Component + std::default::Default,
|
||||||
|
>(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
entities_without_depency: Query<(Entity, &Name), (With<Dependant>, Without<Dependency>)>,
|
entities_without_depency: Query<(Entity, &Name), (With<Dependant>, Without<Dependency>)>,
|
||||||
) {
|
) {
|
||||||
for (entity, name) in entities_without_depency.iter() {
|
for (entity, name) in entities_without_depency.iter() {
|
||||||
let name = name.clone().to_string();
|
let name = name.clone().to_string();
|
||||||
commands.entity(entity)
|
commands.entity(entity).insert(Dependency::default());
|
||||||
.insert(
|
|
||||||
Dependency::default()
|
|
||||||
)
|
|
||||||
;
|
|
||||||
warn!("found an entity called {} with a {} component but without an {}, please check your assets", name.clone(), std::any::type_name::<Dependant>(), std::any::type_name::<Dependency>());
|
warn!("found an entity called {} with a {} component but without an {}, please check your assets", name.clone(), std::any::type_name::<Dependant>(), std::any::type_name::<Dependency>());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,19 +1,19 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_gltf_blueprints::{clone_entity::CloneEntity, SpawnHere, GameWorldTag};
|
use bevy_gltf_blueprints::{clone_entity::CloneEntity, GameWorldTag, SpawnHere};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assets::GameAssets,
|
assets::GameAssets,
|
||||||
state::{InAppRunning, AppState, GameState}
|
state::{AppState, GameState, InAppRunning},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Saveable;
|
use super::Saveable;
|
||||||
|
|
||||||
const SCENE_FILE_PATH: &str = "scenes/save.scn.ron";
|
const SCENE_FILE_PATH: &str = "scenes/save.scn.ron";
|
||||||
|
|
||||||
#[derive(Component, Debug, )]
|
#[derive(Component, Debug)]
|
||||||
pub struct TempLoadedSceneMarker;
|
pub struct TempLoadedSceneMarker;
|
||||||
|
|
||||||
#[derive(Component, Debug, )]
|
#[derive(Component, Debug)]
|
||||||
pub struct SaveablesToRemove(Vec<(Entity, Name)>);
|
pub struct SaveablesToRemove(Vec<(Entity, Name)>);
|
||||||
|
|
||||||
#[derive(Component, Event)]
|
#[derive(Component, Event)]
|
||||||
@ -21,18 +21,14 @@ pub struct LoadRequest {
|
|||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn should_load(save_requested_events: EventReader<LoadRequest>) -> bool {
|
||||||
pub fn should_load(
|
return save_requested_events.len() > 0;
|
||||||
save_requested_events: EventReader<LoadRequest>,
|
|
||||||
) -> bool {
|
|
||||||
return save_requested_events.len() > 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_prepare(
|
pub fn load_prepare(
|
||||||
mut next_app_state: ResMut<NextState<AppState>>,
|
mut next_app_state: ResMut<NextState<AppState>>,
|
||||||
mut next_game_state: ResMut<NextState<GameState>>,
|
mut next_game_state: ResMut<NextState<GameState>>,
|
||||||
){
|
) {
|
||||||
|
|
||||||
next_app_state.set(AppState::LoadingGame);
|
next_app_state.set(AppState::LoadingGame);
|
||||||
next_game_state.set(GameState::None);
|
next_game_state.set(GameState::None);
|
||||||
info!("--loading: prepare")
|
info!("--loading: prepare")
|
||||||
@ -42,7 +38,7 @@ pub fn load_prepare(
|
|||||||
pub fn _unload_world_old(world: &mut World) {
|
pub fn _unload_world_old(world: &mut World) {
|
||||||
let entities: Vec<Entity> = world
|
let entities: Vec<Entity> = world
|
||||||
// .query_filtered::<Entity, Or<(With<Save>, With<Unload>)>>()
|
// .query_filtered::<Entity, Or<(With<Save>, With<Unload>)>>()
|
||||||
.query_filtered::<Entity, With<GameWorldTag>>()// our level/world contains this component
|
.query_filtered::<Entity, With<GameWorldTag>>() // our level/world contains this component
|
||||||
.iter(world)
|
.iter(world)
|
||||||
.collect();
|
.collect();
|
||||||
for entity in entities {
|
for entity in entities {
|
||||||
@ -53,11 +49,8 @@ pub fn _unload_world_old(world: &mut World) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unload_world(
|
pub fn unload_world(mut commands: Commands, gameworlds: Query<Entity, With<GameWorldTag>>) {
|
||||||
mut commands: Commands,
|
for e in gameworlds.iter() {
|
||||||
gameworlds: Query<Entity, With<GameWorldTag>>
|
|
||||||
){
|
|
||||||
for e in gameworlds.iter(){
|
|
||||||
info!("--loading: despawn old world/level");
|
info!("--loading: despawn old world/level");
|
||||||
commands.entity(e).despawn_recursive();
|
commands.entity(e).despawn_recursive();
|
||||||
}
|
}
|
||||||
@ -66,9 +59,9 @@ pub fn unload_world(
|
|||||||
// almost identical to setup_game, !!??
|
// almost identical to setup_game, !!??
|
||||||
pub fn load_world(
|
pub fn load_world(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
game_assets: Res<GameAssets>,
|
game_assets: Res<GameAssets>,
|
||||||
// scenes: ResMut<Scene>,
|
// scenes: ResMut<Scene>,
|
||||||
){
|
) {
|
||||||
info!("--loading: loading world/level");
|
info!("--loading: loading world/level");
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
@ -78,25 +71,18 @@ pub fn load_world(
|
|||||||
},
|
},
|
||||||
bevy::prelude::Name::from("world"),
|
bevy::prelude::Name::from("world"),
|
||||||
GameWorldTag,
|
GameWorldTag,
|
||||||
InAppRunning
|
InAppRunning,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_saved_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
|
commands.spawn((
|
||||||
|
|
||||||
pub fn load_saved_scene(
|
|
||||||
mut commands: Commands,
|
|
||||||
asset_server: Res<AssetServer>
|
|
||||||
) {
|
|
||||||
commands.spawn(
|
|
||||||
(
|
|
||||||
DynamicSceneBundle {
|
DynamicSceneBundle {
|
||||||
// Scenes are loaded just like any other asset.
|
// Scenes are loaded just like any other asset.
|
||||||
scene: asset_server.load(SCENE_FILE_PATH),
|
scene: asset_server.load(SCENE_FILE_PATH),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TempLoadedSceneMarker
|
TempLoadedSceneMarker,
|
||||||
));
|
));
|
||||||
// commands.entity(world).add_child(child_scene);
|
// commands.entity(world).add_child(child_scene);
|
||||||
info!("--loading: loaded saved scene");
|
info!("--loading: loaded saved scene");
|
||||||
@ -109,21 +95,21 @@ pub fn process_loaded_scene(
|
|||||||
|
|
||||||
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
mut game_world: Query<(Entity, &Children), With<GameWorldTag>>,
|
||||||
saveables: Query<(Entity, &Name), With<Saveable>>,
|
saveables: Query<(Entity, &Name), With<Saveable>>,
|
||||||
asset_server: Res<AssetServer>
|
asset_server: Res<AssetServer>,
|
||||||
){
|
) {
|
||||||
for (loaded_scene, children) in loaded_scene.iter(){
|
for (loaded_scene, children) in loaded_scene.iter() {
|
||||||
info!("--loading: post processing loaded scene");
|
info!("--loading: post processing loaded scene");
|
||||||
|
|
||||||
let mut entities_to_load:Vec<(Entity, Name)> = vec![];
|
let mut entities_to_load: Vec<(Entity, Name)> = vec![];
|
||||||
|
|
||||||
for loaded_entity in children.iter() {
|
for loaded_entity in children.iter() {
|
||||||
if let Ok((source, name, _)) = named_entities.get(*loaded_entity) {
|
if let Ok((source, name, _)) = named_entities.get(*loaded_entity) {
|
||||||
entities_to_load.push((source, name.clone()));
|
entities_to_load.push((source, name.clone()));
|
||||||
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for (e, n, p) in named_entities.iter(){
|
for (e, n, p) in named_entities.iter() {
|
||||||
// if we have an entity with the same name as in same file, overwrite
|
// if we have an entity with the same name as in same file, overwrite
|
||||||
if e != source && name.as_str() == n.as_str(){
|
if e != source && name.as_str() == n.as_str() {
|
||||||
// println!("found entity with same name {} {} {:?} {:?}", name, n, source, e);
|
// println!("found entity with same name {} {} {:?} {:?}", name, n, source, e);
|
||||||
// source is entity within the newly loaded scene (source), e is within the existing world (destination)
|
// source is entity within the newly loaded scene (source), e is within the existing world (destination)
|
||||||
info!("copying data from {:?} to {:?}", source, e);
|
info!("copying data from {:?} to {:?}", source, e);
|
||||||
@ -145,10 +131,9 @@ pub fn process_loaded_scene(
|
|||||||
let world = game_world.single_mut();
|
let world = game_world.single_mut();
|
||||||
let world = world.1[0];
|
let world = world.1[0];
|
||||||
|
|
||||||
let new_entity = commands.spawn((
|
let new_entity = commands
|
||||||
bevy::prelude::Name::from(name.clone()),
|
.spawn((bevy::prelude::Name::from(name.clone()), SpawnHere))
|
||||||
SpawnHere,
|
.id();
|
||||||
)).id();
|
|
||||||
|
|
||||||
commands.add(CloneEntity {
|
commands.add(CloneEntity {
|
||||||
source: source,
|
source: source,
|
||||||
@ -157,17 +142,11 @@ pub fn process_loaded_scene(
|
|||||||
|
|
||||||
commands.entity(world).add_child(new_entity);
|
commands.entity(world).add_child(new_entity);
|
||||||
info!("copying data from {:?} to {:?}", source, new_entity);
|
info!("copying data from {:?} to {:?}", source, new_entity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
commands.spawn(SaveablesToRemove(entities_to_load.clone()));
|
commands.spawn(SaveablesToRemove(entities_to_load.clone()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if an entity is present in the world but NOT in the saved entities , it should be removed from the world
|
// if an entity is present in the world but NOT in the saved entities , it should be removed from the world
|
||||||
// ideally this should be run between spawning of the world/level AND spawn_placeholders
|
// ideally this should be run between spawning of the world/level AND spawn_placeholders
|
||||||
|
|
||||||
@ -177,7 +156,6 @@ pub fn process_loaded_scene(
|
|||||||
|
|
||||||
asset_server.mark_unused_assets();
|
asset_server.mark_unused_assets();
|
||||||
asset_server.free_unused_assets();
|
asset_server.free_unused_assets();
|
||||||
|
|
||||||
}
|
}
|
||||||
//for saveable in saveables.iter(){
|
//for saveable in saveables.iter(){
|
||||||
// println!("SAVEABLE BEFORE {:?}", saveable)
|
// println!("SAVEABLE BEFORE {:?}", saveable)
|
||||||
@ -190,17 +168,15 @@ pub fn final_cleanup(
|
|||||||
saveables: Query<(Entity, &Name), With<Saveable>>,
|
saveables: Query<(Entity, &Name), With<Saveable>>,
|
||||||
mut next_app_state: ResMut<NextState<AppState>>,
|
mut next_app_state: ResMut<NextState<AppState>>,
|
||||||
mut next_game_state: ResMut<NextState<GameState>>,
|
mut next_game_state: ResMut<NextState<GameState>>,
|
||||||
|
) {
|
||||||
){
|
if let Ok((e, entities_to_load)) = saveables_to_remove.get_single() {
|
||||||
if let Ok((e, entities_to_load)) = saveables_to_remove.get_single()
|
|
||||||
{
|
|
||||||
info!("saveables to remove {:?}", entities_to_load);
|
info!("saveables to remove {:?}", entities_to_load);
|
||||||
for (e, n) in saveables.iter(){
|
for (e, n) in saveables.iter() {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
println!("SAVEABLE {}", n);
|
println!("SAVEABLE {}", n);
|
||||||
|
|
||||||
//let entities_to_load = saveables_to_remove.single();
|
//let entities_to_load = saveables_to_remove.single();
|
||||||
for (en, na) in entities_to_load.0.iter(){
|
for (en, na) in entities_to_load.0.iter() {
|
||||||
found = na.as_str() == n.as_str();
|
found = na.as_str() == n.as_str();
|
||||||
if found {
|
if found {
|
||||||
break;
|
break;
|
||||||
@ -226,18 +202,17 @@ fn process_loaded_scene_load_alt(
|
|||||||
entities: Query<(Entity, &Children), With<TempLoadedSceneMarker>>,
|
entities: Query<(Entity, &Children), With<TempLoadedSceneMarker>>,
|
||||||
named_entities: Query<(Entity, &Name, &Parent)>, // FIXME: very inneficient
|
named_entities: Query<(Entity, &Name, &Parent)>, // FIXME: very inneficient
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
){
|
for (entity, children) in entities.iter() {
|
||||||
for (entity, children) in entities.iter(){
|
let mut entities_to_load: Vec<(Entity, Name)> = vec![];
|
||||||
let mut entities_to_load:Vec<(Entity, Name)> = vec![];
|
|
||||||
for saved_source in children.iter() {
|
for saved_source in children.iter() {
|
||||||
if let Ok((source, name, _)) = named_entities.get(*saved_source) {
|
if let Ok((source, name, _)) = named_entities.get(*saved_source) {
|
||||||
println!("AAAAAAA {}", name);
|
println!("AAAAAAA {}", name);
|
||||||
entities_to_load.push((source, name.clone()));
|
entities_to_load.push((source, name.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("entities to load {:?}", entities_to_load);
|
println!("entities to load {:?}", entities_to_load);
|
||||||
|
|
||||||
commands.entity(entity).despawn_recursive();
|
commands.entity(entity).despawn_recursive();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,23 +10,21 @@ pub mod loading;
|
|||||||
pub use loading::*;
|
pub use loading::*;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::prelude::{App, Plugin, IntoSystemConfigs};
|
use bevy::prelude::{App, IntoSystemConfigs, Plugin};
|
||||||
use bevy::utils::Uuid;
|
use bevy::utils::Uuid;
|
||||||
|
|
||||||
use bevy_gltf_blueprints::GltfBlueprintsSet;
|
use bevy_gltf_blueprints::GltfBlueprintsSet;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
|
||||||
pub enum LoadingSet{
|
pub enum LoadingSet {
|
||||||
Load,
|
Load,
|
||||||
PostLoad,
|
PostLoad,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SaveLoadPlugin;
|
pub struct SaveLoadPlugin;
|
||||||
impl Plugin for SaveLoadPlugin {
|
impl Plugin for SaveLoadPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app
|
||||||
.register_type::<Uuid>()
|
.register_type::<Uuid>()
|
||||||
.register_type::<Saveable>()
|
.register_type::<Saveable>()
|
||||||
.add_event::<SaveRequest>()
|
.add_event::<SaveRequest>()
|
||||||
@ -54,7 +52,7 @@ impl Plugin for SaveLoadPlugin {
|
|||||||
.run_if(should_load) // .run_if(in_state(AppState::AppRunning))
|
.run_if(should_load) // .run_if(in_state(AppState::AppRunning))
|
||||||
.in_set(LoadingSet::Load)
|
.in_set(LoadingSet::Load)
|
||||||
)
|
)
|
||||||
.add_systems(Update,
|
.add_systems(Update,
|
||||||
(
|
(
|
||||||
process_loaded_scene,
|
process_loaded_scene,
|
||||||
apply_deferred,
|
apply_deferred,
|
||||||
@ -67,7 +65,6 @@ impl Plugin for SaveLoadPlugin {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// .add_systems(Update, bla)
|
// .add_systems(Update, bla)
|
||||||
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::utils::{Uuid};
|
use bevy::utils::Uuid;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug, )]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Saveable{
|
pub struct Saveable {
|
||||||
id: Uuid
|
id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Saveable{
|
impl Default for Saveable {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Saveable{
|
Saveable { id: Uuid::new_v4() }
|
||||||
id: Uuid::new_v4()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
use bevy::pbr::{Clusters, VisiblePointLights};
|
use bevy::pbr::{Clusters, VisiblePointLights};
|
||||||
use bevy::render::camera::CameraRenderGraph;
|
use bevy::render::camera::CameraRenderGraph;
|
||||||
use bevy::render::view::VisibleEntities;
|
use bevy::render::view::VisibleEntities;
|
||||||
use bevy::{prelude::*, gltf::GltfExtras};
|
|
||||||
use bevy::tasks::IoTaskPool;
|
use bevy::tasks::IoTaskPool;
|
||||||
|
use bevy::{gltf::GltfExtras, prelude::*};
|
||||||
use bevy_rapier3d::prelude::RigidBody;
|
use bevy_rapier3d::prelude::RigidBody;
|
||||||
use std::io::Write;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
use crate::core::physics::Collider;
|
use crate::core::physics::Collider;
|
||||||
use crate::game::{Pickable, Player};
|
use crate::game::{Pickable, Player};
|
||||||
|
|
||||||
use super::Saveable;
|
use super::Saveable;
|
||||||
|
|
||||||
|
const NEW_SCENE_FILE_PATH: &str = "save.scn.ron";
|
||||||
const NEW_SCENE_FILE_PATH:&str="save.scn.ron";
|
|
||||||
|
|
||||||
#[derive(Component, Event)]
|
#[derive(Component, Event)]
|
||||||
pub struct SaveRequest {
|
pub struct SaveRequest {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn should_save(
|
pub fn should_save(
|
||||||
// keycode: Res<Input<KeyCode>>,
|
// keycode: Res<Input<KeyCode>>,
|
||||||
save_requested_events: EventReader<SaveRequest>,
|
save_requested_events: EventReader<SaveRequest>,
|
||||||
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
return save_requested_events.len() > 0;
|
return save_requested_events.len() > 0;
|
||||||
|
|
||||||
@ -34,7 +31,7 @@ pub fn should_save(
|
|||||||
pub fn save_game(
|
pub fn save_game(
|
||||||
world: &mut World,
|
world: &mut World,
|
||||||
// save_requested_events: EventReader<SaveRequest>,
|
// save_requested_events: EventReader<SaveRequest>,
|
||||||
){
|
) {
|
||||||
info!("saving");
|
info!("saving");
|
||||||
// world.
|
// world.
|
||||||
/*for bli in save_requested_events.iter(){
|
/*for bli in save_requested_events.iter(){
|
||||||
@ -42,9 +39,9 @@ pub fn save_game(
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
let saveable_entities: Vec<Entity> = world
|
let saveable_entities: Vec<Entity> = world
|
||||||
.query_filtered::<Entity, With<Saveable>>()
|
.query_filtered::<Entity, With<Saveable>>()
|
||||||
.iter(world)
|
.iter(world)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
/*let static_entities: Vec<Entity> = world
|
/*let static_entities: Vec<Entity> = world
|
||||||
.query_filtered::<Entity, Without<Saveable>>()
|
.query_filtered::<Entity, Without<Saveable>>()
|
||||||
@ -60,11 +57,9 @@ pub fn save_game(
|
|||||||
.deny::<Visibility>()
|
.deny::<Visibility>()
|
||||||
.deny::<GltfExtras>()
|
.deny::<GltfExtras>()
|
||||||
.deny::<GlobalTransform>()
|
.deny::<GlobalTransform>()
|
||||||
|
|
||||||
.deny::<Collider>()
|
.deny::<Collider>()
|
||||||
.deny::<RigidBody>()
|
.deny::<RigidBody>()
|
||||||
.deny::<Saveable>()
|
.deny::<Saveable>()
|
||||||
|
|
||||||
// camera stuff
|
// camera stuff
|
||||||
.deny::<Camera>()
|
.deny::<Camera>()
|
||||||
.deny::<CameraRenderGraph>()
|
.deny::<CameraRenderGraph>()
|
||||||
@ -73,22 +68,20 @@ pub fn save_game(
|
|||||||
.deny::<VisibleEntities>()
|
.deny::<VisibleEntities>()
|
||||||
.deny::<VisiblePointLights>()
|
.deny::<VisiblePointLights>()
|
||||||
//.deny::<HasGizmoMarker>()
|
//.deny::<HasGizmoMarker>()
|
||||||
|
|
||||||
|
|
||||||
.extract_entities(saveable_entities.into_iter());
|
.extract_entities(saveable_entities.into_iter());
|
||||||
|
|
||||||
|
let dyn_scene = scene_builder.build();
|
||||||
|
let serialized_scene = dyn_scene
|
||||||
|
.serialize_ron(world.resource::<AppTypeRegistry>())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let dyn_scene = scene_builder.build();
|
IoTaskPool::get()
|
||||||
let serialized_scene = dyn_scene.serialize_ron(world.resource::<AppTypeRegistry>()).unwrap();
|
.spawn(async move {
|
||||||
|
// Write the scene RON data to file
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
File::create(format!("assets/scenes/{NEW_SCENE_FILE_PATH}"))
|
||||||
IoTaskPool::get()
|
.and_then(|mut file| file.write(serialized_scene.as_bytes()))
|
||||||
.spawn(async move {
|
.expect("Error while writing scene to file");
|
||||||
// Write the scene RON data to file
|
})
|
||||||
File::create(format!("assets/scenes/{NEW_SCENE_FILE_PATH}"))
|
.detach();
|
||||||
.and_then(|mut file| file.write(serialized_scene.as_bytes()))
|
|
||||||
.expect("Error while writing scene to file");
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
@ -1,6 +1,9 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{assets::GameAssets, state::{InAppRunning, GameState}};
|
use crate::{
|
||||||
|
assets::GameAssets,
|
||||||
|
state::{GameState, InAppRunning},
|
||||||
|
};
|
||||||
use bevy_gltf_blueprints::GameWorldTag;
|
use bevy_gltf_blueprints::GameWorldTag;
|
||||||
|
|
||||||
pub fn setup_game(
|
pub fn setup_game(
|
||||||
@ -8,7 +11,6 @@ pub fn setup_game(
|
|||||||
game_assets: Res<GameAssets>,
|
game_assets: Res<GameAssets>,
|
||||||
mut next_game_state: ResMut<NextState<GameState>>,
|
mut next_game_state: ResMut<NextState<GameState>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
println!("setting up all stuff");
|
println!("setting up all stuff");
|
||||||
commands.insert_resource(AmbientLight {
|
commands.insert_resource(AmbientLight {
|
||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
@ -23,7 +25,7 @@ pub fn setup_game(
|
|||||||
},
|
},
|
||||||
bevy::prelude::Name::from("world"),
|
bevy::prelude::Name::from("world"),
|
||||||
GameWorldTag,
|
GameWorldTag,
|
||||||
InAppRunning
|
InAppRunning,
|
||||||
));
|
));
|
||||||
|
|
||||||
next_game_state.set(GameState::InGame)
|
next_game_state.set(GameState::InGame)
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::{state::{AppState, GameState, InMainMenu}, core::save_load::{LoadRequest, SaveRequest}};
|
use crate::{
|
||||||
|
core::save_load::{LoadRequest, SaveRequest},
|
||||||
|
state::{AppState, GameState, InMainMenu},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn setup_main_menu(mut commands: Commands){
|
pub fn setup_main_menu(mut commands: Commands) {
|
||||||
commands.spawn((Camera2dBundle::default(), InMainMenu));
|
commands.spawn((Camera2dBundle::default(), InMainMenu));
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
@ -21,10 +24,9 @@ pub fn setup_main_menu(mut commands: Commands){
|
|||||||
left: Val::Px(200.0),
|
left: Val::Px(200.0),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
InMainMenu
|
InMainMenu,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
TextBundle::from_section(
|
TextBundle::from_section(
|
||||||
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
"New Game (press Enter to start, press T once the game is started for demo spawning)",
|
||||||
@ -41,7 +43,7 @@ pub fn setup_main_menu(mut commands: Commands){
|
|||||||
left: Val::Px(200.0),
|
left: Val::Px(200.0),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
InMainMenu
|
InMainMenu,
|
||||||
));
|
));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -84,8 +86,8 @@ pub fn setup_main_menu(mut commands: Commands){
|
|||||||
));*/
|
));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands){
|
pub fn teardown_main_menu(bla: Query<Entity, With<InMainMenu>>, mut commands: Commands) {
|
||||||
for bli in bla.iter(){
|
for bli in bla.iter() {
|
||||||
commands.entity(bli).despawn_recursive();
|
commands.entity(bli).despawn_recursive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,11 +97,9 @@ pub fn main_menu(
|
|||||||
|
|
||||||
mut next_app_state: ResMut<NextState<AppState>>,
|
mut next_app_state: ResMut<NextState<AppState>>,
|
||||||
// mut next_game_state: ResMut<NextState<GameState>>,
|
// mut next_game_state: ResMut<NextState<GameState>>,
|
||||||
|
|
||||||
mut save_requested_events: EventWriter<SaveRequest>,
|
mut save_requested_events: EventWriter<SaveRequest>,
|
||||||
mut load_requested_events: EventWriter<LoadRequest>,
|
mut load_requested_events: EventWriter<LoadRequest>,
|
||||||
|
) {
|
||||||
){
|
|
||||||
if keycode.just_pressed(KeyCode::Return) {
|
if keycode.just_pressed(KeyCode::Return) {
|
||||||
next_app_state.set(AppState::AppLoading);
|
next_app_state.set(AppState::AppLoading);
|
||||||
// next_game_state.set(GameState::None);
|
// next_game_state.set(GameState::None);
|
||||||
|
@ -7,52 +7,46 @@ pub use in_main_menu::*;
|
|||||||
pub mod picking;
|
pub mod picking;
|
||||||
pub use picking::*;
|
pub use picking::*;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
insert_dependant_component,
|
||||||
|
state::{AppState, GameState},
|
||||||
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
use crate::{insert_dependant_component, state::{AppState, GameState}};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this file is just for demo purposes, contains various types of components, systems etc
|
// this file is just for demo purposes, contains various types of components, systems etc
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum SoundMaterial{
|
pub enum SoundMaterial {
|
||||||
Metal,
|
Metal,
|
||||||
Wood,
|
Wood,
|
||||||
Rock,
|
Rock,
|
||||||
Cloth,
|
Cloth,
|
||||||
Squishy,
|
Squishy,
|
||||||
#[default]
|
#[default]
|
||||||
None
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo component showing auto injection of components
|
/// Demo component showing auto injection of components
|
||||||
pub struct ShouldBeWithPlayer;
|
pub struct ShouldBeWithPlayer;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Interactible;
|
pub struct Interactible;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn player_move_demo(
|
fn player_move_demo(
|
||||||
keycode: Res<Input<KeyCode>>,
|
keycode: Res<Input<KeyCode>>,
|
||||||
mut players: Query<&mut Transform, With<Player>>,
|
mut players: Query<&mut Transform, With<Player>>,
|
||||||
){
|
) {
|
||||||
|
|
||||||
let speed = 0.2;
|
let speed = 0.2;
|
||||||
if let Ok(mut player) = players.get_single_mut() {
|
if let Ok(mut player) = players.get_single_mut() {
|
||||||
if keycode.pressed(KeyCode::Left) {
|
if keycode.pressed(KeyCode::Left) {
|
||||||
@ -75,17 +69,15 @@ fn player_move_demo(
|
|||||||
pub fn test_collision_events(
|
pub fn test_collision_events(
|
||||||
mut collision_events: EventReader<CollisionEvent>,
|
mut collision_events: EventReader<CollisionEvent>,
|
||||||
mut contact_force_events: EventReader<ContactForceEvent>,
|
mut contact_force_events: EventReader<ContactForceEvent>,
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
for collision_event in collision_events.iter() {
|
for collision_event in collision_events.iter() {
|
||||||
println!("collision");
|
println!("collision");
|
||||||
match collision_event {
|
match collision_event {
|
||||||
CollisionEvent::Started(_entity1, _entity2 ,_) => {
|
CollisionEvent::Started(_entity1, _entity2, _) => {
|
||||||
println!("collision started")
|
println!("collision started")
|
||||||
}
|
}
|
||||||
CollisionEvent::Stopped(_entity1, _entity2 ,_) => {
|
CollisionEvent::Stopped(_entity1, _entity2, _) => {
|
||||||
println!("collision ended")
|
println!("collision ended")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,42 +87,28 @@ pub fn test_collision_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct GamePlugin;
|
pub struct GamePlugin;
|
||||||
impl Plugin for GamePlugin {
|
impl Plugin for GamePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.add_plugins(PickingPlugin)
|
||||||
.add_plugins(PickingPlugin)
|
.register_type::<Interactible>()
|
||||||
|
.register_type::<SoundMaterial>()
|
||||||
.register_type::<Interactible>()
|
.register_type::<Player>()
|
||||||
.register_type::<SoundMaterial>()
|
// little helper utility, to automatically inject components that are dependant on an other component
|
||||||
.register_type::<Player>()
|
// ie, here an Entity with a Player component should also always have a ShouldBeWithPlayer component
|
||||||
// little helper utility, to automatically inject components that are dependant on an other component
|
// you get a warning if you use this, as I consider this to be stop-gap solution (usually you should have either a bundle, or directly define all needed components)
|
||||||
// ie, here an Entity with a Player component should also always have a ShouldBeWithPlayer component
|
.add_systems(
|
||||||
// you get a warning if you use this, as I consider this to be stop-gap solution (usually you should have either a bundle, or directly define all needed components)
|
Update,
|
||||||
.add_systems(Update, (
|
(
|
||||||
// insert_dependant_component::<Player, ShouldBeWithPlayer>,
|
// insert_dependant_component::<Player, ShouldBeWithPlayer>,
|
||||||
player_move_demo, //.run_if(in_state(AppState::Running)),
|
player_move_demo, //.run_if(in_state(AppState::Running)),
|
||||||
// test_collision_events
|
// test_collision_events
|
||||||
)
|
)
|
||||||
.run_if(in_state(GameState::InGame)))
|
.run_if(in_state(GameState::InGame)),
|
||||||
|
)
|
||||||
|
.add_systems(OnEnter(AppState::MenuRunning), setup_main_menu)
|
||||||
.add_systems(
|
.add_systems(OnExit(AppState::MenuRunning), teardown_main_menu)
|
||||||
OnEnter(AppState::MenuRunning),
|
.add_systems(Update, (main_menu))
|
||||||
setup_main_menu
|
.add_systems(OnEnter(AppState::AppRunning), setup_game);
|
||||||
)
|
}
|
||||||
.add_systems(
|
|
||||||
OnExit(AppState::MenuRunning),
|
|
||||||
teardown_main_menu
|
|
||||||
)
|
|
||||||
.add_systems(Update, (main_menu))
|
|
||||||
|
|
||||||
|
|
||||||
.add_systems(
|
|
||||||
OnEnter(AppState::AppRunning),
|
|
||||||
setup_game
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use super::Player;
|
use super::Player;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Pickable;
|
pub struct Pickable;
|
||||||
|
|
||||||
@ -11,11 +10,13 @@ pub struct Pickable;
|
|||||||
pub fn picking(
|
pub fn picking(
|
||||||
players: Query<&GlobalTransform, With<Player>>,
|
players: Query<&GlobalTransform, With<Player>>,
|
||||||
pickables: Query<(Entity, &GlobalTransform), With<Pickable>>,
|
pickables: Query<(Entity, &GlobalTransform), With<Pickable>>,
|
||||||
mut commands: Commands
|
mut commands: Commands,
|
||||||
){
|
) {
|
||||||
for player_transforms in players.iter(){
|
for player_transforms in players.iter() {
|
||||||
for (pickable, pickable_transforms) in pickables.iter(){
|
for (pickable, pickable_transforms) in pickables.iter() {
|
||||||
let distance = player_transforms.translation().distance(pickable_transforms.translation());
|
let distance = player_transforms
|
||||||
|
.translation()
|
||||||
|
.distance(pickable_transforms.translation());
|
||||||
if distance < 2.5 {
|
if distance < 2.5 {
|
||||||
commands.entity(pickable).despawn_recursive();
|
commands.entity(pickable).despawn_recursive();
|
||||||
}
|
}
|
||||||
@ -25,16 +26,12 @@ pub fn picking(
|
|||||||
|
|
||||||
pub struct PickingPlugin;
|
pub struct PickingPlugin;
|
||||||
impl Plugin for PickingPlugin {
|
impl Plugin for PickingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<Pickable>().add_systems(
|
||||||
.register_type::<Pickable>()
|
Update,
|
||||||
|
(
|
||||||
.add_systems(Update, (
|
picking, //.run_if(in_state(AppState::Running)),
|
||||||
picking, //.run_if(in_state(AppState::Running)),
|
),
|
||||||
))
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::time::Duration;
|
use bevy::{asset::ChangeWatcher, gltf::Gltf, prelude::*};
|
||||||
use bevy::{prelude::*, asset::ChangeWatcher, gltf::Gltf};
|
|
||||||
use bevy_editor_pls::prelude::*;
|
use bevy_editor_pls::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
|
||||||
use bevy_gltf_components::ComponentsFromGltfPlugin;
|
use bevy_gltf_components::ComponentsFromGltfPlugin;
|
||||||
|
use bevy_rapier3d::prelude::*;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
@ -19,33 +19,28 @@ use game::*;
|
|||||||
mod test_components;
|
mod test_components;
|
||||||
use test_components::*;
|
use test_components::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
fn main(){
|
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(
|
DefaultPlugins.set(AssetPlugin {
|
||||||
AssetPlugin {
|
|
||||||
// This tells the AssetServer to watch for changes to assets.
|
// This tells the AssetServer to watch for changes to assets.
|
||||||
// It enables our scenes to automatically reload in game when we modify their files.
|
// It enables our scenes to automatically reload in game when we modify their files.
|
||||||
// practical in our case to be able to edit the shaders without needing to recompile
|
// practical in our case to be able to edit the shaders without needing to recompile
|
||||||
// watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(50)), : FIXME: breaks scene save/loading
|
// watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(50)), : FIXME: breaks scene save/loading
|
||||||
..default()
|
..default()
|
||||||
}
|
}),
|
||||||
),
|
// editor
|
||||||
// editor
|
EditorPlugin::default(),
|
||||||
EditorPlugin::default(),
|
// physics
|
||||||
// physics
|
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||||
RapierPhysicsPlugin::<NoUserData>::default(),
|
RapierDebugRenderPlugin::default(),
|
||||||
RapierDebugRenderPlugin::default(),
|
// our custom plugins
|
||||||
// our custom plugins
|
ComponentsFromGltfPlugin,
|
||||||
ComponentsFromGltfPlugin,
|
StatePlugin,
|
||||||
|
AssetsPlugin,
|
||||||
StatePlugin,
|
CorePlugin, // reusable plugins
|
||||||
AssetsPlugin,
|
GamePlugin, // specific to our game
|
||||||
CorePlugin, // reusable plugins
|
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||||
GamePlugin, // specific to our game
|
))
|
||||||
ComponentsTestPlugin // Showcases different type of components /structs
|
.run();
|
||||||
))
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
use bevy::app::AppExit;
|
use bevy::app::AppExit;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||||
pub enum AppState{
|
pub enum AppState {
|
||||||
#[default]
|
#[default]
|
||||||
CoreLoading,
|
CoreLoading,
|
||||||
MenuRunning,
|
MenuRunning,
|
||||||
@ -11,7 +11,7 @@ pub enum AppState{
|
|||||||
AppEnding,
|
AppEnding,
|
||||||
|
|
||||||
// FIXME: not sure
|
// FIXME: not sure
|
||||||
LoadingGame
|
LoadingGame,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default, States)]
|
||||||
@ -25,7 +25,7 @@ pub enum GameState {
|
|||||||
InGameOver,
|
InGameOver,
|
||||||
|
|
||||||
InSaving,
|
InSaving,
|
||||||
InLoading
|
InLoading,
|
||||||
}
|
}
|
||||||
|
|
||||||
// tag components for all entities within a certain state (for despawning them if needed) , FIXME: seems kinda hack-ish
|
// tag components for all entities within a certain state (for despawning them if needed) , FIXME: seems kinda hack-ish
|
||||||
@ -46,13 +46,9 @@ pub struct InMenu;
|
|||||||
#[derive(Component, Default)]
|
#[derive(Component, Default)]
|
||||||
pub struct InGame;
|
pub struct InGame;
|
||||||
|
|
||||||
|
|
||||||
pub struct StatePlugin;
|
pub struct StatePlugin;
|
||||||
impl Plugin for StatePlugin {
|
impl Plugin for StatePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.add_state::<AppState>().add_state::<GameState>();
|
||||||
.add_state::<AppState>()
|
}
|
||||||
.add_state::<GameState>()
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct UnitTest;
|
struct UnitTest;
|
||||||
|
|
||||||
@ -17,70 +16,65 @@ struct TuppleTestU64(u64);
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct TuppleTestStr(String);
|
pub struct TuppleTestStr(String);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTest2(f32, u64, String);
|
struct TuppleTest2(f32, u64, String);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTestBool(bool);
|
struct TuppleTestBool(bool);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec2(Vec2);
|
struct TuppleVec2(Vec2);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec3(Vec3);
|
struct TuppleVec3(Vec3);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec(Vec<String>);
|
struct TuppleVec(Vec<String>);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTestColor(Color);
|
struct TuppleTestColor(Color);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct BasicTest{
|
struct BasicTest {
|
||||||
a: f32,
|
a: f32,
|
||||||
b: u64,
|
b: u64,
|
||||||
c: String
|
c: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum EnumTest{
|
pub enum EnumTest {
|
||||||
Metal,
|
Metal,
|
||||||
Wood,
|
Wood,
|
||||||
Rock,
|
Rock,
|
||||||
Cloth,
|
Cloth,
|
||||||
Squishy,
|
Squishy,
|
||||||
#[default]
|
#[default]
|
||||||
None
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ComponentsTestPlugin;
|
pub struct ComponentsTestPlugin;
|
||||||
impl Plugin for ComponentsTestPlugin {
|
impl Plugin for ComponentsTestPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<BasicTest>()
|
||||||
.register_type::<BasicTest>()
|
.register_type::<UnitTest>()
|
||||||
.register_type::<UnitTest>()
|
.register_type::<TuppleTestF32>()
|
||||||
.register_type::<TuppleTestF32>()
|
.register_type::<TuppleTestU64>()
|
||||||
.register_type::<TuppleTestU64>()
|
.register_type::<TuppleTestStr>()
|
||||||
.register_type::<TuppleTestStr>()
|
.register_type::<TuppleTestBool>()
|
||||||
.register_type::<TuppleTestBool>()
|
.register_type::<TuppleTest2>()
|
||||||
.register_type::<TuppleTest2>()
|
.register_type::<TuppleVec2>()
|
||||||
.register_type::<TuppleVec2>()
|
.register_type::<TuppleVec3>()
|
||||||
.register_type::<TuppleVec3>()
|
.register_type::<EnumTest>()
|
||||||
.register_type::<EnumTest>()
|
.register_type::<TuppleTestColor>()
|
||||||
.register_type::<TuppleTestColor>()
|
.register_type::<TuppleVec>()
|
||||||
|
.register_type::<Vec<String>>();
|
||||||
.register_type::<TuppleVec>()
|
}
|
||||||
.register_type::<Vec<String>>()
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,24 @@
|
|||||||
|
use bevy::core_pipeline::bloom::{BloomCompositeMode, BloomSettings};
|
||||||
|
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::core_pipeline::bloom::{BloomSettings, BloomCompositeMode};
|
|
||||||
use bevy::core_pipeline::tonemapping::{Tonemapping, DebandDither};
|
|
||||||
|
|
||||||
use super::CameraTrackingOffset;
|
use super::CameraTrackingOffset;
|
||||||
|
|
||||||
pub fn camera_replace_proxies (
|
pub fn camera_replace_proxies(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut added_cameras: Query<(Entity, &mut Camera), (Added<Camera>, With<CameraTrackingOffset>)>,
|
mut added_cameras: Query<(Entity, &mut Camera), (Added<Camera>, With<CameraTrackingOffset>)>,
|
||||||
) {
|
) {
|
||||||
|
for (entity, mut camera) in added_cameras.iter_mut() {
|
||||||
for (entity, mut camera) in added_cameras.iter_mut(){
|
|
||||||
info!("detected added camera, updating proxy");
|
info!("detected added camera, updating proxy");
|
||||||
camera.hdr = true;
|
camera.hdr = true;
|
||||||
commands.entity(entity)
|
commands
|
||||||
.insert(
|
.entity(entity)
|
||||||
DebandDither::Enabled
|
.insert(DebandDither::Enabled)
|
||||||
)
|
.insert(Tonemapping::BlenderFilmic)
|
||||||
.insert(
|
.insert(BloomSettings {
|
||||||
Tonemapping::BlenderFilmic
|
intensity: 0.01,
|
||||||
)
|
composite_mode: BloomCompositeMode::Additive,
|
||||||
.insert(
|
..default()
|
||||||
BloomSettings{
|
});
|
||||||
intensity: 0.01,
|
}
|
||||||
composite_mode:BloomCompositeMode::Additive,
|
|
||||||
..default()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug)]
|
#[derive(Component, Reflect, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Component for cameras, with an offset from the Trackable target
|
/// Component for cameras, with an offset from the Trackable target
|
||||||
///
|
///
|
||||||
pub struct CameraTracking{
|
pub struct CameraTracking {
|
||||||
pub offset: Vec3
|
pub offset: Vec3,
|
||||||
}
|
}
|
||||||
impl Default for CameraTracking {
|
impl Default for CameraTracking {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CameraTracking { offset: Vec3::new(0.0, 6.0, 8.0) }
|
CameraTracking {
|
||||||
|
offset: Vec3::new(0.0, 6.0, 8.0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug, Deref, DerefMut)]
|
#[derive(Component, Reflect, Debug, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Component for cameras, with an offset from the Trackable target
|
/// Component for cameras, with an offset from the Trackable target
|
||||||
@ -26,32 +26,33 @@ impl Default for CameraTrackingOffset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CameraTrackingOffset {
|
impl CameraTrackingOffset {
|
||||||
fn new (input: Vec3) -> Self {
|
fn new(input: Vec3) -> Self {
|
||||||
CameraTrackingOffset(input)
|
CameraTrackingOffset(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Add this component to an entity if you want it to be tracked by a Camera
|
/// Add this component to an entity if you want it to be tracked by a Camera
|
||||||
pub struct CameraTrackable;
|
pub struct CameraTrackable;
|
||||||
|
|
||||||
pub fn camera_track(
|
pub fn camera_track(
|
||||||
mut tracking_cameras: Query<(&mut Transform, &CameraTrackingOffset), (With<Camera>, With<CameraTrackingOffset>, Without<CameraTrackable>)>,
|
mut tracking_cameras: Query<
|
||||||
|
(&mut Transform, &CameraTrackingOffset),
|
||||||
|
(
|
||||||
|
With<Camera>,
|
||||||
|
With<CameraTrackingOffset>,
|
||||||
|
Without<CameraTrackable>,
|
||||||
|
),
|
||||||
|
>,
|
||||||
camera_tracked: Query<&Transform, With<CameraTrackable>>,
|
camera_tracked: Query<&Transform, With<CameraTrackable>>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
for (mut camera_transform, tracking_offset) in tracking_cameras.iter_mut() {
|
for (mut camera_transform, tracking_offset) in tracking_cameras.iter_mut() {
|
||||||
for tracked_transform in camera_tracked.iter(){
|
for tracked_transform in camera_tracked.iter() {
|
||||||
|
|
||||||
let target_position = tracked_transform.translation + tracking_offset.0;
|
let target_position = tracked_transform.translation + tracking_offset.0;
|
||||||
let eased_position = camera_transform.translation.lerp(target_position, 0.1);
|
let eased_position = camera_transform.translation.lerp(target_position, 0.1);
|
||||||
camera_transform.translation = eased_position;// + tracking.offset;// tracked_transform.translation + tracking.offset;
|
camera_transform.translation = eased_position; // + tracking.offset;// tracked_transform.translation + tracking.offset;
|
||||||
*camera_transform = camera_transform.looking_at(tracked_transform.translation, Vec3::Y);
|
*camera_transform = camera_transform.looking_at(tracked_transform.translation, Vec3::Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,10 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
pub struct CameraPlugin;
|
pub struct CameraPlugin;
|
||||||
impl Plugin for CameraPlugin {
|
impl Plugin for CameraPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<CameraTrackable>()
|
||||||
.register_type::<CameraTrackable>()
|
.register_type::<CameraTracking>()
|
||||||
.register_type::<CameraTracking>()
|
.register_type::<CameraTrackingOffset>()
|
||||||
.register_type::<CameraTrackingOffset>()
|
.add_systems(Update, (camera_replace_proxies, camera_track));
|
||||||
|
}
|
||||||
.add_systems(Update,
|
|
||||||
(
|
|
||||||
camera_replace_proxies,
|
|
||||||
camera_track,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,29 +1,25 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use bevy::pbr::{CascadeShadowConfigBuilder, CascadeShadowConfig};
|
use bevy::pbr::{CascadeShadowConfig, CascadeShadowConfigBuilder};
|
||||||
|
|
||||||
// fixme might be too specific to might needs, should it be moved out ? also these are all for lights, not models
|
// fixme might be too specific to might needs, should it be moved out ? also these are all for lights, not models
|
||||||
pub fn lighting_replace_proxies(
|
pub fn lighting_replace_proxies(
|
||||||
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
mut added_dirights: Query<(Entity, &mut DirectionalLight), Added<DirectionalLight>>,
|
||||||
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
mut added_spotlights: Query<&mut SpotLight, Added<SpotLight>>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
) {
|
||||||
){
|
for (entity, mut light) in added_dirights.iter_mut() {
|
||||||
|
light.illuminance *= 5.0;
|
||||||
for (entity, mut light) in added_dirights.iter_mut(){
|
light.shadows_enabled = true;
|
||||||
light.illuminance *= 5.0;
|
let shadow_config: CascadeShadowConfig = CascadeShadowConfigBuilder {
|
||||||
light.shadows_enabled = true;
|
first_cascade_far_bound: 15.0,
|
||||||
let shadow_config:CascadeShadowConfig = CascadeShadowConfigBuilder {
|
maximum_distance: 135.0,
|
||||||
first_cascade_far_bound: 15.0,
|
..default()
|
||||||
maximum_distance: 135.0,
|
}
|
||||||
..default()
|
.into();
|
||||||
}
|
commands.entity(entity).insert(shadow_config);
|
||||||
.into();
|
}
|
||||||
commands.entity(entity)
|
for mut light in added_spotlights.iter_mut() {
|
||||||
.insert(shadow_config);
|
light.shadows_enabled = true;
|
||||||
}
|
}
|
||||||
for mut light in added_spotlights.iter_mut(){
|
|
||||||
light.shadows_enabled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
mod lighting_replace_proxies;
|
mod lighting_replace_proxies;
|
||||||
use lighting_replace_proxies::*;
|
use lighting_replace_proxies::*;
|
||||||
|
|
||||||
|
use bevy::pbr::{DirectionalLightShadowMap, NotShadowCaster};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::pbr::{NotShadowCaster, DirectionalLightShadowMap};
|
|
||||||
|
|
||||||
pub struct LightingPlugin;
|
pub struct LightingPlugin;
|
||||||
impl Plugin for LightingPlugin {
|
impl Plugin for LightingPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app
|
||||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||||
// FIXME: adding these since they are missing
|
// FIXME: adding these since they are missing
|
||||||
.register_type::<NotShadowCaster>()
|
.register_type::<NotShadowCaster>()
|
||||||
|
|
||||||
.add_systems(PreUpdate, lighting_replace_proxies) // FIXME: you should actually run this in a specific state most likely
|
.add_systems(PreUpdate, lighting_replace_proxies) // FIXME: you should actually run this in a specific state most likely
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,12 +13,7 @@ pub use physics::*;
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
pub struct CorePlugin;
|
pub struct CorePlugin;
|
||||||
impl Plugin for CorePlugin {
|
impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.add_plugins((LightingPlugin, CameraPlugin, PhysicsPlugin));
|
||||||
.add_plugins((
|
}
|
||||||
LightingPlugin,
|
|
||||||
CameraPlugin,
|
|
||||||
PhysicsPlugin
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use bevy::prelude::ResMut;
|
use bevy::prelude::ResMut;
|
||||||
use bevy_rapier3d::prelude::RapierConfiguration;
|
use bevy_rapier3d::prelude::RapierConfiguration;
|
||||||
|
|
||||||
pub fn pause_physics(mut physics_config: ResMut<RapierConfiguration>){
|
pub fn pause_physics(mut physics_config: ResMut<RapierConfiguration>) {
|
||||||
physics_config.physics_pipeline_active = false;
|
physics_config.physics_pipeline_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resume_physics(mut physics_config: ResMut<RapierConfiguration>){
|
pub fn resume_physics(mut physics_config: ResMut<RapierConfiguration>) {
|
||||||
physics_config.physics_pipeline_active = true;
|
physics_config.physics_pipeline_active = true;
|
||||||
}
|
}
|
@ -10,8 +10,8 @@ use bevy::prelude::*;
|
|||||||
// use crate::Collider;
|
// use crate::Collider;
|
||||||
pub struct PhysicsPlugin;
|
pub struct PhysicsPlugin;
|
||||||
impl Plugin for PhysicsPlugin {
|
impl Plugin for PhysicsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app
|
||||||
.register_type::<AutoAABBCollider>()
|
.register_type::<AutoAABBCollider>()
|
||||||
.register_type::<physics_replace_proxies::Collider>()
|
.register_type::<physics_replace_proxies::Collider>()
|
||||||
|
|
||||||
@ -23,6 +23,5 @@ impl Plugin for PhysicsPlugin {
|
|||||||
//.add_system(pause_physics.in_schedule(OnEnter(GameState::InMenu)))
|
//.add_system(pause_physics.in_schedule(OnEnter(GameState::InMenu)))
|
||||||
//.add_system(resume_physics.in_schedule(OnEnter(GameState::InGame)))
|
//.add_system(resume_physics.in_schedule(OnEnter(GameState::InGame)))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
// use bevy::render::primitives::Aabb;
|
// use bevy::render::primitives::Aabb;
|
||||||
use bevy_rapier3d::geometry::Collider as RapierCollider;
|
use bevy_rapier3d::geometry::Collider as RapierCollider;
|
||||||
use bevy_rapier3d::prelude::{ComputedColliderShape, ActiveEvents, ActiveCollisionTypes};
|
use bevy_rapier3d::prelude::{ActiveCollisionTypes, ActiveEvents, ComputedColliderShape};
|
||||||
|
|
||||||
use super::utils::*;
|
use super::utils::*;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum Collider {
|
pub enum Collider {
|
||||||
Ball(f32),
|
Ball(f32),
|
||||||
@ -15,20 +15,23 @@ pub enum Collider {
|
|||||||
Mesh,
|
Mesh,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum AutoAABBCollider {
|
pub enum AutoAABBCollider {
|
||||||
#[default]
|
#[default]
|
||||||
Cuboid,
|
Cuboid,
|
||||||
Ball,
|
Ball,
|
||||||
Capsule
|
Capsule,
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaces all physics stand-ins with the actual rapier types
|
// replaces all physics stand-ins with the actual rapier types
|
||||||
pub fn physics_replace_proxies (
|
pub fn physics_replace_proxies(
|
||||||
meshes: Res<Assets<Mesh>>,
|
meshes: Res<Assets<Mesh>>,
|
||||||
mesh_handles: Query<&Handle<Mesh>>,
|
mesh_handles: Query<&Handle<Mesh>>,
|
||||||
mut proxy_colliders: Query<(Entity, &Collider, &Name, &mut Visibility), (Without<RapierCollider>, Added<Collider>)>,
|
mut proxy_colliders: Query<
|
||||||
|
(Entity, &Collider, &Name, &mut Visibility),
|
||||||
|
(Without<RapierCollider>, Added<Collider>),
|
||||||
|
>,
|
||||||
// needed for tri meshes
|
// needed for tri meshes
|
||||||
children: Query<&Children>,
|
children: Query<&Children>,
|
||||||
|
|
||||||
@ -37,12 +40,12 @@ pub fn physics_replace_proxies (
|
|||||||
for proxy_colider in proxy_colliders.iter_mut() {
|
for proxy_colider in proxy_colliders.iter_mut() {
|
||||||
let (entity, collider_proxy, name, mut visibility) = proxy_colider;
|
let (entity, collider_proxy, name, mut visibility) = proxy_colider;
|
||||||
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
// we hide the collider meshes: perhaps they should be removed altogether once processed ?
|
||||||
if name.ends_with( "_collider" ) || name.ends_with( "_sensor" ) {
|
if name.ends_with("_collider") || name.ends_with("_sensor") {
|
||||||
*visibility = Visibility::Hidden;
|
*visibility = Visibility::Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rapier_collider:RapierCollider;
|
let mut rapier_collider: RapierCollider;
|
||||||
match collider_proxy{
|
match collider_proxy {
|
||||||
Collider::Ball(radius) => {
|
Collider::Ball(radius) => {
|
||||||
println!("proxy: ball");
|
println!("proxy: ball");
|
||||||
rapier_collider = RapierCollider::ball(*radius);
|
rapier_collider = RapierCollider::ball(*radius);
|
||||||
@ -69,15 +72,25 @@ pub fn physics_replace_proxies (
|
|||||||
}
|
}
|
||||||
Collider::Mesh => {
|
Collider::Mesh => {
|
||||||
println!("proxy: mesh");
|
println!("proxy: mesh");
|
||||||
for (_, collider_mesh) in Mesh::search_in_children(entity, &children, &meshes, &mesh_handles)
|
for (_, collider_mesh) in
|
||||||
|
Mesh::search_in_children(entity, &children, &meshes, &mesh_handles)
|
||||||
{
|
{
|
||||||
rapier_collider = RapierCollider::from_bevy_mesh(collider_mesh, &ComputedColliderShape::TriMesh).unwrap();
|
rapier_collider = RapierCollider::from_bevy_mesh(
|
||||||
commands.entity(entity)
|
collider_mesh,
|
||||||
|
&ComputedColliderShape::TriMesh,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
.insert(rapier_collider)
|
.insert(rapier_collider)
|
||||||
// FIXME: this is just for demo purposes !!!
|
// FIXME: this is just for demo purposes !!!
|
||||||
.insert(ActiveCollisionTypes::default() | ActiveCollisionTypes::KINEMATIC_STATIC | ActiveCollisionTypes::STATIC_STATIC | ActiveCollisionTypes::DYNAMIC_STATIC)
|
.insert(
|
||||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
ActiveCollisionTypes::default()
|
||||||
;
|
| ActiveCollisionTypes::KINEMATIC_STATIC
|
||||||
|
| ActiveCollisionTypes::STATIC_STATIC
|
||||||
|
| ActiveCollisionTypes::DYNAMIC_STATIC,
|
||||||
|
)
|
||||||
|
.insert(ActiveEvents::COLLISION_EVENTS);
|
||||||
// .insert(ActiveEvents::COLLISION_EVENTS)
|
// .insert(ActiveEvents::COLLISION_EVENTS)
|
||||||
// break;
|
// break;
|
||||||
// RapierCollider::convex_hull(points)
|
// RapierCollider::convex_hull(points)
|
||||||
|
@ -5,7 +5,7 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
pub struct EcsRelationshipsPlugin;
|
pub struct EcsRelationshipsPlugin;
|
||||||
impl Plugin for EcsRelationshipsPlugin {
|
impl Plugin for EcsRelationshipsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app;
|
app;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,15 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub fn insert_dependant_component<Dependant: Component, Dependency: Component+ std::default::Default>(
|
pub fn insert_dependant_component<
|
||||||
|
Dependant: Component,
|
||||||
|
Dependency: Component + std::default::Default,
|
||||||
|
>(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
entities_without_depency: Query<(Entity, &Name), (With<Dependant>, Without<Dependency>)>,
|
entities_without_depency: Query<(Entity, &Name), (With<Dependant>, Without<Dependency>)>,
|
||||||
) {
|
) {
|
||||||
for (entity, name) in entities_without_depency.iter() {
|
for (entity, name) in entities_without_depency.iter() {
|
||||||
let name = name.clone().to_string();
|
let name = name.clone().to_string();
|
||||||
commands.entity(entity)
|
commands.entity(entity).insert(Dependency::default());
|
||||||
.insert(
|
|
||||||
Dependency::default()
|
|
||||||
)
|
|
||||||
;
|
|
||||||
warn!("found an entity called {} with a {} component but without an {}, please check your assets", name.clone(), std::any::type_name::<Dependant>(), std::any::type_name::<Dependency>());
|
warn!("found an entity called {} with a {} component but without an {}, please check your assets", name.clone(), std::any::type_name::<Dependant>(), std::any::type_name::<Dependency>());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,50 +1,45 @@
|
|||||||
|
use crate::insert_dependant_component;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
use crate::insert_dependant_component;
|
|
||||||
|
|
||||||
// this file is just for demo purposes, contains various types of components, systems etc
|
// this file is just for demo purposes, contains various types of components, systems etc
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum SoundMaterial{
|
pub enum SoundMaterial {
|
||||||
Metal,
|
Metal,
|
||||||
Wood,
|
Wood,
|
||||||
Rock,
|
Rock,
|
||||||
Cloth,
|
Cloth,
|
||||||
Squishy,
|
Squishy,
|
||||||
#[default]
|
#[default]
|
||||||
None
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo component showing auto injection of components
|
/// Demo component showing auto injection of components
|
||||||
pub struct ShouldBeWithPlayer;
|
pub struct ShouldBeWithPlayer;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Interactible;
|
pub struct Interactible;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Pickable;
|
pub struct Pickable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn player_move_demo(
|
fn player_move_demo(
|
||||||
keycode: Res<Input<KeyCode>>,
|
keycode: Res<Input<KeyCode>>,
|
||||||
mut players: Query<&mut Transform, With<Player>>,
|
mut players: Query<&mut Transform, With<Player>>,
|
||||||
){
|
) {
|
||||||
|
|
||||||
let speed = 0.2;
|
let speed = 0.2;
|
||||||
if let Ok(mut player) = players.get_single_mut() {
|
if let Ok(mut player) = players.get_single_mut() {
|
||||||
if keycode.pressed(KeyCode::Left) {
|
if keycode.pressed(KeyCode::Left) {
|
||||||
@ -67,17 +62,15 @@ fn player_move_demo(
|
|||||||
pub fn test_collision_events(
|
pub fn test_collision_events(
|
||||||
mut collision_events: EventReader<CollisionEvent>,
|
mut collision_events: EventReader<CollisionEvent>,
|
||||||
mut contact_force_events: EventReader<ContactForceEvent>,
|
mut contact_force_events: EventReader<ContactForceEvent>,
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
for collision_event in collision_events.iter() {
|
for collision_event in collision_events.iter() {
|
||||||
println!("collision");
|
println!("collision");
|
||||||
match collision_event {
|
match collision_event {
|
||||||
CollisionEvent::Started(_entity1, _entity2 ,_) => {
|
CollisionEvent::Started(_entity1, _entity2, _) => {
|
||||||
println!("collision started")
|
println!("collision started")
|
||||||
}
|
}
|
||||||
CollisionEvent::Stopped(_entity1, _entity2 ,_) => {
|
CollisionEvent::Stopped(_entity1, _entity2, _) => {
|
||||||
println!("collision ended")
|
println!("collision ended")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,23 +80,23 @@ pub fn test_collision_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct DemoPlugin;
|
pub struct DemoPlugin;
|
||||||
impl Plugin for DemoPlugin {
|
impl Plugin for DemoPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<Interactible>()
|
||||||
.register_type::<Interactible>()
|
.register_type::<Pickable>()
|
||||||
.register_type::<Pickable>()
|
.register_type::<SoundMaterial>()
|
||||||
.register_type::<SoundMaterial>()
|
.register_type::<Player>()
|
||||||
.register_type::<Player>()
|
// little helper utility, to automatically inject components that are dependant on an other component
|
||||||
// little helper utility, to automatically inject components that are dependant on an other component
|
// ie, here an Entity with a Player component should also always have a ShouldBeWithPlayer component
|
||||||
// ie, here an Entity with a Player component should also always have a ShouldBeWithPlayer component
|
// you get a warning if you use this, as I consider this to be stop-gap solution (usually you should have either a bundle, or directly define all needed components)
|
||||||
// you get a warning if you use this, as I consider this to be stop-gap solution (usually you should have either a bundle, or directly define all needed components)
|
.add_systems(
|
||||||
.add_systems(Update, (
|
Update,
|
||||||
insert_dependant_component::<Player, ShouldBeWithPlayer>,
|
(
|
||||||
player_move_demo, //.run_if(in_state(AppState::Running)),
|
insert_dependant_component::<Player, ShouldBeWithPlayer>,
|
||||||
test_collision_events
|
player_move_demo, //.run_if(in_state(AppState::Running)),
|
||||||
))
|
test_collision_events,
|
||||||
;
|
),
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::time::Duration;
|
use bevy::{asset::ChangeWatcher, gltf::Gltf, prelude::*};
|
||||||
use bevy::{prelude::*, asset::ChangeWatcher, gltf::Gltf};
|
|
||||||
use bevy_editor_pls::prelude::*;
|
use bevy_editor_pls::prelude::*;
|
||||||
use bevy_rapier3d::prelude::*;
|
|
||||||
use bevy_gltf_components::ComponentsFromGltfPlugin;
|
use bevy_gltf_components::ComponentsFromGltfPlugin;
|
||||||
|
use bevy_rapier3d::prelude::*;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
@ -13,12 +13,11 @@ use game::*;
|
|||||||
mod test_components;
|
mod test_components;
|
||||||
use test_components::*;
|
use test_components::*;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// helper marker component
|
/// helper marker component
|
||||||
pub struct LoadedMarker;
|
pub struct LoadedMarker;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
|
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
|
||||||
enum AppState {
|
enum AppState {
|
||||||
#[default]
|
#[default]
|
||||||
@ -26,54 +25,41 @@ enum AppState {
|
|||||||
Running,
|
Running,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
fn main(){
|
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(
|
DefaultPlugins.set(AssetPlugin {
|
||||||
AssetPlugin {
|
|
||||||
// This tells the AssetServer to watch for changes to assets.
|
// This tells the AssetServer to watch for changes to assets.
|
||||||
// It enables our scenes to automatically reload in game when we modify their files.
|
// It enables our scenes to automatically reload in game when we modify their files.
|
||||||
// practical in our case to be able to edit the shaders without needing to recompile
|
// practical in our case to be able to edit the shaders without needing to recompile
|
||||||
watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(50)),
|
watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(50)),
|
||||||
..default()
|
..default()
|
||||||
}
|
}),
|
||||||
),
|
// editor
|
||||||
// editor
|
EditorPlugin::default(),
|
||||||
EditorPlugin::default(),
|
// physics
|
||||||
// physics
|
RapierPhysicsPlugin::<NoUserData>::default(),
|
||||||
RapierPhysicsPlugin::<NoUserData>::default(),
|
RapierDebugRenderPlugin::default(),
|
||||||
RapierDebugRenderPlugin::default(),
|
// our custom plugins
|
||||||
// our custom plugins
|
ComponentsFromGltfPlugin,
|
||||||
ComponentsFromGltfPlugin,
|
CorePlugin, // reusable plugins
|
||||||
CorePlugin, // reusable plugins
|
DemoPlugin, // specific to our game
|
||||||
DemoPlugin, // specific to our game
|
ComponentsTestPlugin, // Showcases different type of components /structs
|
||||||
ComponentsTestPlugin // Showcases different type of components /structs
|
))
|
||||||
))
|
.add_state::<AppState>()
|
||||||
|
.add_systems(Startup, setup)
|
||||||
.add_state::<AppState>()
|
.add_systems(Update, (spawn_level.run_if(in_state(AppState::Loading)),))
|
||||||
.add_systems(Startup, setup)
|
.run();
|
||||||
.add_systems(Update, (
|
|
||||||
spawn_level.run_if(in_state(AppState::Loading)),
|
|
||||||
))
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
struct AssetLoadHelper(Handle<Scene>);
|
struct AssetLoadHelper(Handle<Scene>);
|
||||||
// we preload the data here, but this is for DEMO PURPOSES ONLY !! Please use https://github.com/NiklasEi/bevy_asset_loader or a similar logic to seperate loading / pre processing
|
// we preload the data here, but this is for DEMO PURPOSES ONLY !! Please use https://github.com/NiklasEi/bevy_asset_loader or a similar logic to seperate loading / pre processing
|
||||||
// of assets from the spawning
|
// of assets from the spawning
|
||||||
// AssetLoadHelper is also just for the same purpose, you do not need it in a real scenario
|
// AssetLoadHelper is also just for the same purpose, you do not need it in a real scenario
|
||||||
// the states here are also for demo purposes only,
|
// the states here are also for demo purposes only,
|
||||||
fn setup(
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
||||||
mut commands: Commands,
|
let tmp: Handle<Scene> = asset_server.load("basic/models/level1.glb#Scene0");
|
||||||
asset_server: Res<AssetServer>,
|
|
||||||
) {
|
|
||||||
|
|
||||||
let tmp: Handle<Scene> = asset_server.load("basic/models/level1.glb#Scene0");
|
|
||||||
commands.insert_resource(AssetLoadHelper(tmp));
|
commands.insert_resource(AssetLoadHelper(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,28 +70,25 @@ fn spawn_level(
|
|||||||
|
|
||||||
mut asset_event_reader: EventReader<AssetEvent<Gltf>>,
|
mut asset_event_reader: EventReader<AssetEvent<Gltf>>,
|
||||||
mut next_state: ResMut<NextState<AppState>>,
|
mut next_state: ResMut<NextState<AppState>>,
|
||||||
){
|
) {
|
||||||
|
|
||||||
if let Some(asset_event) = asset_event_reader.iter().next() {
|
if let Some(asset_event) = asset_event_reader.iter().next() {
|
||||||
match asset_event {
|
match asset_event {
|
||||||
AssetEvent::Created { handle: _ } => {
|
AssetEvent::Created { handle: _ } => {
|
||||||
info!("GLTF loaded");
|
info!("GLTF loaded");
|
||||||
if scene_markers.is_empty() {
|
if scene_markers.is_empty() {
|
||||||
info!("spawning scene");
|
info!("spawning scene");
|
||||||
commands.spawn(
|
commands.spawn((
|
||||||
(
|
SceneBundle {
|
||||||
SceneBundle {
|
scene: preloaded_scene.0.clone(),
|
||||||
scene: preloaded_scene.0.clone(),
|
..default()
|
||||||
..default()
|
},
|
||||||
},
|
LoadedMarker,
|
||||||
LoadedMarker,
|
Name::new("Level1"),
|
||||||
Name::new("Level1")
|
));
|
||||||
)
|
|
||||||
);
|
|
||||||
next_state.set(AppState::Running);
|
next_state.set(AppState::Running);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct UnitTest;
|
struct UnitTest;
|
||||||
|
|
||||||
@ -17,70 +16,65 @@ struct TuppleTestU64(u64);
|
|||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct TuppleTestStr(String);
|
pub struct TuppleTestStr(String);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTest2(f32, u64, String);
|
struct TuppleTest2(f32, u64, String);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTestBool(bool);
|
struct TuppleTestBool(bool);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec2(Vec2);
|
struct TuppleVec2(Vec2);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec3(Vec3);
|
struct TuppleVec3(Vec3);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleVec(Vec<String>);
|
struct TuppleVec(Vec<String>);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct TuppleTestColor(Color);
|
struct TuppleTestColor(Color);
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
struct BasicTest{
|
struct BasicTest {
|
||||||
a: f32,
|
a: f32,
|
||||||
b: u64,
|
b: u64,
|
||||||
c: String
|
c: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug, )]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub enum EnumTest{
|
pub enum EnumTest {
|
||||||
Metal,
|
Metal,
|
||||||
Wood,
|
Wood,
|
||||||
Rock,
|
Rock,
|
||||||
Cloth,
|
Cloth,
|
||||||
Squishy,
|
Squishy,
|
||||||
#[default]
|
#[default]
|
||||||
None
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ComponentsTestPlugin;
|
pub struct ComponentsTestPlugin;
|
||||||
impl Plugin for ComponentsTestPlugin {
|
impl Plugin for ComponentsTestPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app
|
app.register_type::<BasicTest>()
|
||||||
.register_type::<BasicTest>()
|
.register_type::<UnitTest>()
|
||||||
.register_type::<UnitTest>()
|
.register_type::<TuppleTestF32>()
|
||||||
.register_type::<TuppleTestF32>()
|
.register_type::<TuppleTestU64>()
|
||||||
.register_type::<TuppleTestU64>()
|
.register_type::<TuppleTestStr>()
|
||||||
.register_type::<TuppleTestStr>()
|
.register_type::<TuppleTestBool>()
|
||||||
.register_type::<TuppleTestBool>()
|
.register_type::<TuppleTest2>()
|
||||||
.register_type::<TuppleTest2>()
|
.register_type::<TuppleVec2>()
|
||||||
.register_type::<TuppleVec2>()
|
.register_type::<TuppleVec3>()
|
||||||
.register_type::<TuppleVec3>()
|
.register_type::<EnumTest>()
|
||||||
.register_type::<EnumTest>()
|
.register_type::<TuppleTestColor>()
|
||||||
.register_type::<TuppleTestColor>()
|
.register_type::<TuppleVec>()
|
||||||
|
.register_type::<Vec<String>>();
|
||||||
.register_type::<TuppleVec>()
|
}
|
||||||
.register_type::<Vec<String>>()
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user