fix(tools:bevy_gltf_blueprints): (#27)

* fix(tools:bevy_gltf_blueprints):
 * fixed missing rotation in blueprint collections (if there is any)
 * fixed similar issues with scale 
 * fixed issues with active collection at the time of saving/export being poluted by temporary data
* refactor(bevy_gltf_blueprints): minor cleanups
This commit is contained in:
Mark Moissette 2023-10-14 20:47:35 +02:00 committed by GitHub
parent 5683f01cea
commit 921a5ef331
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 20 additions and 33 deletions

Binary file not shown.

Binary file not shown.

View File

@ -50,7 +50,7 @@ pub(crate) fn spawn_from_blueprints(
asset_server: Res<AssetServer>,
blueprints_config: Res<BluePrintsConfig>,
) {
for (entity, name, blupeprint_name, global_transform) in spawn_placeholders.iter() {
for (entity, name, blupeprint_name, transform) in spawn_placeholders.iter() {
debug!("need to spawn {:?}", blupeprint_name.0);
let what = &blupeprint_name.0;
let model_file_name = format!("{}.glb", &what);
@ -59,7 +59,6 @@ pub(crate) fn spawn_from_blueprints(
debug!("attempting to spawn {:?}", model_path);
let scene: Handle<Gltf> = asset_server.load(model_path);
// let scene = game_assets.models.get(&model_path).expect(&format!("no matching model {:?} found", model_path));
let world = game_world.single_mut();
let world = world.1[0]; // FIXME: dangerous hack because our gltf data have a single child like this, but might not always be the case
@ -75,21 +74,16 @@ pub(crate) fn spawn_from_blueprints(
.expect("there should be at least one named scene in the gltf file to spawn");
let scene = &gltf.named_scenes[main_scene_name];
//spawn_requested_events.send(SpawnRequestedEvent { what: "enemy".into(), position, amount: 1, spawner_id: None });
let child_scene = commands
.spawn((
SceneBundle {
scene: scene.clone(),
transform: global_transform.clone(),
transform: transform.clone(),
..Default::default()
},
bevy::prelude::Name::from(["scene_wrapper", &name.clone()].join("_")),
// Parent(world) // FIXME/ would be good if this worked directly
SpawnedRoot,
/*AnimationHelper{ // TODO: insert this at the ENTITY level, not the scene level
named_animations: gltf.named_animations.clone(),
// animations: gltf.named_animations.values().clone()
},*/
Original(entity),
))
.id();

View File

@ -17,7 +17,6 @@ pub(crate) struct SpawnedRootProcessed;
/// this system updates the first (and normally only) child of a scene flaged SpawnedRoot
/// - adds a name based on parent component (spawned scene) which is named on the scene name/prefab to be instanciated
/// - adds the initial physics impulse (FIXME: we would need to add a temporary physics component to those who do not have it)
// FIXME: updating hierarchy does not work in all cases ! this is sadly dependant on the structure of the exported blend data
// - blender root-> object with properties => WORKS
// - scene instance -> does not work
@ -78,28 +77,20 @@ pub(crate) fn update_spawned_root_first_child(
commands.entity(*root_entity).insert((
bevy::prelude::Name::from(name.clone()),
// ItemType {name},
// Spawned, // FIXME: not sure
));
// flag the spawned_root as being processed
commands.entity(scene_instance).insert(SpawnedRootProcessed);
// let original_transforms =
// parent is either the world or an entity with a marker (BlueprintName)
commands.entity(parent.get()).add_child(*root_entity);
// commands.entity(*root_entity).despawn_recursive();
// commands.entity(parent.get()).push_children(&actual_stuff);
//commands.entity(*root_entity).log_components();
let matching_animation_helper = animation_helpers.get(scene_instance);
// println!("WE HAVE SOME ADDED ANIMATION PLAYERS {:?}", matching_animation_helper);
if let Ok(anim_helper) = matching_animation_helper {
for (added, _) in added_animation_helpers.iter() {
commands.entity(added).insert(AnimationHelper {
// TODO: insert this at the ENTITY level, not the scene level
named_animations: anim_helper.named_animations.clone(),
// animations: gltf.named_animations.values().clone()
});
}
}

View File

@ -1,8 +1,8 @@
bl_info = {
"name": "gltf_auto_export",
"author": "kaosigh",
"version": (0, 2),
"blender": (3, 4, 1),
"version": (0, 3),
"blender": (3, 4, 0),
"location": "File > Import-Export",
"description": "glTF/glb auto-export",
"warning": "",
@ -30,9 +30,7 @@ from bpy.props import (BoolProperty,
#see here for original gltf exporter infos https://github.com/KhronosGroup/glTF-Blender-IO/blob/main/addons/io_scene_gltf2/__init__.py
@persistent
def deps_update_handler(scene, depsgraph):
print("depsgraph_update_post", scene.name)
print("toto")
print("-------------")
changed_objects = []
for obj in depsgraph.updates:
@ -91,7 +89,9 @@ def get_collection_hierarchy(root_col, levels=1):
# the active collection is a View Layer concept, so you actually have to find the active LayerCollection
# which must be done recursively
def find_layer_collection_recursive(find, col):
print("root collection", col)
for c in col.children:
print("child collection", c)
if c.collection == find:
return c
return None
@ -129,18 +129,16 @@ def make_empty2(name, location, collection):
collection.objects.link( empty_obj )
return empty_obj
def make_empty3(name, location, collection):
def make_empty3(name, location, rotation, scale, collection):
original_active_object = bpy.context.active_object
bpy.ops.object.empty_add(type='PLAIN_AXES', location=location)
bpy.ops.object.empty_add(type='PLAIN_AXES', location=location, rotation=rotation, scale=scale)
empty_obj = bpy.context.active_object
empty_obj.name = name
collection.objects.link( empty_obj )
empty_obj.scale = scale # scale is not set correctly ?????
bpy.context.view_layer.objects.active = original_active_object
return empty_obj
# generate a copy of a scene that replaces collection instances with empties
# FIXME: will not preserve original names
# alternative: copy original names before creating a new scene, & reset them
# or create empties, hide original ones, and do the same renaming trick
def generate_hollow_scene(scene):
@ -149,13 +147,15 @@ def generate_hollow_scene(scene):
copy_root_collection = temp_scene.collection
scene_objects = [o for o in root_collection.objects]
# we set our active scene to be this one : this is needed otherwise the stand-in empties get generated in the wrong scene
bpy.context.window.scene = temp_scene
found = find_layer_collection_recursive(copy_root_collection, bpy.context.view_layer.layer_collection)
if found:
print("FOUND COLLECTION")
# once it's found, set the active layer collection to the one we found
bpy.context.view_layer.active_layer_collection = found
#original_names = {}
original_names = []
for object in scene_objects:
@ -171,7 +171,7 @@ def generate_hollow_scene(scene):
original_names.append(original_name)
object.name = original_name + "____bak"
empty_obj = make_empty3(original_name, object.location, copy_root_collection)
empty_obj = make_empty3(original_name, object.location, object.rotation_euler, object.scale, copy_root_collection)
"""we inject the collection/blueprint name, as a component called 'BlueprintName', but we only do this in the empty, not the original object"""
empty_obj['BlueprintName'] = '"'+collection_name+'"'
empty_obj['SpawnHere'] = ''
@ -194,9 +194,7 @@ def clear_hollow_scene(temp_scene, original_scene, original_names):
for object in scene_objects:
if object.instance_type == 'COLLECTION':
print("object name to reset", object.name)
if object.name.endswith("____bak"):
print("reseting")
object.name = object.name.replace("____bak", "")
# remove empties (only needed when we go via ops ????)
@ -204,8 +202,12 @@ def clear_hollow_scene(temp_scene, original_scene, original_names):
scene_objects = [o for o in root_collection.objects]
for object in scene_objects:
if object.type == 'EMPTY':
bpy.data.objects.remove(object, do_unlink=True)
if hasattr(object, "SpawnHere"):
bpy.data.objects.remove(object, do_unlink=True)
else:
bpy.context.scene.collection.objects.unlink(object)
#bpy.data.objects.remove(object, do_unlink=True)
bpy.data.scenes.remove(temp_scene)