Successfull export/clear/importgit add .; git commit Tadagit add .; git commit
parent
5952ee5608
commit
0e643965f4
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,108 @@
|
||||
(
|
||||
resources: {},
|
||||
entities: {
|
||||
4: (
|
||||
components: {
|
||||
"bevy_transform::components::transform::Transform": (
|
||||
translation: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
rotation: (0.0, 0.0, 0.0, 1.0),
|
||||
scale: (
|
||||
x: 1.0,
|
||||
y: 1.0,
|
||||
z: 1.0,
|
||||
),
|
||||
),
|
||||
"bevy_transform::components::global_transform::GlobalTransform": ((
|
||||
matrix3: (
|
||||
x_axis: (
|
||||
x: 1.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
y_axis: (
|
||||
x: 0.0,
|
||||
y: 1.0,
|
||||
z: 0.0,
|
||||
),
|
||||
z_axis: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 1.0,
|
||||
),
|
||||
),
|
||||
translation: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
)),
|
||||
"bevy_render::view::visibility::Visibility": Inherited,
|
||||
"bevy_hierarchy::components::children::Children": ([
|
||||
5,
|
||||
6,
|
||||
]),
|
||||
},
|
||||
),
|
||||
5: (
|
||||
components: {
|
||||
"bevy_hierarchy::components::parent::Parent": (4),
|
||||
"bevy_asset::handle::Handle<bevy_audio::audio_source::AudioSource>": (
|
||||
id: AssetPathId(((5718828327369153735), (8823233378563626002))),
|
||||
),
|
||||
},
|
||||
),
|
||||
6: (
|
||||
components: {
|
||||
"bevy_transform::components::transform::Transform": (
|
||||
translation: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
rotation: (0.0, 0.0, 0.0, 1.0),
|
||||
scale: (
|
||||
x: 1.0,
|
||||
y: 1.0,
|
||||
z: 1.0,
|
||||
),
|
||||
),
|
||||
"bevy_transform::components::global_transform::GlobalTransform": ((
|
||||
matrix3: (
|
||||
x_axis: (
|
||||
x: 1.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
y_axis: (
|
||||
x: 0.0,
|
||||
y: 1.0,
|
||||
z: 0.0,
|
||||
),
|
||||
z_axis: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 1.0,
|
||||
),
|
||||
),
|
||||
translation: (
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
z: 0.0,
|
||||
),
|
||||
)),
|
||||
"bevy_render::view::visibility::Visibility": Inherited,
|
||||
"bevy_hierarchy::components::parent::Parent": (4),
|
||||
"bevy_hierarchy::components::children::Children": ([
|
||||
16,
|
||||
]),
|
||||
"bevy_asset::handle::Handle<bevy_scene::scene::Scene>": (
|
||||
id: AssetPathId(((8329447081204006281), (13531267934229906755))),
|
||||
),
|
||||
},
|
||||
),
|
||||
},
|
||||
)
|
||||
@ -0,0 +1,297 @@
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
use bevy::{audio::PlaybackMode, prelude::*, tasks::IoTaskPool};
|
||||
use monologue_trees::{debug::*, ui};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.init_resource::<AssetRegistry>()
|
||||
.add_plugins((
|
||||
DefaultPlugins.set(WindowPlugin {
|
||||
primary_window: Some(Window {
|
||||
title: "Serialization WTF".into(),
|
||||
resolution: (640., 480.).into(),
|
||||
..default()
|
||||
}),
|
||||
..default()
|
||||
}),
|
||||
DebugInfoPlugin,
|
||||
ui::GameUiPlugin { ..default() },
|
||||
))
|
||||
.add_systems(Startup, init)
|
||||
.add_systems(
|
||||
Update,
|
||||
(
|
||||
export.run_if(interaction_condition::<ExportAction>),
|
||||
clear.run_if(interaction_condition::<ClearAction>),
|
||||
import.run_if(interaction_condition::<ImportAction>),
|
||||
rehydrate::<Visibility, ComputedVisibility>,
|
||||
rehydrate::<Handle<AudioSource>, PlaybackSettings>,
|
||||
inspect.run_if(interaction_condition::<InspectAction>),
|
||||
fallback_camera.run_if(fallback_camera_condition),
|
||||
),
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[derive(Debug, Component, Reflect, Default)]
|
||||
#[reflect(Component)]
|
||||
struct LevelRoot;
|
||||
|
||||
#[derive(Debug, Component)]
|
||||
struct ExportAction;
|
||||
|
||||
#[derive(Debug, Component)]
|
||||
struct ClearAction;
|
||||
|
||||
#[derive(Debug, Component)]
|
||||
struct ImportAction;
|
||||
|
||||
#[derive(Debug, Component)]
|
||||
struct InspectAction;
|
||||
|
||||
#[derive(Debug, Resource, Default)]
|
||||
struct AssetRegistry {
|
||||
handles: Vec<HandleUntyped>,
|
||||
}
|
||||
|
||||
fn init(server: Res<AssetServer>, mut commands: Commands, mut registry: ResMut<AssetRegistry>) {
|
||||
commands.spawn((
|
||||
Camera2dBundle { ..default() },
|
||||
UiCameraConfig { show_ui: true },
|
||||
));
|
||||
|
||||
let audio_handle: Handle<AudioSource> = server.load("audio/Ambient/Lake Sound 1.ogg");
|
||||
let scene_handle: Handle<Scene> = server.load("models/materials.glb#Scene0");
|
||||
commands
|
||||
.spawn((SpatialBundle { ..default() }, LevelRoot))
|
||||
.with_children(|parent| {
|
||||
parent.spawn(AudioSourceBundle {
|
||||
source: audio_handle.clone(),
|
||||
settings: PlaybackSettings {
|
||||
mode: PlaybackMode::Loop,
|
||||
paused: false,
|
||||
..default()
|
||||
},
|
||||
});
|
||||
parent.spawn((SceneBundle {
|
||||
scene: scene_handle.clone(),
|
||||
..default()
|
||||
},));
|
||||
});
|
||||
registry.handles.push(audio_handle.clone_untyped());
|
||||
registry.handles.push(scene_handle.clone_untyped());
|
||||
|
||||
commands
|
||||
.spawn((
|
||||
NodeBundle {
|
||||
style: Style {
|
||||
top: Val::Px(0.0),
|
||||
right: Val::Px(0.0),
|
||||
margin: UiRect::all(Val::Px(5.0)),
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
border: UiRect::all(Val::Px(1.0)),
|
||||
position_type: PositionType::Absolute,
|
||||
..default()
|
||||
},
|
||||
background_color: Color::WHITE.into(),
|
||||
border_color: Color::BLACK.into(),
|
||||
..default()
|
||||
},
|
||||
ui::Select::Action,
|
||||
))
|
||||
.with_children(|parent| {
|
||||
parent.spawn((
|
||||
ButtonBundle {
|
||||
style: Style {
|
||||
margin: UiRect::all(Val::Px(5.0)),
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
border: UiRect::all(Val::Px(1.0)),
|
||||
..default()
|
||||
},
|
||||
border_color: Color::BLACK.into(),
|
||||
..default()
|
||||
},
|
||||
ui::Title {
|
||||
text: "Export".into(),
|
||||
..default()
|
||||
},
|
||||
ExportAction,
|
||||
));
|
||||
parent.spawn((
|
||||
ButtonBundle {
|
||||
style: Style {
|
||||
margin: UiRect::all(Val::Px(5.0)),
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
border: UiRect::all(Val::Px(1.0)),
|
||||
..default()
|
||||
},
|
||||
border_color: Color::BLACK.into(),
|
||||
..default()
|
||||
},
|
||||
ui::Title {
|
||||
text: "Clear".into(),
|
||||
..default()
|
||||
},
|
||||
ClearAction,
|
||||
));
|
||||
parent.spawn((
|
||||
ButtonBundle {
|
||||
style: Style {
|
||||
margin: UiRect::all(Val::Px(5.0)),
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
border: UiRect::all(Val::Px(1.0)),
|
||||
..default()
|
||||
},
|
||||
border_color: Color::BLACK.into(),
|
||||
..default()
|
||||
},
|
||||
ui::Title {
|
||||
text: "Import".into(),
|
||||
..default()
|
||||
},
|
||||
ImportAction,
|
||||
));
|
||||
parent.spawn((
|
||||
ButtonBundle {
|
||||
style: Style {
|
||||
margin: UiRect::all(Val::Px(5.0)),
|
||||
padding: UiRect::all(Val::Px(5.0)),
|
||||
border: UiRect::all(Val::Px(1.0)),
|
||||
..default()
|
||||
},
|
||||
border_color: Color::BLACK.into(),
|
||||
..default()
|
||||
},
|
||||
ui::Title {
|
||||
text: "Inspect".into(),
|
||||
..default()
|
||||
},
|
||||
InspectAction,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
fn interaction_condition<T: Component>(
|
||||
events: Query<&Interaction, (Changed<Interaction>, With<T>)>,
|
||||
) -> bool {
|
||||
events
|
||||
.iter()
|
||||
.find(|&interaction| *interaction == Interaction::Pressed)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn rehydrate<W: Component, WO: Component + Default + std::fmt::Debug>(
|
||||
events: Query<Entity, (Added<W>, Without<WO>)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
events.iter().for_each(|entity| {
|
||||
info!("Rehydrating {:?}", WO::default());
|
||||
commands.entity(entity).insert(WO::default());
|
||||
});
|
||||
}
|
||||
|
||||
fn ser(
|
||||
root: &Query<Entity, With<LevelRoot>>,
|
||||
children: &Query<&Children>,
|
||||
world: &World,
|
||||
) -> String {
|
||||
let app_type_registry = world.resource::<AppTypeRegistry>().clone();
|
||||
let mut builder = DynamicSceneBuilder::from_world(world.clone());
|
||||
|
||||
builder.deny_all_resources();
|
||||
|
||||
// builder.allow_all();
|
||||
builder.deny::<ComputedVisibility>();
|
||||
|
||||
// Level administrivia
|
||||
builder.allow::<LevelRoot>();
|
||||
|
||||
// Scene components
|
||||
builder.allow::<Handle<Scene>>();
|
||||
builder.allow::<Visibility>();
|
||||
builder.allow::<Transform>();
|
||||
builder.allow::<GlobalTransform>();
|
||||
|
||||
// Audio components
|
||||
builder.allow::<Handle<AudioSource>>();
|
||||
builder.allow::<PlaybackSettings>();
|
||||
|
||||
root.iter().for_each(|r| {
|
||||
// Extract the level root
|
||||
builder.extract_entity(r);
|
||||
|
||||
// Extract all level root children
|
||||
builder.extract_entities(
|
||||
children
|
||||
.get(r)
|
||||
.expect("Root has children")
|
||||
.iter()
|
||||
.map(|&entity| entity),
|
||||
);
|
||||
});
|
||||
|
||||
let scene = builder.build();
|
||||
|
||||
scene
|
||||
.serialize_ron(&app_type_registry)
|
||||
.expect("Serialize scene")
|
||||
}
|
||||
|
||||
fn export(root: Query<Entity, With<LevelRoot>>, children: Query<&Children>, world: &World) {
|
||||
info!("Export level");
|
||||
|
||||
let serialized = ser(&root, &children, world);
|
||||
|
||||
IoTaskPool::get()
|
||||
.spawn(async move {
|
||||
// Write the scene RON data to file
|
||||
File::create(format!("assets/output.scn.ron"))
|
||||
.and_then(|mut file| file.write(serialized.as_bytes()))
|
||||
.expect("Error while writing scene to file");
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn inspect(root: Query<Entity, With<LevelRoot>>, children: Query<&Children>, world: &World) {
|
||||
info!("Inexpect level");
|
||||
|
||||
let serialized = ser(&root, &children, world);
|
||||
|
||||
print!("{}", serialized);
|
||||
}
|
||||
|
||||
fn clear(root: Query<Entity, With<LevelRoot>>, mut commands: Commands) {
|
||||
info!("Clearing level");
|
||||
|
||||
root.iter().for_each(|entity| {
|
||||
commands.entity(entity).despawn_recursive();
|
||||
});
|
||||
}
|
||||
|
||||
fn import(mut commands: Commands, server: Res<AssetServer>) {
|
||||
info!("Importing level");
|
||||
|
||||
let scene_handle: Handle<DynamicScene> = server.load("output.scn.ron");
|
||||
commands.spawn((
|
||||
LevelRoot,
|
||||
DynamicSceneBundle {
|
||||
scene: scene_handle.clone(),
|
||||
..default()
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
fn fallback_camera_condition(
|
||||
added: Query<Entity, Added<Camera>>,
|
||||
mut removed: RemovedComponents<Camera>,
|
||||
) -> bool {
|
||||
added.iter().chain(removed.iter()).count() > 0
|
||||
}
|
||||
|
||||
fn fallback_camera(
|
||||
mut ui_camera: Query<&mut Camera, With<Camera2d>>,
|
||||
cameras: Query<&mut Camera, Without<Camera2d>>,
|
||||
) {
|
||||
ui_camera.single_mut().is_active = cameras.iter().len() <= 0;
|
||||
}
|
||||
Loading…
Reference in New Issue