Finished persistance prototype

This commit is contained in:
rewin
2024-01-25 23:34:25 +03:00
parent 68833f0785
commit 4318496d58
9 changed files with 222 additions and 262 deletions
Generated
+8 -9
View File
@@ -3787,7 +3787,7 @@ dependencies = [
[[package]] [[package]]
name = "space_bevy_xpbd_plugin" name = "space_bevy_xpbd_plugin"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy_xpbd_3d", "bevy_xpbd_3d",
@@ -3797,7 +3797,7 @@ dependencies = [
[[package]] [[package]]
name = "space_editor" name = "space_editor"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"space_bevy_xpbd_plugin", "space_bevy_xpbd_plugin",
@@ -3808,7 +3808,7 @@ dependencies = [
[[package]] [[package]]
name = "space_editor_core" name = "space_editor_core"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"space_persistence", "space_persistence",
@@ -3820,7 +3820,7 @@ dependencies = [
[[package]] [[package]]
name = "space_editor_ui" name = "space_editor_ui"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy_debug_grid", "bevy_debug_grid",
@@ -3841,7 +3841,7 @@ dependencies = [
[[package]] [[package]]
name = "space_persistence" name = "space_persistence"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"ron", "ron",
@@ -3851,7 +3851,7 @@ dependencies = [
[[package]] [[package]]
name = "space_prefab" name = "space_prefab"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy-inspector-egui", "bevy-inspector-egui",
@@ -3865,7 +3865,7 @@ dependencies = [
[[package]] [[package]]
name = "space_shared" name = "space_shared"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"bevy-inspector-egui", "bevy-inspector-egui",
@@ -3875,11 +3875,10 @@ dependencies = [
[[package]] [[package]]
name = "space_undo" name = "space_undo"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/rewin123/space_editor?rev=b56d81222cbf59448ecda5064bf1b37ca90b84f1#b56d81222cbf59448ecda5064bf1b37ca90b84f1" source = "git+https://github.com/rewin123/space_editor?rev=ce83f86dc902787ab16213f3209276a784654df6#ce83f86dc902787ab16213f3209276a784654df6"
dependencies = [ dependencies = [
"bevy", "bevy",
"pretty-type-name", "pretty-type-name",
"space_shared",
] ]
[[package]] [[package]]
Binary file not shown.
+21 -14
View File
@@ -1,9 +1,15 @@
use std::fmt; use std::fmt;
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{prelude::*, window::PrimaryWindow};
use bevy_inspector_egui::{quick::WorldInspectorPlugin, bevy_egui::EguiPlugin, DefaultInspectorConfigPlugin}; use bevy_inspector_egui::{bevy_egui::EguiPlugin, DefaultInspectorConfigPlugin};
use bevy_mod_picking::debug::DebugPickingMode; use bevy_mod_picking::debug::DebugPickingMode;
use space_editor::{space_editor_ui::{EditorPluginGroup, EditorPickingPlugin, EditorDefaultCameraPlugin, bottom_menu::BottomMenuPlugin, EditorUiCore, tools::gizmo::GizmoToolPlugin, ShowEditorUi}, prelude::{EditorCameraMarker, space_undo::UndoPlugin}}; use space_editor::{
prelude::EditorCameraMarker,
space_editor_ui::{
bottom_menu::BottomMenuPlugin, tools::gizmo::GizmoToolPlugin, EditorDefaultCameraPlugin,
EditorPickingPlugin, EditorPluginGroup, EditorUiCore, ShowEditorUi,
},
};
use crate::{ use crate::{
camera_controller::{CameraController, CameraMotionSystem}, camera_controller::{CameraController, CameraMotionSystem},
@@ -46,14 +52,14 @@ impl Plugin for DebugPlugin {
), ),
); );
//space_editor stuff //space_editor stuff
// app.add_plugins(UndoPlugin); // app.add_plugins(UndoPlugin);
app.add_plugins( app.add_plugins(
EditorPluginGroup.build() EditorPluginGroup
.build()
.disable::<EditorUiCore>() .disable::<EditorUiCore>()
.add_before::<EditorDefaultCameraPlugin, _>(EditorUiCore { .add_before::<EditorDefaultCameraPlugin, _>(EditorUiCore {
disable_no_editor_cams: false disable_no_editor_cams: false,
}) })
.disable::<EguiPlugin>() .disable::<EguiPlugin>()
.disable::<DefaultInspectorConfigPlugin>() .disable::<DefaultInspectorConfigPlugin>()
@@ -62,18 +68,19 @@ impl Plugin for DebugPlugin {
.disable::<BottomMenuPlugin>() .disable::<BottomMenuPlugin>()
.disable::<GizmoToolPlugin>() .disable::<GizmoToolPlugin>()
.set(space_editor::prelude::SelectedPlugin { .set(space_editor::prelude::SelectedPlugin {
show_selected_wireframe: false show_selected_wireframe: false,
}) }),
); );
app.add_systems(Update, sync_editor_camera); app.add_systems(Update, sync_editor_camera);
app.add_systems(Update, update_editor_ui_mode.run_if(resource_changed::<DebugMode>())); app.add_systems(
Update,
update_editor_ui_mode.run_if(resource_changed::<DebugMode>()),
);
} }
} }
fn toggle_debug_mode( fn toggle_debug_mode(mut input: EventReader<InputAction>, mut r_debug: ResMut<DebugMode>) {
mut input: EventReader<InputAction>,
mut r_debug: ResMut<DebugMode>,) {
if input if input
.read() .read()
.any(|action| matches!(action, InputAction(Lifecycle::Stop, Action::ToggleDebug))) .any(|action| matches!(action, InputAction(Lifecycle::Stop, Action::ToggleDebug)))
@@ -164,10 +171,10 @@ pub fn print_mat3(m: &Mat3, label: impl fmt::Display) -> fmt::Result {
} }
fn sync_editor_camera( fn sync_editor_camera(
mut cmd : Commands, mut cmd: Commands,
mut q_cam : Query<Entity, (With<MainCamera>, Without<EditorCameraMarker>)> mut q_cam: Query<Entity, (With<MainCamera>, Without<EditorCameraMarker>)>,
) { ) {
for ent in q_cam.iter_mut() { for ent in q_cam.iter_mut() {
cmd.entity(ent).insert(EditorCameraMarker); cmd.entity(ent).insert(EditorCameraMarker);
} }
} }
+8 -2
View File
@@ -320,12 +320,18 @@ fn read_mouse_delta(
// TODO: Make it configurable // TODO: Make it configurable
fn send_undo_event(mut events: EventWriter<UndoRedo>, keyboard: Res<Input<KeyCode>>) { fn send_undo_event(mut events: EventWriter<UndoRedo>, keyboard: Res<Input<KeyCode>>) {
if keyboard.pressed(KeyCode::ControlLeft) && keyboard.just_pressed(KeyCode::Z) && !keyboard.pressed(KeyCode::ShiftLeft) { if keyboard.pressed(KeyCode::ControlLeft)
&& keyboard.just_pressed(KeyCode::Z)
&& !keyboard.pressed(KeyCode::ShiftLeft)
{
events.send(UndoRedo::Undo); events.send(UndoRedo::Undo);
info!("Undo event sent"); info!("Undo event sent");
} }
if keyboard.pressed(KeyCode::ControlLeft) && keyboard.just_pressed(KeyCode::Z) && keyboard.pressed(KeyCode::ShiftLeft) { if keyboard.pressed(KeyCode::ControlLeft)
&& keyboard.just_pressed(KeyCode::Z)
&& keyboard.pressed(KeyCode::ShiftLeft)
{
events.send(UndoRedo::Redo); events.send(UndoRedo::Redo);
info!("Redo event sent"); info!("Redo event sent");
} }
+1 -1
View File
@@ -36,7 +36,7 @@ pub(super) fn spawn_gizmo_camera(
}, },
RenderLayers::layer(GIZMO_RENDER_LAYER), RenderLayers::layer(GIZMO_RENDER_LAYER),
Fxaa::default(), Fxaa::default(),
NotShowCamera NotShowCamera,
)); ));
}); });
} }
+8 -7
View File
@@ -24,7 +24,7 @@ impl Plugin for SelectionPlugin {
.chain() .chain()
.after(SceneSpawnerSystem), .after(SceneSpawnerSystem),
); );
app.add_systems(Update, tag_scene_elements); app.add_systems(Update, tag_scene_elements);
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
@@ -35,10 +35,7 @@ impl Plugin for SelectionPlugin {
.run_if(resource_changed_or_removed::<Selection>()), .run_if(resource_changed_or_removed::<Selection>()),
); );
app.add_systems( app.add_systems(Update, sync_editor_selected);
Update,
sync_editor_selected
);
} }
} }
@@ -56,11 +53,15 @@ fn sync_editor_selected(
q_new_selected: Query<Entity, (Added<Selected>, Without<space_editor::prelude::Selected>)>, q_new_selected: Query<Entity, (Added<Selected>, Without<space_editor::prelude::Selected>)>,
q_editor_selected: Query<Entity, With<space_editor::prelude::Selected>>, q_editor_selected: Query<Entity, With<space_editor::prelude::Selected>>,
q_selected: Query<Entity, With<Selected>>, q_selected: Query<Entity, With<Selected>>,
q_added_editor_selected: Query<Entity, (Without<Selected>, Added<space_editor::prelude::Selected>)>, q_added_editor_selected: Query<
Entity,
(Without<Selected>, Added<space_editor::prelude::Selected>),
>,
) { ) {
for ent in q_new_selected.iter() { for ent in q_new_selected.iter() {
for ed_ent in q_editor_selected.iter() { for ed_ent in q_editor_selected.iter() {
cmd.entity(ed_ent).remove::<space_editor::prelude::Selected>(); cmd.entity(ed_ent)
.remove::<space_editor::prelude::Selected>();
} }
cmd.entity(ent).insert(space_editor::prelude::Selected); cmd.entity(ent).insert(space_editor::prelude::Selected);
} }
+5 -10
View File
@@ -3,10 +3,6 @@
use bevy::{app::PluginGroupBuilder, prelude::*}; use bevy::{app::PluginGroupBuilder, prelude::*};
use bevy_mod_picking::DefaultPickingPlugins; use bevy_mod_picking::DefaultPickingPlugins;
use space_editor::{
prelude::{space_undo::UndoPlugin, PersistencePlugin},
space_editor_ui::{EditorPluginGroup, ext::{bevy_egui::EguiPlugin, bevy_inspector_egui::DefaultInspectorConfigPlugin}, EditorPickingPlugin},
};
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
@@ -17,12 +13,12 @@ mod input;
mod inspector; mod inspector;
mod interaction; mod interaction;
mod math; mod math;
mod persistance;
mod scene; mod scene;
mod skybox; mod skybox;
mod ui; mod ui;
mod viewport; mod viewport;
mod world_grid; mod world_grid;
mod persistance;
use crate::{ use crate::{
camera_controller::CameraControllerPlugin, camera_controller::CameraControllerPlugin,
@@ -79,9 +75,7 @@ impl PluginGroup for CommonPlugins {
struct EditorPlugins; struct EditorPlugins;
impl PluginGroup for EditorPlugins { impl PluginGroup for EditorPlugins {
fn build(self) -> PluginGroupBuilder { fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>() PluginGroupBuilder::start::<Self>().add(InteractionPlugin)
.add(InteractionPlugin)
.add(UndoPlugin)
} }
} }
@@ -125,7 +119,7 @@ pub fn init(viewport_size: ViewportSize) {
SkyboxPlugin, SkyboxPlugin,
UiLayerPlugin, UiLayerPlugin,
WorldGridPlugin, WorldGridPlugin,
persistance::PersistancePlugin persistance::PersistancePlugin,
)) ))
.add_systems( .add_systems(
Startup, Startup,
@@ -228,7 +222,8 @@ pub fn start_internal(
CommonPlugins, CommonPlugins,
)); ));
if matches!(studio_mode, StudioMode::Editor) { if studio_mode == StudioMode::Editor {
info!("Starting in editor mode");
app.add_plugins((DefaultPickingPlugins, EditorPlugins)); app.add_plugins((DefaultPickingPlugins, EditorPlugins));
// Only for registering components for undo // Only for registering components for undo
+12 -6
View File
@@ -6,17 +6,23 @@ pub struct PersistancePlugin;
impl Plugin for PersistancePlugin { impl Plugin for PersistancePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
info!("PersistancePlugin::build"); info!("PersistancePlugin::build");
app.editor_tab_by_trait(EditorTabName::Other("Persistance".to_string()), DebugPersistanceTab::default()); app.editor_tab_by_trait(
EditorTabName::Other("Persistance".to_string()),
DebugPersistanceTab::default(),
);
} }
} }
#[derive(Resource, Default)] #[derive(Resource, Default)]
pub struct DebugPersistanceTab { pub struct DebugPersistanceTab {}
}
impl EditorTab for DebugPersistanceTab { impl EditorTab for DebugPersistanceTab {
fn ui(&mut self, ui: &mut bevy_inspector_egui::egui::Ui, commands: &mut Commands, world: &mut World) { fn ui(
&mut self,
ui: &mut bevy_inspector_egui::egui::Ui,
commands: &mut Commands,
world: &mut World,
) {
if ui.button("Save").clicked() { if ui.button("Save").clicked() {
world.send_event(EditorEvent::Save(EditorPrefabPath::MemoryCahce)); world.send_event(EditorEvent::Save(EditorPrefabPath::MemoryCahce));
} }
@@ -36,4 +42,4 @@ impl EditorTab for DebugPersistanceTab {
fn title(&self) -> bevy_inspector_egui::egui::WidgetText { fn title(&self) -> bevy_inspector_egui::egui::WidgetText {
"Persistance".into() "Persistance".into()
} }
} }
+159 -213
View File
@@ -1,19 +1,19 @@
use bevy::{ use bevy::{
asset::AssetPath, asset::{DependencyLoadState, LoadState, RecursiveDependencyLoadState},
core_pipeline::{ core_pipeline::{
bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings}, bloom::{BloomCompositeMode, BloomPrefilterSettings, BloomSettings},
fxaa::Fxaa, fxaa::Fxaa,
tonemapping::Tonemapping, tonemapping::Tonemapping,
}, },
gltf::{Gltf, GltfLoader}, gltf::Gltf,
math::{vec2, vec3}, math::vec2,
pbr::ShadowFilteringMethod, pbr::ShadowFilteringMethod,
prelude::*, prelude::*,
render::primitives::Aabb, render::primitives::Aabb,
scene::InstanceId, scene::InstanceId,
}; };
use space_editor::{prelude::{space_undo::OneFrameUndoIgnore, PrefabMarker}, space_prefab::component::{SceneAutoChild, SceneAutoRoot}}; use space_editor::{prelude::PrefabMarker, space_prefab::component::SceneAutoChild};
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::prelude::wasm_bindgen;
@@ -40,31 +40,33 @@ impl Plugin for ScenePlugin {
Update, Update,
( (
init_scene_loading, init_scene_loading,
tick_scene_loading.run_if(in_state(SceneState::Loading)),
tick_scene_spawning.run_if(in_state(SceneState::Spawning)), tick_scene_spawning.run_if(in_state(SceneState::Spawning)),
) )
.in_set(SceneSpawnerSystem), .in_set(SceneSpawnerSystem),
) )
.add_systems(
OnEnter(SceneState::Loading),
despawn_previous_scene.in_set(SceneSpawnerSystem),
)
.add_systems(
OnEnter(SceneState::Spawning),
spawn_next_scene.in_set(SceneSpawnerSystem),
)
.add_systems( .add_systems(
OnEnter(SceneState::Active), OnEnter(SceneState::Active),
( (tag_scene_elements, frame_scene_in_view).in_set(SceneSpawnerSystem),
tag_scene_elements,
spawn_main_scene_light,
frame_scene_in_view,
)
.in_set(SceneSpawnerSystem),
); );
app.add_systems(Update, tag_scene_elements); app.add_systems(Update, tag_scene_elements);
//Auto loading screen
//Register handles on which we will look to show loading screen
app.init_resource::<LoadingQueue>();
app.add_systems(
PostUpdate,
(
check_loading,
auto_add_handle::<Scene>,
auto_add_handle::<Mesh>,
auto_add_handle::<StandardMaterial>,
),
);
//setup default light
app.add_systems(Startup, minimal_scene_setup);
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
app.add_systems( app.add_systems(
Update, Update,
@@ -78,6 +80,18 @@ impl Plugin for ScenePlugin {
} }
} }
fn minimal_scene_setup(mut cmd: Commands) {
cmd.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
shadows_enabled: false,
..default()
},
transform: Transform::default().looking_at(Vec3::NEG_ONE, Vec3::Y),
..default()
})
.insert(PrefabMarker);
}
#[cfg_attr(feature = "wasm", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
#[derive(States, Clone, Copy, Default, Debug, PartialEq, Eq, Hash)] #[derive(States, Clone, Copy, Default, Debug, PartialEq, Eq, Hash)]
pub enum SceneState { pub enum SceneState {
@@ -88,9 +102,6 @@ pub enum SceneState {
Active, Active,
} }
#[derive(Resource, Deref, DerefMut)]
struct PendingScene(pub Handle<Gltf>);
#[derive(Resource, Deref)] #[derive(Resource, Deref)]
pub struct ActiveScene { pub struct ActiveScene {
#[deref] #[deref]
@@ -98,6 +109,51 @@ pub struct ActiveScene {
pub source: Handle<Gltf>, pub source: Handle<Gltf>,
} }
#[derive(Resource, Default)]
pub struct LoadingQueue {
pub queue: Vec<UntypedHandle>,
}
fn check_loading(
mut loading_queue: ResMut<LoadingQueue>,
mut st_next: ResMut<NextState<SceneState>>,
asset_server: Res<AssetServer>,
) {
if !loading_queue.queue.is_empty() {
//filter queue to only include notloaded assets
loading_queue.queue.retain(|h| {
if let Some((load_state, dep_load_state, rec_load_state)) =
asset_server.get_load_states(h.id())
{
let is_loaded = dep_load_state == DependencyLoadState::Loaded;
let is_failed = dep_load_state == DependencyLoadState::Failed
|| rec_load_state == RecursiveDependencyLoadState::Failed
|| load_state == LoadState::Failed;
!(is_failed || is_loaded)
} else {
false
}
});
info!("Loading {} assets", loading_queue.queue.len());
st_next.set(SceneState::Loading);
} else {
st_next.set(SceneState::Active);
}
}
fn auto_add_handle<T: Asset>(
mut queue: ResMut<LoadingQueue>,
query: Query<&Handle<T>, Added<Handle<T>>>,
) {
for h in query.iter() {
queue.queue.push(h.clone().untyped());
}
}
#[derive(Event, Deref)] #[derive(Event, Deref)]
pub struct LoadSceneEvent(pub String); pub struct LoadSceneEvent(pub String);
@@ -115,7 +171,6 @@ pub struct SceneData {
pub scene_path: String, pub scene_path: String,
} }
#[derive(Component)] #[derive(Component)]
pub struct SceneRoot; pub struct SceneRoot;
@@ -152,8 +207,6 @@ fn initialize(mut cmd: Commands) {
fn init_scene_loading( fn init_scene_loading(
mut cmd: Commands, mut cmd: Commands,
assets: Res<AssetServer>,
r_active_scene: Option<Res<ActiveScene>>,
mut er: EventReader<LoadSceneEvent>, mut er: EventReader<LoadSceneEvent>,
mut st_next: ResMut<NextState<SceneState>>, mut st_next: ResMut<NextState<SceneState>>,
) { ) {
@@ -168,65 +221,9 @@ fn init_scene_loading(
scene: "Scene0".to_string(), scene: "Scene0".to_string(),
}, },
PrefabMarker, PrefabMarker,
SceneRoot
));
}
}
fn despawn_previous_scene(mut cmd: Commands, q_scene_root: Query<Entity, With<SceneRoot>>) {
if let Ok(scene_root) = q_scene_root.get_single() {
cmd.entity(scene_root).despawn_recursive();
}
}
fn tick_scene_loading(
r_pending_scene: Res<PendingScene>,
ra_gltfs: Res<Assets<Gltf>>,
mut er_scene_events: EventReader<AssetEvent<Scene>>,
mut st_next: ResMut<NextState<SceneState>>,
) {
for event in er_scene_events.read() {
if let AssetEvent::LoadedWithDependencies { id } = event {
let gltf = ra_gltfs.get(&**r_pending_scene).unwrap();
if gltf.default_scene.is_some() && gltf.default_scene.as_ref().unwrap().id() == *id {
st_next.set(SceneState::Spawning);
break;
}
}
}
}
fn spawn_next_scene(
mut cmd: Commands,
ra_gltfs: Res<Assets<Gltf>>,
r_pending_scene: Res<PendingScene>,
mut r_scene_spawner: ResMut<SceneSpawner>,
) {
let gltf = ra_gltfs.get(&**r_pending_scene).unwrap();
let scene = gltf
.default_scene
.as_ref()
.expect("Expected glTF to include a default scene");
let parent = cmd
.spawn((
Name::new("Scene"),
SceneRoot, SceneRoot,
SceneElement, ));
SpatialBundle::default(), }
PrefabMarker,
OneFrameUndoIgnore::default(), //To prevert undo try to register add event
))
.id();
let instance = r_scene_spawner.spawn_as_child(scene.clone(), parent);
cmd.remove_resource::<PendingScene>();
cmd.insert_resource(ActiveScene {
instance,
source: r_pending_scene.clone(),
});
} }
fn tick_scene_spawning( fn tick_scene_spawning(
@@ -251,152 +248,101 @@ fn tag_scene_elements(
// because they often consist of stuff like a single eyeball, or just the // because they often consist of stuff like a single eyeball, or just the
// leafy parts of a plant. Here we only want to tag the elements that a user // leafy parts of a plant. Here we only want to tag the elements that a user
// might want to individually address when arranging or animating a scene. // might want to individually address when arranging or animating a scene.
q_named_non_primitives: Query<Entity, (With<SceneAutoChild>, With<Name>, Without<Handle<Mesh>>, Without<SceneElement>)>, q_named_non_primitives: Query<
Entity,
(
With<SceneAutoChild>,
With<Name>,
Without<Handle<Mesh>>,
Without<SceneElement>,
),
>,
) { ) {
for loaded_part in q_named_non_primitives.iter() { for loaded_part in q_named_non_primitives.iter() {
cmd.entity(loaded_part).insert(SceneElement); cmd.entity(loaded_part).insert(SceneElement);
} }
} }
fn spawn_main_scene_light( fn frame_scene_in_view(
mut cmd: Commands, mut cmd: Commands,
r_scene_spawner: Res<SceneSpawner>, q_aabbs: Query<(&Aabb, &GlobalTransform), With<SceneAutoChild>>,
// r_active_scene: Res<ActiveScene>, mut q_camera: Query<(&mut CameraController, &mut Transform, &Projection)>,
q_aabbs: Query<(&Aabb, &GlobalTransform)>,
q_scene_root: Query<Entity, With<SceneRoot>>,
) { ) {
let Ok(scene_root) = q_scene_root.get_single() else { let Ok((mut cam, mut cam_xform, cam_proj)) = q_camera.get_single_mut() else {
error!("Failed to get camera controller");
return; return;
}; };
// let Some(aabb) = Aabb::combine( let Some(aabb) = Aabb::combine(q_aabbs.iter()) else {
// r_scene_spawner return;
// .iter_instance_entities(**r_active_scene) };
// .filter_map(|ent| q_aabbs.get(ent).ok()),
// ) else {
// return;
// };
// let light_offset_base = vec3(0.5, 1., 1.).normalize(); let world2cam = cam_xform.compute_matrix().inverse();
// let size = f32::max( let plane_origin = Vec3::from(aabb.center);
// f32::max(aabb.half_extents.x, aabb.half_extents.y), let plane_normal = cam_xform.forward();
// aabb.half_extents.z,
// ) * 2.;
// let light_pos = Vec3::from(aabb.center) + light_offset_base * size * 2.;
// cmd.spawn(DebugPoint { let Some((_depth, bounding_rect)) = aabb
// point: light_pos, .extrema()
// color: Color::WHITE, .iter()
// }); .copied()
// cmd.entity(scene_root).with_children(|cmd| { .map(|mut p| {
// cmd.spawn(( cmd.spawn(DebugPoint {
// Name::new("Light"), point: p,
// SceneElement, color: Color::CYAN,
// SpotLightBundle { });
// spot_light: SpotLight {
// color: Color::WHITE,
// // TODO: This doesn't scale super well to very large objects
// intensity: 200. * size,
// radius: 0.1,
// shadows_enabled: true,
// shadow_normal_bias: 0.2 * size,
// outer_angle: f32::to_radians(150.),
// inner_angle: f32::to_radians(45.),
// ..default()
// },
// transform: Transform::from_translation(light_pos)
// .looking_at(aabb.center.into(), Vec3::Y),
// ..default()
// },
// ));
// });
}
fn frame_scene_in_view( // Inflate the combined AABB to give the model some breathing room
// mut cmd: Commands, p *= 1.5;
// r_scene_spawner: Res<SceneSpawner>,
// r_active_scene: Res<ActiveScene>,
// q_aabbs: Query<(&Aabb, &GlobalTransform)>,
// mut q_camera: Query<(&mut CameraController, &mut Transform, &Projection)>,
) {
// let Ok((mut cam, mut cam_xform, cam_proj)) = q_camera.get_single_mut() else {
// return;
// };
// let Some(aabb) = Aabb::combine( // Project each corner onto the camera plane
// r_scene_spawner let v = p - plane_origin;
// .iter_instance_entities(**r_active_scene) let proj = p - v.project_onto_normalized(plane_normal);
// .filter_map(|ent| q_aabbs.get(ent).ok()),
// ) else {
// return;
// };
// let world2cam = cam_xform.compute_matrix().inverse(); cmd.spawn(DebugPoint {
// let plane_origin = Vec3::from(aabb.center); point: proj,
// let plane_normal = cam_xform.forward(); color: Color::FUCHSIA,
});
// let Some((_depth, bounding_rect)) = aabb // Transform into the camera's local space
// .extrema() world2cam.transform_point(proj)
// .iter() })
// .copied() // Fold the camera-space plane-projected points into a bounding rect and view depth
// .map(|mut p| { .fold(None, |accum: Option<(f32, Rect)>, p: Vec3| match accum {
// cmd.spawn(DebugPoint { Some((depth, rect)) => Some((depth, rect.union_point(vec2(p.x, p.y)))),
// point: p, None => {
// color: Color::CYAN, let depth = p.z.abs();
// }); let p = vec2(p.x, p.y);
Some((depth, Rect::from_corners(p, p)))
}
})
else {
return;
};
// // Inflate the combined AABB to give the model some breathing room let pproj = match cam_proj {
// p *= 1.5; Projection::Perspective(p) => p,
_ => panic!("Expected a perspective projection"),
};
// // Project each corner onto the camera plane // Formula for the target camera distance
// let v = p - plane_origin; // (c/o https://stackoverflow.com/questions/2866350/move-camera-to-fit-3d-scene):
// let proj = p - v.project_onto_normalized(plane_normal); //
// d = (s/2) / tan(a/2)
// where:
// d = distance
// s = size of the largest camera-aligned axis in world coords
// a = field-of-view angle for the same axis
let Vec2 {
x: width,
y: height,
} = bounding_rect.size();
// cmd.spawn(DebugPoint { let s = f32::max(width, height);
// point: proj, let a = if s == height {
// color: Color::FUCHSIA, pproj.fov
// }); } else {
f32::atan(pproj.aspect_ratio * f32::tan(pproj.fov / 2.))
// // Transform into the camera's local space };
// world2cam.transform_point(proj)
// })
// // Fold the camera-space plane-projected points into a bounding rect and view depth
// .fold(None, |accum: Option<(f32, Rect)>, p: Vec3| match accum {
// Some((depth, rect)) => Some((depth, rect.union_point(vec2(p.x, p.y)))),
// None => {
// let depth = p.z.abs();
// let p = vec2(p.x, p.y);
// Some((depth, Rect::from_corners(p, p)))
// }
// })
// else {
// return;
// };
// let pproj = match cam_proj {
// Projection::Perspective(p) => p,
// _ => panic!("Expected a perspective projection"),
// };
// // Formula for the target camera distance
// // (c/o https://stackoverflow.com/questions/2866350/move-camera-to-fit-3d-scene):
// //
// // d = (s/2) / tan(a/2)
// // where:
// // d = distance
// // s = size of the largest camera-aligned axis in world coords
// // a = field-of-view angle for the same axis
// let Vec2 {
// x: width,
// y: height,
// } = bounding_rect.size();
// let s = f32::max(width, height);
// let a = if s == height {
// pproj.fov
// } else {
// f32::atan(pproj.aspect_ratio * f32::tan(pproj.fov / 2.))
// };
// // TODO: // // TODO:
// // According to "I eat babies" at the Ars Technica forums // // According to "I eat babies" at the Ars Technica forums
@@ -413,11 +359,11 @@ fn frame_scene_in_view(
// // // //
// // Unfortunately I'm embarrassingly bad at algebra, but there // // Unfortunately I'm embarrassingly bad at algebra, but there
// // must be some room for simplification here. // // must be some room for simplification here.
// let radius = (s / 2.) / f32::tan(a / 2.); let radius = (s / 2.) / f32::tan(a / 2.);
// cam.focus = aabb.center.into(); cam.focus = aabb.center.into();
// cam.radius = radius; cam.radius = radius;
// cam_xform.translation = cam.focus + cam_xform.back() * radius; cam_xform.translation = cam.focus + cam_xform.back() * radius;
} }
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]