Compare commits
4 Commits
e54d41ca5c
...
4a72ed68bf
Author | SHA1 | Date |
---|---|---|
kaosat.dev | 4a72ed68bf | |
kaosat.dev | 16a28ab760 | |
kaosat.dev | a951d82330 | |
kaosat.dev | 382759d71f |
16
TODO.md
16
TODO.md
|
@ -62,7 +62,7 @@ Components:
|
||||||
- [x] Hashmap Support
|
- [x] Hashmap Support
|
||||||
- [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side
|
- [x] fix parsing of keys's type either on Bevy side (prefered) or on the Blender side
|
||||||
- [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set
|
- [x] fix weird issue with missing "0" property when adding new entry in empty hashmap => happens only if the values for the "setter" have never been set
|
||||||
- [ ] handle missing types in registry for keys & values
|
- [x] handle missing types in registry for keys & values
|
||||||
- [x] adding a hashmap nukes every existing component ??
|
- [x] adding a hashmap nukes every existing component ??
|
||||||
- [x] Add correct upgrade handling from individual component to bevy_components
|
- [x] Add correct upgrade handling from individual component to bevy_components
|
||||||
- [x] Settings handling:
|
- [x] Settings handling:
|
||||||
|
@ -218,6 +218,11 @@ Blender side:
|
||||||
|
|
||||||
- [ ] add option to 'split out' meshes from blueprints ?
|
- [ ] add option to 'split out' meshes from blueprints ?
|
||||||
- [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs
|
- [ ] ie considering meshletts etc , it would make sense to keep blueprints seperate from purely mesh gltfs
|
||||||
|
|
||||||
|
- [ ] materials fixes & upgrades
|
||||||
|
- [x] materials do not get exported again if the files are missing, until you change a material
|
||||||
|
- [x] materials do not get exported when a material is added ?
|
||||||
|
- [ ] material assets seem to be added to list regardless of whether material exports are enabled or not
|
||||||
- [ ] persist exported materials path in blueprints so that it can be read from library file users
|
- [ ] persist exported materials path in blueprints so that it can be read from library file users
|
||||||
- [ ] just like "export_path" write it into each blueprint's collection
|
- [ ] just like "export_path" write it into each blueprint's collection
|
||||||
- [ ] scan for used materials per blueprint !
|
- [ ] scan for used materials per blueprint !
|
||||||
|
@ -284,7 +289,7 @@ Bevy Side:
|
||||||
- [x] for sub blueprint tracking: do not propagate/ deal with parent blueprints if they are not themselves Spawning (ie filter out by "BlueprintSpawning")
|
- [x] for sub blueprint tracking: do not propagate/ deal with parent blueprints if they are not themselves Spawning (ie filter out by "BlueprintSpawning")
|
||||||
- [x] cleanup internals
|
- [x] cleanup internals
|
||||||
- [ ] analyse what is off with blueprint level components
|
- [ ] analyse what is off with blueprint level components
|
||||||
- [ ] add the root blueprint itself to the assets either on the blender side or on the bevy side programatically
|
- [x] add the root blueprint itself to the assets either on the blender side or on the bevy side programatically
|
||||||
- [ ] invalidate despawned entity & parent entities AABB
|
- [ ] invalidate despawned entity & parent entities AABB
|
||||||
- [ ] add unloading/cache removal of materials
|
- [ ] add unloading/cache removal of materials
|
||||||
|
|
||||||
|
@ -316,6 +321,11 @@ Bevy Side:
|
||||||
- [x] replace all references to the old 2 add-ons with those to Blenvy
|
- [x] replace all references to the old 2 add-ons with those to Blenvy
|
||||||
- [x] rename repo to "Blenvy"
|
- [x] rename repo to "Blenvy"
|
||||||
- [x] do a deprecation release of all bevy_gltf_xxx crates to point at the new Blenvy crate
|
- [x] do a deprecation release of all bevy_gltf_xxx crates to point at the new Blenvy crate
|
||||||
- [ ] material assets seem to be added to list regardless of whether material exports are enabled or not
|
- [ ] consider finding a way of having unique ids for all objects & collections in Blender (not trivial, if not impossible)
|
||||||
|
this would allow things such as
|
||||||
|
- [ ] mapping uuids to blueprint paths
|
||||||
|
- [ ] solving problems with scene renames
|
||||||
|
- [ ] the ability to map external TEXT files to data in BLender (git-able, hand editable)
|
||||||
|
- [x] make aabbs calculation non configurable, getting rid of the last setting (for now)
|
||||||
|
|
||||||
clear && pytest -svv --blender-template ../../testing/bevy_example/art/testing_library.blend --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration_prepare.py && pytest -svv --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration.py
|
clear && pytest -svv --blender-template ../../testing/bevy_example/art/testing_library.blend --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration_prepare.py && pytest -svv --blender-executable /home/ckaos/tools/blender/blender-4.1.0-linux-x64/blender tests/test_bevy_integration.py
|
|
@ -14,7 +14,7 @@ license = "MIT OR Apache-2.0"
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.14", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf", "file_watcher"] }
|
bevy = { version = "0.14", default-features = false, features = ["bevy_asset", "bevy_scene", "bevy_gltf"] } #, "file_watcher"
|
||||||
serde = "1.0.188"
|
serde = "1.0.188"
|
||||||
ron = "0.8.1"
|
ron = "0.8.1"
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
|
|
|
@ -37,8 +37,7 @@ pub fn compute_scene_aabbs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for entity in other_entities.iter() {
|
for entity in other_entities.iter() {
|
||||||
println!("already got AABB");
|
commands.entity(entity).insert(BlueprintReadyForFinalizing);
|
||||||
commands.entity(entity).insert(BlueprintReadyForFinalizing); // FIXME ! Yikes !!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,10 +87,14 @@ pub struct AnimationMarkerReached {
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
|
|
||||||
/// triggers events when a given animation marker is reached for BLUEPRINT animations
|
/// triggers events when a given animation marker is reached for BLUEPRINT animations
|
||||||
pub fn trigger_blueprint_animation_markers_events(
|
pub fn trigger_blueprint_animation_markers_events(
|
||||||
animation_data: Query<(Entity, &BlueprintAnimationPlayerLink, &BlueprintAnimationInfosLink, &BlueprintAnimations)>,
|
animation_data: Query<(
|
||||||
|
Entity,
|
||||||
|
&BlueprintAnimationPlayerLink,
|
||||||
|
&BlueprintAnimationInfosLink,
|
||||||
|
&BlueprintAnimations,
|
||||||
|
)>,
|
||||||
// FIXME: annoying hiearchy issue yet again: the Markers & AnimationInfos are stored INSIDE the blueprint, so we need to access them differently
|
// FIXME: annoying hiearchy issue yet again: the Markers & AnimationInfos are stored INSIDE the blueprint, so we need to access them differently
|
||||||
animation_infos: Query<(&AnimationInfos, &AnimationMarkers)>,
|
animation_infos: Query<(&AnimationInfos, &AnimationMarkers)>,
|
||||||
animation_players: Query<&AnimationPlayer>,
|
animation_players: Query<&AnimationPlayer>,
|
||||||
|
@ -99,9 +103,7 @@ pub fn trigger_blueprint_animation_markers_events(
|
||||||
animation_clips: Res<Assets<AnimationClip>>,
|
animation_clips: Res<Assets<AnimationClip>>,
|
||||||
) {
|
) {
|
||||||
for (entity, player_link, infos_link, animations) in animation_data.iter() {
|
for (entity, player_link, infos_link, animations) in animation_data.iter() {
|
||||||
|
|
||||||
for (animation_name, node_index) in animations.named_indices.iter() {
|
for (animation_name, node_index) in animations.named_indices.iter() {
|
||||||
|
|
||||||
let animation_player = animation_players.get(player_link.0).unwrap();
|
let animation_player = animation_players.get(player_link.0).unwrap();
|
||||||
let (animation_infos, animation_markers) = animation_infos.get(infos_link.0).unwrap();
|
let (animation_infos, animation_markers) = animation_infos.get(infos_link.0).unwrap();
|
||||||
|
|
||||||
|
@ -109,21 +111,24 @@ pub fn trigger_blueprint_animation_markers_events(
|
||||||
if let Some(animation) = animation_player.animation(*node_index) {
|
if let Some(animation) = animation_player.animation(*node_index) {
|
||||||
// animation.speed()
|
// animation.speed()
|
||||||
// animation.completions()
|
// animation.completions()
|
||||||
if let Some(animation_clip_handle) = animations.named_animations.get(animation_name) {
|
if let Some(animation_clip_handle) =
|
||||||
|
animations.named_animations.get(animation_name)
|
||||||
|
{
|
||||||
if let Some(animation_clip) = animation_clips.get(animation_clip_handle) {
|
if let Some(animation_clip) = animation_clips.get(animation_clip_handle) {
|
||||||
let animation_length_seconds = animation_clip.duration();
|
let animation_length_seconds = animation_clip.duration();
|
||||||
let animation_length_frames = animation_infos // FIXME: horribly inneficient
|
let animation_length_frames =
|
||||||
|
animation_infos // FIXME: horribly inneficient
|
||||||
.animations
|
.animations
|
||||||
.iter()
|
.iter()
|
||||||
.find(|anim| &anim.name == animation_name)
|
.find(|anim| &anim.name == animation_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.frames_length;
|
.frames_length;
|
||||||
|
|
||||||
|
|
||||||
// TODO: we also need to take playback speed into account
|
// TODO: we also need to take playback speed into account
|
||||||
let time_in_animation = animation.elapsed()
|
let time_in_animation = animation.elapsed()
|
||||||
- (animation.completions() as f32) * animation_length_seconds;
|
- (animation.completions() as f32) * animation_length_seconds;
|
||||||
let frame_seconds = (animation_length_frames / animation_length_seconds)
|
let frame_seconds = (animation_length_frames
|
||||||
|
/ animation_length_seconds)
|
||||||
* time_in_animation;
|
* time_in_animation;
|
||||||
// println!("frame seconds {}", frame_seconds);
|
// println!("frame seconds {}", frame_seconds);
|
||||||
let frame = frame_seconds.ceil() as u32; // FIXME , bad hack
|
let frame = frame_seconds.ceil() as u32; // FIXME , bad hack
|
||||||
|
@ -133,7 +138,10 @@ pub fn trigger_blueprint_animation_markers_events(
|
||||||
if matching_animation_marker.contains_key(&frame) {
|
if matching_animation_marker.contains_key(&frame) {
|
||||||
let matching_markers_per_frame =
|
let matching_markers_per_frame =
|
||||||
matching_animation_marker.get(&frame).unwrap();
|
matching_animation_marker.get(&frame).unwrap();
|
||||||
println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame);
|
println!(
|
||||||
|
"FOUND A MARKER {:?} at frame {}",
|
||||||
|
matching_markers_per_frame, frame
|
||||||
|
);
|
||||||
// FIXME: complete hack-ish solution , otherwise this can fire multiple times in a row, depending on animation length , speed , etc
|
// FIXME: complete hack-ish solution , otherwise this can fire multiple times in a row, depending on animation length , speed , etc
|
||||||
let diff = frame as f32 - frame_seconds;
|
let diff = frame as f32 - frame_seconds;
|
||||||
if diff < 0.1 {
|
if diff < 0.1 {
|
||||||
|
@ -155,7 +163,6 @@ pub fn trigger_blueprint_animation_markers_events(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// triggers events when a given animation marker is reached for INSTANCE animations
|
/// triggers events when a given animation marker is reached for INSTANCE animations
|
||||||
pub fn trigger_instance_animation_markers_events(
|
pub fn trigger_instance_animation_markers_events(
|
||||||
animation_infos: Query<(
|
animation_infos: Query<(
|
||||||
|
@ -178,9 +185,10 @@ pub fn trigger_instance_animation_markers_events(
|
||||||
let animation_player = animation_players.get(player_link.0).unwrap();
|
let animation_player = animation_players.get(player_link.0).unwrap();
|
||||||
if animation_player.animation_is_playing(*node_index) {
|
if animation_player.animation_is_playing(*node_index) {
|
||||||
if let Some(animation) = animation_player.animation(*node_index) {
|
if let Some(animation) = animation_player.animation(*node_index) {
|
||||||
if let Some(animation_clip_handle) = animations.named_animations.get(animation_name) {
|
if let Some(animation_clip_handle) =
|
||||||
|
animations.named_animations.get(animation_name)
|
||||||
|
{
|
||||||
if let Some(animation_clip) = animation_clips.get(animation_clip_handle) {
|
if let Some(animation_clip) = animation_clips.get(animation_clip_handle) {
|
||||||
|
|
||||||
println!("helooo")
|
println!("helooo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ pub struct BlueprintAllAssets {
|
||||||
pub assets: Vec<BlueprintAsset>,
|
pub assets: Vec<BlueprintAsset>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
///
|
///
|
||||||
/// flag component, usually added when a blueprint is loaded
|
/// flag component, usually added when a blueprint is loaded
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
use crate::{BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintInfo, BlueprintInstanceReady, BlueprintSpawning, FromBlueprint, SpawnBlueprint, SubBlueprintsSpawnTracker};
|
use crate::{
|
||||||
|
BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintInfo, BlueprintInstanceReady,
|
||||||
|
BlueprintSpawning, FromBlueprint, SpawnBlueprint, SubBlueprintsSpawnTracker,
|
||||||
|
};
|
||||||
use bevy::asset::AssetEvent;
|
use bevy::asset::AssetEvent;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::scene::SceneInstance;
|
use bevy::scene::SceneInstance;
|
||||||
use bevy::utils::hashbrown::HashMap;
|
use bevy::utils::hashbrown::HashMap;
|
||||||
|
|
||||||
|
|
||||||
/// Resource mapping asset paths (ideally untyped ids, but more complex) to a list of blueprint instance entity ids
|
/// Resource mapping asset paths (ideally untyped ids, but more complex) to a list of blueprint instance entity ids
|
||||||
#[derive(Debug, Clone, Resource, Default)]
|
#[derive(Debug, Clone, Resource, Default)]
|
||||||
pub(crate) struct AssetToBlueprintInstancesMapper {
|
pub(crate) struct AssetToBlueprintInstancesMapper {
|
||||||
// pub(crate) untyped_id_to_blueprint_entity_ids: HashMap<UntypedAssetId, Vec<Entity>>
|
// pub(crate) untyped_id_to_blueprint_entity_ids: HashMap<UntypedAssetId, Vec<Entity>>
|
||||||
pub(crate) untyped_id_to_blueprint_entity_ids: HashMap<String, Vec<Entity>>
|
pub(crate) untyped_id_to_blueprint_entity_ids: HashMap<String, Vec<Entity>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn react_to_asset_changes(
|
pub(crate) fn react_to_asset_changes(
|
||||||
mut gltf_events: EventReader<AssetEvent<Gltf>>, // FIXME: Problem: we need to react to any asset change, not just gltf files !
|
mut gltf_events: EventReader<AssetEvent<Gltf>>, // FIXME: Problem: we need to react to any asset change, not just gltf files !
|
||||||
// mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
// mut untyped_events: EventReader<AssetEvent<LoadedUntypedAsset>>,
|
||||||
blueprint_assets: Query<(
|
blueprint_assets: Query<(Entity, Option<&Name>, &BlueprintInfo, Option<&Children>)>,
|
||||||
Entity,
|
|
||||||
Option<&Name>,
|
|
||||||
&BlueprintInfo,
|
|
||||||
Option<&Children>,
|
|
||||||
)>,
|
|
||||||
blueprint_children_entities: Query<&FromBlueprint>, //=> can only be used if the entites are tagged
|
blueprint_children_entities: Query<&FromBlueprint>, //=> can only be used if the entites are tagged
|
||||||
assets_to_blueprint_instances: Res<AssetToBlueprintInstancesMapper>,
|
assets_to_blueprint_instances: Res<AssetToBlueprintInstancesMapper>,
|
||||||
all_parents: Query<&Parent>,
|
all_parents: Query<&Parent>,
|
||||||
|
@ -28,7 +25,6 @@ pub(crate) fn react_to_asset_changes(
|
||||||
|
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
let mut respawn_candidates: Vec<&Entity> = vec![];
|
let mut respawn_candidates: Vec<&Entity> = vec![];
|
||||||
|
|
||||||
|
@ -44,15 +40,19 @@ pub(crate) fn react_to_asset_changes(
|
||||||
// let bla = untyped.unwrap().id();
|
// let bla = untyped.unwrap().id();
|
||||||
// asset_server.get
|
// asset_server.get
|
||||||
// in order to avoid respawn both a parent & a child , which would crash Bevy, we do things in two steps
|
// in order to avoid respawn both a parent & a child , which would crash Bevy, we do things in two steps
|
||||||
if let Some(entities) = assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.get(&asset_path.to_string()) {
|
if let Some(entities) = assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.get(&asset_path.to_string())
|
||||||
|
{
|
||||||
for entity in entities.iter() {
|
for entity in entities.iter() {
|
||||||
println!("matching blueprint instance {}", entity);
|
// println!("matching blueprint instance {}", entity);
|
||||||
// disregard entities that are already (re) spawning
|
// disregard entities that are already (re) spawning
|
||||||
if !respawn_candidates.contains(&entity) && blueprint_assets.get(*entity).is_ok() && spawning_blueprints.get(*entity).is_err()
|
if !respawn_candidates.contains(&entity)
|
||||||
|
&& blueprint_assets.get(*entity).is_ok()
|
||||||
|
&& spawning_blueprints.get(*entity).is_err()
|
||||||
{
|
{
|
||||||
respawn_candidates.push(entity);
|
respawn_candidates.push(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,10 +81,12 @@ pub(crate) fn react_to_asset_changes(
|
||||||
}
|
}
|
||||||
// println!("respawn candidates {:?}", respawn_candidates);
|
// println!("respawn candidates {:?}", respawn_candidates);
|
||||||
for retained in retained_candidates.iter() {
|
for retained in retained_candidates.iter() {
|
||||||
println!("retained {}", retained);
|
// println!("retained {}", retained);
|
||||||
|
|
||||||
if let Ok((entity, entity_name, _blueprint_info, children)) = blueprint_assets.get(*retained) {
|
if let Ok((entity, entity_name, _blueprint_info, children)) =
|
||||||
println!("HOLY MOLY IT DETECTS !!, now respawn {:?}", entity_name);
|
blueprint_assets.get(*retained)
|
||||||
|
{
|
||||||
|
info!("Change detected !!, now respawn {:?}", entity_name);
|
||||||
|
|
||||||
// TODO: only remove those that are "in blueprint"
|
// TODO: only remove those that are "in blueprint"
|
||||||
if children.is_some() {
|
if children.is_some() {
|
||||||
|
|
|
@ -53,7 +53,12 @@ pub(crate) fn inject_materials(
|
||||||
material_found = Some(material);
|
material_found = Some(material);
|
||||||
} else {
|
} else {
|
||||||
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
let model_handle: Handle<Gltf> = asset_server.load(material_info.path.clone()); // FIXME: kinda weird now
|
||||||
let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| panic!("materials file {} should have been preloaded", material_info.path));
|
let mat_gltf = assets_gltf.get(model_handle.id()).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"materials file {} should have been preloaded",
|
||||||
|
material_info.path
|
||||||
|
)
|
||||||
|
});
|
||||||
if mat_gltf
|
if mat_gltf
|
||||||
.named_materials
|
.named_materials
|
||||||
.contains_key(&material_info.name as &str)
|
.contains_key(&material_info.name as &str)
|
||||||
|
|
|
@ -50,19 +50,14 @@ impl Default for BluePrintBundle {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
/// Plugin for gltf blueprints
|
/// Plugin for gltf blueprints
|
||||||
pub struct BlueprintsPlugin {
|
pub struct BlueprintsPlugin {
|
||||||
/// Automatically generate aabbs for the blueprints root objects
|
|
||||||
pub aabbs: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BlueprintsPlugin {
|
impl Default for BlueprintsPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { aabbs: false }
|
Self { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn aabbs_enabled(blenvy_config: Res<BlenvyConfig>) -> bool {
|
|
||||||
blenvy_config.aabbs
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
|
fn hot_reload(watching_for_changes: Res<WatchingForChanges>) -> bool {
|
||||||
// println!("hot reload ? {}", watching_for_changes.0);
|
// println!("hot reload ? {}", watching_for_changes.0);
|
||||||
|
@ -131,7 +126,7 @@ impl Plugin for BlueprintsPlugin {
|
||||||
blueprints_cleanup_spawned_scene,
|
blueprints_cleanup_spawned_scene,
|
||||||
// beyond this point : post processing to finalize blueprint instances
|
// beyond this point : post processing to finalize blueprint instances
|
||||||
inject_materials,
|
inject_materials,
|
||||||
compute_scene_aabbs, // .run_if(aabbs_enabled),
|
compute_scene_aabbs,
|
||||||
blueprints_finalize_instances,
|
blueprints_finalize_instances,
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
|
|
|
@ -4,7 +4,10 @@ use bevy::{gltf::Gltf, prelude::*, scene::SceneInstance, utils::hashbrown::HashM
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlenvyConfig, BlueprintAnimationInfosLink, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState, BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, InstanceAnimationInfosLink, InstanceAnimationPlayerLink, InstanceAnimations, WatchingForChanges
|
AnimationInfos, AssetLoadTracker, AssetToBlueprintInstancesMapper, BlueprintAnimationInfosLink,
|
||||||
|
BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintAssets, BlueprintAssetsLoadState,
|
||||||
|
BlueprintAssetsLoaded, BlueprintAssetsNotLoaded, InstanceAnimationInfosLink,
|
||||||
|
InstanceAnimationPlayerLink, InstanceAnimations, WatchingForChanges,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// this is a flag component for our levels/game world
|
/// this is a flag component for our levels/game world
|
||||||
|
@ -89,7 +92,6 @@ pub enum BlueprintEvent {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Component, Reflect, Debug, Default)]
|
#[derive(Component, Reflect, Debug, Default)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
/// component gets added when a blueprint starts spawning, removed when spawning is completely done
|
/// component gets added when a blueprint starts spawning, removed when spawning is completely done
|
||||||
|
@ -97,7 +99,6 @@ pub struct BlueprintSpawning;
|
||||||
|
|
||||||
use gltf::Gltf as RawGltf;
|
use gltf::Gltf as RawGltf;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Overview of the Blueprint Spawning process
|
Overview of the Blueprint Spawning process
|
||||||
- Blueprint Load Assets
|
- Blueprint Load Assets
|
||||||
|
@ -115,10 +116,7 @@ Overview of the Blueprint Spawning process
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub(crate) fn blueprints_prepare_spawn(
|
pub(crate) fn blueprints_prepare_spawn(
|
||||||
blueprint_instances_to_spawn: Query<
|
blueprint_instances_to_spawn: Query<(Entity, &BlueprintInfo), Added<SpawnBlueprint>>,
|
||||||
(Entity, &BlueprintInfo),
|
|
||||||
Added<SpawnBlueprint>,
|
|
||||||
>,
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
// for hot reload
|
// for hot reload
|
||||||
|
@ -153,9 +151,9 @@ pub(crate) fn blueprints_prepare_spawn(
|
||||||
/* prefetch attempt */
|
/* prefetch attempt */
|
||||||
let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap();
|
let gltf = RawGltf::open(format!("assets/{}", blueprint_info.path)).unwrap();
|
||||||
for scene in gltf.scenes() {
|
for scene in gltf.scenes() {
|
||||||
if let Some(scene_extras) = scene.extras().clone()
|
if let Some(scene_extras) = scene.extras().clone() {
|
||||||
{
|
let lookup: HashMap<String, Value> =
|
||||||
let lookup: HashMap<String, Value> = serde_json::from_str(scene_extras.get()).unwrap();
|
serde_json::from_str(scene_extras.get()).unwrap();
|
||||||
if lookup.contains_key("BlueprintAssets") {
|
if lookup.contains_key("BlueprintAssets") {
|
||||||
let assets_raw = &lookup["BlueprintAssets"];
|
let assets_raw = &lookup["BlueprintAssets"];
|
||||||
//println!("ASSETS RAW {}", assets_raw);
|
//println!("ASSETS RAW {}", assets_raw);
|
||||||
|
@ -183,18 +181,56 @@ pub(crate) fn blueprints_prepare_spawn(
|
||||||
|
|
||||||
// Only do this if hot reload is enabled
|
// Only do this if hot reload is enabled
|
||||||
if watching_for_changes.0 {
|
if watching_for_changes.0 {
|
||||||
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.contains_key(&path_id) {
|
if !assets_to_blueprint_instances
|
||||||
assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.insert(path_id.clone(), vec![]);
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.contains_key(&path_id)
|
||||||
|
{
|
||||||
|
assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.insert(path_id.clone(), vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only insert if not already present in mapping
|
// only insert if not already present in mapping
|
||||||
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids[&path_id].contains(&entity) {
|
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids
|
||||||
|
[&path_id]
|
||||||
|
.contains(&entity)
|
||||||
|
{
|
||||||
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
||||||
assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids.get_mut(&path_id).unwrap().push(entity);
|
assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.get_mut(&path_id)
|
||||||
|
.unwrap()
|
||||||
|
.push(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only do this if hot reload is enabled
|
||||||
|
// TODO: should this be added to the list of "all assets" on the blender side instead
|
||||||
|
if watching_for_changes.0 {
|
||||||
|
// also add the root blueprint info to the list of hot reload items
|
||||||
|
if !assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.contains_key(&blueprint_info.path)
|
||||||
|
{
|
||||||
|
assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.insert(blueprint_info.path.clone(), vec![]);
|
||||||
}
|
}
|
||||||
}
|
// only insert if not already present in mapping
|
||||||
|
if !assets_to_blueprint_instances.untyped_id_to_blueprint_entity_ids
|
||||||
|
[&blueprint_info.path]
|
||||||
|
.contains(&entity)
|
||||||
|
{
|
||||||
|
// println!("adding mapping between {} and entity {:?}", path_id, all_names.get(entity));
|
||||||
|
assets_to_blueprint_instances
|
||||||
|
.untyped_id_to_blueprint_entity_ids
|
||||||
|
.get_mut(&blueprint_info.path)
|
||||||
|
.unwrap()
|
||||||
|
.push(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +279,9 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||||
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
let loaded = asset_server.is_loaded_with_dependencies(asset_id);
|
||||||
|
|
||||||
let mut failed = false;
|
let mut failed = false;
|
||||||
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) { failed = true }
|
if let bevy::asset::LoadState::Failed(_) = asset_server.load_state(asset_id) {
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
tracker.loaded = loaded || failed;
|
tracker.loaded = loaded || failed;
|
||||||
if loaded || failed {
|
if loaded || failed {
|
||||||
loaded_amount += 1;
|
loaded_amount += 1;
|
||||||
|
@ -267,12 +305,10 @@ pub(crate) fn blueprints_check_assets_loading(
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(BlueprintAssetsLoaded)
|
.insert(BlueprintAssetsLoaded)
|
||||||
.remove::<BlueprintAssetsNotLoaded>()
|
.remove::<BlueprintAssetsNotLoaded>();
|
||||||
;
|
|
||||||
|
|
||||||
if !watching_for_changes.0 {
|
if !watching_for_changes.0 {
|
||||||
commands.entity(entity)
|
commands.entity(entity).remove::<BlueprintAssetsLoadState>(); //we REMOVE this component when in hot reload is OFF, as we
|
||||||
.remove::<BlueprintAssetsLoadState>(); //we REMOVE this component when in hot reload is OFF, as we
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,12 +592,11 @@ pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
|
|
||||||
all_names: Query<&Name>,
|
all_names: Query<&Name>,
|
||||||
) {
|
) {
|
||||||
for (original, children, original_children, name, animations) in
|
for (original, children, original_children, name, animations) in blueprint_scenes.iter() {
|
||||||
blueprint_scenes.iter()
|
|
||||||
{
|
|
||||||
info!("Cleaning up spawned scene {:?}", name);
|
info!("Cleaning up spawned scene {:?}", name);
|
||||||
|
|
||||||
if children.len() == 0 { // TODO: investigate, Honestly not sure if this issue from Bevy 0.12 is still present at all anymore
|
if children.len() == 0 {
|
||||||
|
// TODO: investigate, Honestly not sure if this issue from Bevy 0.12 is still present at all anymore
|
||||||
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)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +617,6 @@ pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
commands.entity(child).insert(FromBlueprint); // we do this here in order to avoid doing it to normal children
|
commands.entity(child).insert(FromBlueprint); // we do this here in order to avoid doing it to normal children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// copy components into from blueprint instance's blueprint_root_entity to original entity
|
// copy components into from blueprint instance's blueprint_root_entity to original entity
|
||||||
commands.add(CopyComponents {
|
commands.add(CopyComponents {
|
||||||
source: blueprint_root_entity,
|
source: blueprint_root_entity,
|
||||||
|
@ -632,14 +666,10 @@ pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
all_names.get(child),
|
all_names.get(child),
|
||||||
all_names.get(original)
|
all_names.get(original)
|
||||||
);
|
);
|
||||||
commands
|
commands.entity(original).insert(
|
||||||
.entity(original)
|
|
||||||
.insert(
|
|
||||||
//BlueprintAnimationPlayerLink(bla),
|
//BlueprintAnimationPlayerLink(bla),
|
||||||
BlueprintAnimationInfosLink(child)
|
BlueprintAnimationInfosLink(child),
|
||||||
)
|
);
|
||||||
;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for parent in all_parents.iter_ancestors(child) {
|
for parent in all_parents.iter_ancestors(child) {
|
||||||
if animation_players.get(parent).is_ok() {
|
if animation_players.get(parent).is_ok() {
|
||||||
|
@ -663,8 +693,9 @@ pub(crate) fn blueprints_cleanup_spawned_scene(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if with_animation_infos.get(parent).is_ok() {
|
if with_animation_infos.get(parent).is_ok() {
|
||||||
commands.entity(child).insert(InstanceAnimationInfosLink(parent));
|
commands
|
||||||
|
.entity(child)
|
||||||
|
.insert(InstanceAnimationInfosLink(parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,6 @@ fn components_string_to_components(
|
||||||
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
ron::ser::to_string_pretty(&serializer, ron::ser::PrettyConfig::default()).unwrap();
|
||||||
println!("serialized Component {}", serialized);
|
println!("serialized Component {}", serialized);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
debug!("component data ron string {}", ron_string);
|
debug!("component data ron string {}", ron_string);
|
||||||
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
let mut deserializer = ron::Deserializer::from_str(ron_string.as_str())
|
||||||
.expect("deserialzer should have been generated from string");
|
.expect("deserialzer should have been generated from string");
|
||||||
|
|
|
@ -13,13 +13,13 @@ pub use blueprints::*;
|
||||||
#[derive(Clone, Resource)]
|
#[derive(Clone, Resource)]
|
||||||
pub struct BlenvyConfig {
|
pub struct BlenvyConfig {
|
||||||
// registry
|
// registry
|
||||||
|
pub(crate) export_registry: bool,
|
||||||
pub(crate) registry_save_path: PathBuf,
|
pub(crate) registry_save_path: PathBuf,
|
||||||
pub(crate) registry_component_filter: SceneFilter,
|
pub(crate) registry_component_filter: SceneFilter,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) registry_resource_filter: SceneFilter,
|
pub(crate) registry_resource_filter: SceneFilter,
|
||||||
|
|
||||||
// blueprints
|
// blueprints
|
||||||
pub(crate) aabbs: bool,
|
|
||||||
pub(crate) aabb_cache: HashMap<String, Aabb>, // cache for aabbs
|
pub(crate) aabb_cache: HashMap<String, Aabb>, // cache for aabbs
|
||||||
pub(crate) materials_cache: HashMap<String, Handle<StandardMaterial>>, // cache for materials
|
pub(crate) materials_cache: HashMap<String, Handle<StandardMaterial>>, // cache for materials
|
||||||
|
|
||||||
|
@ -31,14 +31,12 @@ pub struct BlenvyConfig {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
/// Plugin for gltf blueprints
|
/// Plugin for gltf blueprints
|
||||||
pub struct BlenvyPlugin {
|
pub struct BlenvyPlugin {
|
||||||
|
pub export_registry: bool,
|
||||||
pub registry_save_path: PathBuf,
|
pub registry_save_path: PathBuf,
|
||||||
|
|
||||||
pub registry_component_filter: SceneFilter,
|
pub registry_component_filter: SceneFilter,
|
||||||
pub registry_resource_filter: SceneFilter,
|
pub registry_resource_filter: SceneFilter,
|
||||||
|
|
||||||
/// Automatically generate aabbs for the blueprints root objects
|
|
||||||
pub aabbs: bool,
|
|
||||||
|
|
||||||
// for save & load
|
// for save & load
|
||||||
pub save_component_filter: SceneFilter,
|
pub save_component_filter: SceneFilter,
|
||||||
pub save_resource_filter: SceneFilter,
|
pub save_resource_filter: SceneFilter,
|
||||||
|
@ -47,10 +45,10 @@ pub struct BlenvyPlugin {
|
||||||
impl Default for BlenvyPlugin {
|
impl Default for BlenvyPlugin {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
export_registry: true,
|
||||||
registry_save_path: PathBuf::from("registry.json"), // relative to assets folder
|
registry_save_path: PathBuf::from("registry.json"), // relative to assets folder
|
||||||
registry_component_filter: SceneFilter::default(),
|
registry_component_filter: SceneFilter::default(),
|
||||||
registry_resource_filter: SceneFilter::default(),
|
registry_resource_filter: SceneFilter::default(),
|
||||||
aabbs: false,
|
|
||||||
|
|
||||||
save_component_filter: SceneFilter::default(),
|
save_component_filter: SceneFilter::default(),
|
||||||
save_resource_filter: SceneFilter::default(),
|
save_resource_filter: SceneFilter::default(),
|
||||||
|
@ -66,17 +64,17 @@ impl Plugin for BlenvyPlugin {
|
||||||
BlueprintsPlugin::default(),
|
BlueprintsPlugin::default(),
|
||||||
))
|
))
|
||||||
.insert_resource(BlenvyConfig {
|
.insert_resource(BlenvyConfig {
|
||||||
|
export_registry: self.export_registry,
|
||||||
registry_save_path: self.registry_save_path.clone(),
|
registry_save_path: self.registry_save_path.clone(),
|
||||||
registry_component_filter: self.registry_component_filter.clone(),
|
registry_component_filter: self.registry_component_filter.clone(),
|
||||||
registry_resource_filter: self.registry_resource_filter.clone(),
|
registry_resource_filter: self.registry_resource_filter.clone(),
|
||||||
|
|
||||||
aabbs: self.aabbs,
|
|
||||||
aabb_cache: HashMap::new(),
|
aabb_cache: HashMap::new(),
|
||||||
|
|
||||||
materials_cache: HashMap::new(),
|
materials_cache: HashMap::new(),
|
||||||
|
|
||||||
save_component_filter: self.save_component_filter.clone(),
|
save_component_filter: self.save_component_filter.clone(),
|
||||||
save_resource_filter: self.save_resource_filter.clone()
|
save_resource_filter: self.save_resource_filter.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,12 @@ pub use export_types::*;
|
||||||
use bevy::{
|
use bevy::{
|
||||||
app::Startup,
|
app::Startup,
|
||||||
asset::AssetPlugin,
|
asset::AssetPlugin,
|
||||||
prelude::{App, Plugin, Resource},
|
prelude::{App, IntoSystemConfigs, Plugin, Res, Resource},
|
||||||
scene::SceneFilter,
|
scene::SceneFilter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::BlenvyConfig;
|
||||||
|
|
||||||
pub struct ExportRegistryPlugin {
|
pub struct ExportRegistryPlugin {
|
||||||
pub component_filter: SceneFilter,
|
pub component_filter: SceneFilter,
|
||||||
pub resource_filter: SceneFilter,
|
pub resource_filter: SceneFilter,
|
||||||
|
@ -26,9 +28,14 @@ impl Default for ExportRegistryPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn export_registry(blenvy_config: Res<BlenvyConfig>) -> bool {
|
||||||
|
// TODO: add detection of Release builds, wasm, and android in order to avoid exporting registry in those cases
|
||||||
|
blenvy_config.export_registry
|
||||||
|
}
|
||||||
|
|
||||||
impl Plugin for ExportRegistryPlugin {
|
impl Plugin for ExportRegistryPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.register_asset_root().add_systems(Startup, export_types);
|
app.register_asset_root().add_systems(Startup, export_types.run_if(export_registry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use blenvy::{AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
use blenvy::{
|
||||||
|
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintAnimationPlayerLink,
|
||||||
|
BlueprintAnimations, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady,
|
||||||
|
SpawnBlueprint,
|
||||||
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
mod component_examples;
|
mod component_examples;
|
||||||
|
@ -22,31 +26,24 @@ pub struct Fox;
|
||||||
/// Demo marker component
|
/// Demo marker component
|
||||||
pub struct Robot;
|
pub struct Robot;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((
|
||||||
DefaultPlugins.set(AssetPlugin::default()),
|
DefaultPlugins.set(AssetPlugin::default()),
|
||||||
// our custom plugins
|
// our custom plugins
|
||||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||||
BlenvyPlugin::default()
|
BlenvyPlugin::default(),
|
||||||
))
|
))
|
||||||
.register_type::<Player>()
|
.register_type::<Player>()
|
||||||
.register_type::<Fox>()
|
.register_type::<Fox>()
|
||||||
.register_type::<Robot>()
|
.register_type::<Robot>()
|
||||||
|
|
||||||
.add_systems(Startup, setup_game)
|
.add_systems(Startup, setup_game)
|
||||||
.add_systems(Update,
|
.add_systems(Update, (animation_control,))
|
||||||
(animation_control,)
|
|
||||||
)
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is how you setup & spawn a level from a blueprint
|
// this is how you setup & spawn a level from a blueprint
|
||||||
fn setup_game(
|
fn setup_game(mut commands: Commands) {
|
||||||
mut commands: Commands,
|
|
||||||
) {
|
|
||||||
|
|
||||||
// here we actually spawn our game world/level
|
// here we actually spawn our game world/level
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||||
|
@ -56,7 +53,6 @@ fn setup_game(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
pub fn animation_control(
|
pub fn animation_control(
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use blenvy::{AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance, GameWorldTag, HideUntilReady, SpawnBlueprint};
|
use blenvy::{
|
||||||
|
AddToGameWorld, BlenvyPlugin, BluePrintBundle, BlueprintInfo, DynamicBlueprintInstance,
|
||||||
|
GameWorldTag, HideUntilReady, SpawnBlueprint,
|
||||||
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
mod component_examples;
|
mod component_examples;
|
||||||
|
@ -11,20 +14,15 @@ fn main() {
|
||||||
DefaultPlugins.set(AssetPlugin::default()),
|
DefaultPlugins.set(AssetPlugin::default()),
|
||||||
// our custom plugins
|
// our custom plugins
|
||||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||||
BlenvyPlugin::default()
|
BlenvyPlugin::default(),
|
||||||
))
|
))
|
||||||
|
|
||||||
.add_systems(Startup, setup_game)
|
.add_systems(Startup, setup_game)
|
||||||
.add_systems(Update, spawn_blueprint_instance)
|
.add_systems(Update, spawn_blueprint_instance)
|
||||||
|
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is how you setup & spawn a level from a blueprint
|
// this is how you setup & spawn a level from a blueprint
|
||||||
fn setup_game(
|
fn setup_game(mut commands: Commands) {
|
||||||
mut commands: Commands,
|
|
||||||
) {
|
|
||||||
|
|
||||||
// here we spawn our game world/level, which is also a blueprint !
|
// here we spawn our game world/level, which is also a blueprint !
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||||
|
@ -34,7 +32,6 @@ fn setup_game(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// you can also spawn blueprint instances at runtime
|
// you can also spawn blueprint instances at runtime
|
||||||
pub fn spawn_blueprint_instance(
|
pub fn spawn_blueprint_instance(
|
||||||
keycode: Res<ButtonInput<KeyCode>>,
|
keycode: Res<ButtonInput<KeyCode>>,
|
||||||
|
@ -67,10 +64,8 @@ pub fn spawn_blueprint_instance(
|
||||||
HideUntilReady,
|
HideUntilReady,
|
||||||
AddToGameWorld,
|
AddToGameWorld,
|
||||||
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
TransformBundle::from_transform(Transform::from_xyz(x, 2.0, y)),
|
||||||
|
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
// commands.entity(world).add_child(new_entity);
|
// commands.entity(world).add_child(new_entity);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,18 +10,13 @@ fn main() {
|
||||||
DefaultPlugins.set(AssetPlugin::default()),
|
DefaultPlugins.set(AssetPlugin::default()),
|
||||||
// our custom plugins
|
// our custom plugins
|
||||||
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
ComponentsExamplesPlugin, // Showcases different type of components /structs
|
||||||
BlenvyPlugin::default()
|
BlenvyPlugin::default(),
|
||||||
))
|
))
|
||||||
|
|
||||||
.add_systems(Startup, setup_game)
|
.add_systems(Startup, setup_game)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_game(mut commands: Commands) {
|
||||||
fn setup_game(
|
|
||||||
mut commands: Commands,
|
|
||||||
) {
|
|
||||||
|
|
||||||
// here we actually spawn our game world/level
|
// here we actually spawn our game world/level
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
BlueprintInfo::from_path("levels/World.glb"), // all we need is a Blueprint info...
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use blenvy::{BluePrintBundle, BlueprintName, GameWorldTag};
|
|
||||||
use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning};
|
use bevy_gltf_worlflow_examples_common_rapier::{assets::GameAssets, GameState, InAppRunning};
|
||||||
|
use blenvy::{BluePrintBundle, BlueprintName, GameWorldTag};
|
||||||
|
|
||||||
use bevy_rapier3d::prelude::Velocity;
|
use bevy_rapier3d::prelude::Velocity;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use bevy::{gltf::Gltf, prelude::*};
|
use bevy::{gltf::Gltf, prelude::*};
|
||||||
use blenvy::GameWorldTag;
|
|
||||||
use bevy_gltf_worlflow_examples_common_rapier::{
|
use bevy_gltf_worlflow_examples_common_rapier::{
|
||||||
assets::GameAssets, GameState, InAppRunning, Player,
|
assets::GameAssets, GameState, InAppRunning, Player,
|
||||||
};
|
};
|
||||||
use bevy_rapier3d::prelude::*;
|
use bevy_rapier3d::prelude::*;
|
||||||
|
use blenvy::GameWorldTag;
|
||||||
|
|
||||||
#[derive(Component, Reflect, Default, Debug)]
|
#[derive(Component, Reflect, Default, Debug)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
|
|
|
@ -12,7 +12,9 @@ from .export_gltf import get_standard_exporter_settings
|
||||||
|
|
||||||
from ..levels.export_levels import export_level_scene
|
from ..levels.export_levels import export_level_scene
|
||||||
from ..blueprints.export_blueprints import export_blueprints
|
from ..blueprints.export_blueprints import export_blueprints
|
||||||
from .export_materials import cleanup_materials, export_materials
|
|
||||||
|
from ..materials.get_materials_to_export import get_materials_to_export
|
||||||
|
from ..materials.export_materials import cleanup_materials, export_materials
|
||||||
from ..levels.bevy_scene_components import remove_scene_components, upsert_scene_components
|
from ..levels.bevy_scene_components import remove_scene_components, upsert_scene_components
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,9 +72,7 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
|
|
||||||
# since materials export adds components we need to call this before blueprints are exported
|
# since materials export adds components we need to call this before blueprints are exported
|
||||||
# export materials & inject materials components into relevant objects
|
# export materials & inject materials components into relevant objects
|
||||||
# FIXME: improve change detection, perhaps even add "material changes"
|
materials_to_export = get_materials_to_export(changes_per_material, changed_export_parameters, blueprints_data, settings)
|
||||||
if export_materials_library and (changed_export_parameters or len(changes_per_material.keys()) > 0 ):
|
|
||||||
export_materials(blueprints_data.blueprint_names, settings.library_scenes, settings)
|
|
||||||
|
|
||||||
# update the list of tracked exports
|
# update the list of tracked exports
|
||||||
exports_total = len(blueprints_to_export) + len(level_scenes_to_export) + (1 if export_materials_library else 0)
|
exports_total = len(blueprints_to_export) + len(level_scenes_to_export) + (1 if export_materials_library else 0)
|
||||||
|
@ -92,7 +92,9 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
print("-------------------------------")
|
print("-------------------------------")
|
||||||
print("BLUEPRINTS: to export:", [blueprint.name for blueprint in blueprints_to_export])
|
print("BLUEPRINTS: to export:", [blueprint.name for blueprint in blueprints_to_export])
|
||||||
print("-------------------------------")
|
print("-------------------------------")
|
||||||
print("MAIN SCENES: to export:", level_scenes_to_export)
|
print("LEVELS: to export:", level_scenes_to_export)
|
||||||
|
print("-------------------------------")
|
||||||
|
print("MATERIALS: to export:", materials_to_export)
|
||||||
print("-------------------------------")
|
print("-------------------------------")
|
||||||
# backup current active scene
|
# backup current active scene
|
||||||
old_current_scene = bpy.context.scene
|
old_current_scene = bpy.context.scene
|
||||||
|
@ -112,6 +114,10 @@ def auto_export(changes_per_scene, changes_per_collection, changes_per_material,
|
||||||
print("export LIBRARY")
|
print("export LIBRARY")
|
||||||
export_blueprints(blueprints_to_export, settings, blueprints_data)
|
export_blueprints(blueprints_to_export, settings, blueprints_data)
|
||||||
|
|
||||||
|
# then deal with materials
|
||||||
|
if export_materials_library:
|
||||||
|
export_materials(materials_to_export, settings, blueprints_data)#blueprints_data.blueprint_names, settings.library_scenes, settings)
|
||||||
|
|
||||||
# reset current scene from backup
|
# reset current scene from backup
|
||||||
bpy.context.window.scene = old_current_scene
|
bpy.context.window.scene = old_current_scene
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ from pathlib import Path
|
||||||
from blenvy.core.helpers_collections import (traverse_tree)
|
from blenvy.core.helpers_collections import (traverse_tree)
|
||||||
from blenvy.core.object_makers import make_cube
|
from blenvy.core.object_makers import make_cube
|
||||||
from blenvy.materials.materials_helpers import add_material_info_to_objects, get_all_materials
|
from blenvy.materials.materials_helpers import add_material_info_to_objects, get_all_materials
|
||||||
from .generate_temporary_scene_and_export import generate_temporary_scene_and_export
|
from ..common.generate_temporary_scene_and_export import generate_temporary_scene_and_export
|
||||||
from .export_gltf import (generate_gltf_export_settings)
|
from ..common.export_gltf import (generate_gltf_export_settings)
|
||||||
|
|
||||||
# material library logic
|
# material library logic
|
||||||
# To avoid redundant materials (can be very costly, mostly when using high res textures)
|
# To avoid redundant materials (can be very costly, mostly when using high res textures)
|
||||||
|
@ -65,11 +65,12 @@ def clear_materials_scene(temp_scene):
|
||||||
|
|
||||||
# exports the materials used inside the current project:
|
# exports the materials used inside the current project:
|
||||||
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
|
# the name of the output path is <materials_folder>/<name_of_your_blend_file>_materials_library.gltf/glb
|
||||||
def export_materials(collections, library_scenes, settings):
|
def export_materials(materials_to_export, settings, blueprints_data):
|
||||||
|
if len(materials_to_export) > 0:
|
||||||
gltf_export_settings = generate_gltf_export_settings(settings)
|
gltf_export_settings = generate_gltf_export_settings(settings)
|
||||||
materials_path_full = getattr(settings,"materials_path_full")
|
materials_path_full = getattr(settings,"materials_path_full")
|
||||||
|
|
||||||
(used_material_names, materials_per_object) = get_all_materials(collections, library_scenes)
|
(used_material_names, materials_per_object) = get_all_materials(blueprints_data.blueprint_names, settings.library_scenes)
|
||||||
add_material_info_to_objects(materials_per_object, settings)
|
add_material_info_to_objects(materials_per_object, settings)
|
||||||
|
|
||||||
gltf_export_settings = { **gltf_export_settings,
|
gltf_export_settings = { **gltf_export_settings,
|
||||||
|
@ -96,6 +97,8 @@ def export_materials(collections, library_scenes, settings):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def cleanup_materials(collections, library_scenes):
|
def cleanup_materials(collections, library_scenes):
|
||||||
# remove temporary components
|
# remove temporary components
|
||||||
clear_material_info(collections, library_scenes)
|
clear_material_info(collections, library_scenes)
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from blenvy.materials.materials_helpers import find_materials_not_on_disk
|
||||||
|
|
||||||
|
def get_materials_to_export(changes_per_material, changed_export_parameters, blueprints_data, settings):
|
||||||
|
export_gltf_extension = getattr(settings, "export_gltf_extension", ".glb")
|
||||||
|
blueprints_path_full = getattr(settings,"blueprints_path_full", "")
|
||||||
|
materials_path_full = getattr(settings,"materials_path_full", "")
|
||||||
|
|
||||||
|
change_detection = getattr(settings.auto_export, "change_detection")
|
||||||
|
collection_instances_combine_mode = getattr(settings.auto_export, "collection_instances_combine_mode")
|
||||||
|
|
||||||
|
all_materials = bpy.data.materials
|
||||||
|
local_materials = [material for material in all_materials if material.library is None]
|
||||||
|
#and (changed_export_parameters or len(changes_per_material.keys()) > 0 )
|
||||||
|
|
||||||
|
materials_to_export = []
|
||||||
|
if change_detection and not changed_export_parameters:
|
||||||
|
changed_materials = []
|
||||||
|
|
||||||
|
# first check if all materials have already been exported before (if this is the first time the exporter is run
|
||||||
|
# in your current Blender session for example)
|
||||||
|
materials_not_on_disk = find_materials_not_on_disk(local_materials, materials_path_full, export_gltf_extension)
|
||||||
|
|
||||||
|
# also deal with blueprints that are always marked as "always_export"
|
||||||
|
#materials_always_export = [material for material in internal_materials if is_material_always_export(material)]
|
||||||
|
materials_always_export = []
|
||||||
|
materials_to_export = list(set(changed_materials + materials_not_on_disk + materials_always_export))
|
||||||
|
|
||||||
|
|
||||||
|
return materials_to_export
|
|
@ -1,5 +1,5 @@
|
||||||
|
import posixpath
|
||||||
import bpy
|
import bpy
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from blenvy.assets.assets_scan import get_blueprint_asset_tree, get_level_scene_assets_tree2
|
from blenvy.assets.assets_scan import get_blueprint_asset_tree, get_level_scene_assets_tree2
|
||||||
|
|
||||||
|
@ -10,9 +10,6 @@ def assets_to_fake_ron(list_like):
|
||||||
|
|
||||||
return f"(assets: {result})".replace("'", '')
|
return f"(assets: {result})".replace("'", '')
|
||||||
|
|
||||||
return f"({result})".replace("'", '')
|
|
||||||
|
|
||||||
|
|
||||||
# TODO : move to assets
|
# TODO : move to assets
|
||||||
def upsert_scene_assets(scene, blueprints_data, settings):
|
def upsert_scene_assets(scene, blueprints_data, settings):
|
||||||
"""print("level scene", scene)
|
"""print("level scene", scene)
|
||||||
|
@ -33,7 +30,7 @@ def upsert_scene_assets(scene, blueprints_data, settings):
|
||||||
blueprints_path = getattr(settings, "blueprints_path")
|
blueprints_path = getattr(settings, "blueprints_path")
|
||||||
for blueprint in blueprints_in_scene:
|
for blueprint in blueprints_in_scene:
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||||
|
@ -56,7 +53,7 @@ def upsert_scene_assets(scene, blueprints_data, settings):
|
||||||
materials_path = getattr(settings, "materials_path")
|
materials_path = getattr(settings, "materials_path")
|
||||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
materials_library_name = f"{current_project_name}_materials"
|
materials_library_name = f"{current_project_name}_materials"
|
||||||
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
material_assets = [{"name": materials_library_name, "path": materials_exported_path}] # we also add the material library as an asset
|
material_assets = [{"name": materials_library_name, "path": materials_exported_path}] # we also add the material library as an asset
|
||||||
print("material_assets", material_assets, "extension", export_gltf_extension)
|
print("material_assets", material_assets, "extension", export_gltf_extension)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import posixpath
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list
|
from .asset_helpers import does_asset_exist, get_user_assets, get_user_assets_as_list
|
||||||
|
@ -22,7 +23,7 @@ def scan_assets(scene, blueprints_data, settings):
|
||||||
#print("BLUEPRINT", blueprint)
|
#print("BLUEPRINT", blueprint)
|
||||||
blueprint_exported_path = None
|
blueprint_exported_path = None
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(relative_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(relative_blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
||||||
|
@ -71,7 +72,7 @@ def get_blueprint_assets_tree(blueprint, blueprints_data, parent, settings):
|
||||||
if child_blueprint:
|
if child_blueprint:
|
||||||
blueprint_exported_path = None
|
blueprint_exported_path = None
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{child_blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{child_blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = child_blueprint.collection['export_path'] if 'export_path' in child_blueprint.collection else None
|
blueprint_exported_path = child_blueprint.collection['export_path'] if 'export_path' in child_blueprint.collection else None
|
||||||
|
@ -101,7 +102,7 @@ def get_level_scene_assets_tree(level_scene, blueprints_data, settings):
|
||||||
if blueprint is not None:
|
if blueprint is not None:
|
||||||
blueprint_exported_path = None
|
blueprint_exported_path = None
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||||
|
@ -134,7 +135,7 @@ def get_level_scene_assets_tree2(level_scene, blueprints_data, settings):
|
||||||
if blueprint is not None:
|
if blueprint is not None:
|
||||||
blueprint_exported_path = None
|
blueprint_exported_path = None
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
blueprint_exported_path = blueprint.collection['export_path'] if 'export_path' in blueprint.collection else None
|
||||||
|
@ -156,7 +157,7 @@ def get_blueprint_asset_tree(blueprint, blueprints_data, settings):
|
||||||
if sub_blueprint is not None:
|
if sub_blueprint is not None:
|
||||||
sub_blueprint_exported_path = None
|
sub_blueprint_exported_path = None
|
||||||
if sub_blueprint.local:
|
if sub_blueprint.local:
|
||||||
sub_blueprint_exported_path = os.path.join(blueprints_path, f"{sub_blueprint.name}{export_gltf_extension}")
|
sub_blueprint_exported_path = posixpath.join(blueprints_path, f"{sub_blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
sub_blueprint_exported_path = sub_blueprint.collection['export_path'] if 'export_path' in sub_blueprint.collection else None
|
sub_blueprint_exported_path = sub_blueprint.collection['export_path'] if 'export_path' in sub_blueprint.collection else None
|
||||||
|
|
|
@ -3,6 +3,7 @@ import os
|
||||||
import json
|
import json
|
||||||
import bpy
|
import bpy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import posixpath
|
||||||
|
|
||||||
from ..core.scene_helpers import add_scene_property
|
from ..core.scene_helpers import add_scene_property
|
||||||
|
|
||||||
|
@ -28,10 +29,10 @@ def inject_export_path_into_internal_blueprints(internal_blueprints, blueprints_
|
||||||
materials_path = getattr(settings, "materials_path")
|
materials_path = getattr(settings, "materials_path")
|
||||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
materials_library_name = f"{current_project_name}_materials"
|
materials_library_name = f"{current_project_name}_materials"
|
||||||
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
|
|
||||||
for blueprint in internal_blueprints:
|
for blueprint in internal_blueprints:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{gltf_extension}")
|
||||||
# print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name)
|
# print("injecting blueprint path", blueprint_exported_path, "for", blueprint.name)
|
||||||
blueprint.collection["export_path"] = blueprint_exported_path
|
blueprint.collection["export_path"] = blueprint_exported_path
|
||||||
if export_materials_library:
|
if export_materials_library:
|
||||||
|
@ -58,7 +59,7 @@ def inject_blueprints_list_into_level_scene(scene, blueprints_data, settings):
|
||||||
#print("BLUEPRINT", blueprint)
|
#print("BLUEPRINT", blueprint)
|
||||||
blueprint_exported_path = None
|
blueprint_exported_path = None
|
||||||
if blueprint.local:
|
if blueprint.local:
|
||||||
blueprint_exported_path = os.path.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
blueprint_exported_path = posixpath.join(blueprints_path, f"{blueprint.name}{export_gltf_extension}")
|
||||||
else:
|
else:
|
||||||
# get the injected path of the external blueprints
|
# get the injected path of the external blueprints
|
||||||
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
blueprint_exported_path = blueprint.collection['Export_path'] if 'Export_path' in blueprint.collection else None
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
import os
|
import os
|
||||||
|
import posixpath
|
||||||
import bpy
|
import bpy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from ..core.helpers_collections import (traverse_tree)
|
from ..core.helpers_collections import (traverse_tree)
|
||||||
|
|
||||||
|
def find_materials_not_on_disk(materials, folder_path, extension):
|
||||||
|
not_found_materials = []
|
||||||
|
for material in materials:
|
||||||
|
gltf_output_path = os.path.join(folder_path, material.name + extension)
|
||||||
|
# print("gltf_output_path", gltf_output_path)
|
||||||
|
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
|
||||||
|
if not found:
|
||||||
|
not_found_materials.append(material)
|
||||||
|
return not_found_materials
|
||||||
|
|
||||||
|
def check_if_material_on_disk(scene_name, folder_path, extension):
|
||||||
|
gltf_output_path = os.path.join(folder_path, scene_name + extension)
|
||||||
|
found = os.path.exists(gltf_output_path) and os.path.isfile(gltf_output_path)
|
||||||
|
return found
|
||||||
|
|
||||||
# get materials per object, and injects the materialInfo component
|
# get materials per object, and injects the materialInfo component
|
||||||
def get_materials(object, materials_per_object):
|
def get_materials(object, materials_per_object):
|
||||||
material_slots = object.material_slots
|
material_slots = object.material_slots
|
||||||
|
@ -38,11 +54,11 @@ def add_material_info_to_objects(materials_per_object, settings):
|
||||||
|
|
||||||
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
current_project_name = Path(bpy.context.blend_data.filepath).stem
|
||||||
materials_library_name = f"{current_project_name}_materials"
|
materials_library_name = f"{current_project_name}_materials"
|
||||||
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
for object in materials_per_object.keys():
|
for object in materials_per_object.keys():
|
||||||
material = materials_per_object[object]
|
material = materials_per_object[object]
|
||||||
# TODO: switch to using actual components ?
|
# TODO: switch to using actual components ?
|
||||||
materials_exported_path = os.path.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
materials_exported_path = posixpath.join(materials_path, f"{materials_library_name}{export_gltf_extension}")
|
||||||
object['MaterialInfo'] = f'(name: "{material.name}", path: "{materials_exported_path}")'
|
object['MaterialInfo'] = f'(name: "{material.name}", path: "{materials_exported_path}")'
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue