Compare commits

..

1 Commits

Author SHA1 Message Date
Mark Moissette
a3d95b8425
Merge 1f959c51bd into bb4b07b7af 2024-03-22 23:02:54 +00:00
6 changed files with 15 additions and 150 deletions

View File

@ -34,14 +34,4 @@ pub struct InstanceAnimations {
/// so that the root entity knows which of its children contains an actualy `AnimationPlayer` component /// so that the root entity knows which of its children contains an actualy `AnimationPlayer` component
/// this is for convenience, because currently , Bevy's gltf parsing inserts `AnimationPlayers` "one level down" /// this is for convenience, because currently , Bevy's gltf parsing inserts `AnimationPlayers` "one level down"
/// ie armature/root for animated models, which means more complex queries to trigger animations that we want to avoid /// ie armature/root for animated models, which means more complex queries to trigger animations that we want to avoid
pub struct InstanceAnimationPlayerLink(pub Entity); pub struct InstanceAnimationPlayerLink(pub Entity);
pub struct AnimationMarker{
pub frame:u32,
pub name: String,
}
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)]
pub struct AnimationMarkers(pub HashMap<String, HashMap<u32, Vec<String> >>);

View File

@ -127,10 +127,6 @@ impl Plugin for BlueprintsPlugin {
.register_type::<BlueprintAnimations>() .register_type::<BlueprintAnimations>()
.register_type::<InstanceAnimations>() .register_type::<InstanceAnimations>()
.register_type::<Animated>() .register_type::<Animated>()
.register_type::<AnimationMarkers>()
.register_type::<HashMap<u32, Vec<String>>>()
.register_type::<HashMap<String, HashMap<u32, Vec<String> >>>()
.register_type::<BlueprintsList>() .register_type::<BlueprintsList>()
.register_type::<Vec<String>>() .register_type::<Vec<String>>()

View File

@ -1,10 +1,5 @@
use bevy::pbr::DirectionalLightShadowMap; use bevy::pbr::DirectionalLightShadowMap;
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::render_asset::RenderAssetUsages;
use bevy::render::render_resource::{
Extent3d, TextureDimension, TextureFormat, TextureViewDescriptor, TextureViewDimension,
};
use std::iter;
use crate::GltfComponentsSet; use crate::GltfComponentsSet;
@ -89,66 +84,14 @@ fn process_shadowmap(
} }
fn process_background_shader( fn process_background_shader(
background_shaders: Query<Ref<BlenderBackgroundShader>>, background_shaders: Query<&BlenderBackgroundShader, Added<BlenderBackgroundShader>>,
cameras: Query<(Entity, Ref<Camera3d>)>,
mut images: ResMut<Assets<Image>>,
mut commands: Commands, mut commands: Commands,
mut env_map_handle: Local<Option<Handle<Image>>>,
) { ) {
let Ok(background_shader) = background_shaders.get_single() else { for background_shader in background_shaders.iter() {
return; commands.insert_resource(AmbientLight {
}; color: background_shader.color,
// Just a guess, see <https://github.com/bevyengine/bevy/issues/12280>
let env_map_handle = env_map_handle.get_or_insert_with(|| { brightness: background_shader.strength * 400.0,
let size = Extent3d {
width: 1,
height: 6,
depth_or_array_layers: 1,
};
let dimension = TextureDimension::D2;
const SIDES_PER_CUBE: usize = 6;
let data: Vec<_> = iter::repeat(background_shader.color.as_rgba_u8())
.take(SIDES_PER_CUBE)
.flatten()
.collect();
let format = TextureFormat::Rgba8UnormSrgb;
let asset_usage = RenderAssetUsages::RENDER_WORLD;
let mut image = Image::new(size, dimension, data, format, asset_usage);
// Source: https://github.com/bevyengine/bevy/blob/85b488b73d6f6e75690962fba67a144d9beb6b88/examples/3d/skybox.rs#L152-L160
image.reinterpret_stacked_2d_as_array(image.height() / image.width());
image.texture_view_descriptor = Some(TextureViewDescriptor {
dimension: Some(TextureViewDimension::Cube),
..default()
});
images.add(image)
});
// Don't need the handle to be &mut
let env_map_handle = &*env_map_handle;
if background_shader.is_added() {
// We're using an environment map, so we don't need the ambient light
commands.remove_resource::<AmbientLight>();
}
let is_bg_outdated = background_shader.is_changed();
if is_bg_outdated {
let color = background_shader.color * background_shader.strength;
commands.insert_resource(ClearColor(color));
}
let camera_entities = cameras
.iter()
.filter_map(|(entity, cam)| (is_bg_outdated || cam.is_changed()).then_some(entity));
for camera_entity in camera_entities {
// See https://github.com/KhronosGroup/glTF-Blender-IO/blob/8573cc0dfb612091bfc1bcf6df55c18a44b9668a/addons/io_scene_gltf2/blender/com/gltf2_blender_conversion.py#L19
const PBR_WATTS_TO_LUMENS: f32 = 683.0;
commands.entity(camera_entity).insert(EnvironmentMapLight {
diffuse_map: env_map_handle.clone(),
specular_map: env_map_handle.clone(),
intensity: background_shader.strength * PBR_WATTS_TO_LUMENS,
}); });
} }
} }

View File

@ -3,7 +3,7 @@ use std::{
collections::HashMap, fs, time::Duration collections::HashMap, fs, time::Duration
}; };
use bevy_gltf_blueprints::{Animated, AnimationMarkers, BlueprintAnimationPlayerLink, BlueprintAnimations, BlueprintName, BlueprintsList, GltfBlueprintsSet, InstanceAnimationPlayerLink, InstanceAnimations}; use bevy_gltf_blueprints::{Animated, BlueprintAnimationPlayerLink, BlueprintAnimations, InstanceAnimationPlayerLink, InstanceAnimations, BlueprintName, BlueprintsList, GltfBlueprintsSet};
pub use in_game::*; pub use in_game::*;
use bevy::{ use bevy::{
@ -308,39 +308,6 @@ fn play_animations(
} }
} }
fn trigger_event_based_on_animation_marker(
bla: Query<(Entity, &AnimationMarkers, &InstanceAnimationPlayerLink, &InstanceAnimations)>,
animation_players: Query<&AnimationPlayer>,
animation_clips: Res<Assets<AnimationClip>>
) {
for (entity, markers, link, animations) in bla.iter() {
let animation_player = animation_players.get(link.0).unwrap();
let animation_clip = animation_clips.get(animation_player.animation_clip());
if animation_clip.is_some(){
// println!("Entity {:?} markers {:?}", entity, markers);
// println!("Player {:?} {}", animation_player.elapsed(), animation_player.completions());
let animation_total_length = animation_clip.unwrap().duration();
let animation_total_frames = 80; // FIXME just for testing
// TODO: we also need to take playback speed into account
let time_in_animation = animation_player.elapsed() - (animation_player.completions() as f32) * animation_total_length;//(animation_player.elapsed() / (animation_player.completions() as f32 + 1.0)) ;// / animation_total_length;
let time_bla = (animation_total_frames as f32 / animation_total_length) * time_in_animation ;
let frame = time_bla as u32;
// println!("time_in_animation {} out of {}, completions {}, // frame {}",time_in_animation, animation_total_length, animation_player.completions(), frame);
//animation_player.animation_clip()
let matching_animation_marker = &markers.0[&"Blueprint1_jump".to_string()];
if matching_animation_marker.contains_key(&frame) {
let matching_markers_per_frame = matching_animation_marker.get(&frame).unwrap();
println!("FOUND A MARKER {:?} at frame {}", matching_markers_per_frame, frame);
}
}
}
}
#[derive(Component, Reflect, Default, Debug)] #[derive(Component, Reflect, Default, Debug)]
#[reflect(Component)] #[reflect(Component)]
/// flag component for testing /// flag component for testing
@ -369,7 +336,7 @@ impl Plugin for GamePlugin {
.add_systems(OnEnter(AppState::AppRunning), setup_game) .add_systems(OnEnter(AppState::AppRunning), setup_game)
.add_systems(OnEnter(AppState::MenuRunning), setup_main_scene_animations) .add_systems(OnEnter(AppState::MenuRunning), setup_main_scene_animations)
.add_systems(Update, (animations, trigger_event_based_on_animation_marker) .add_systems(Update, animations
.run_if(in_state(AppState::AppRunning)) .run_if(in_state(AppState::AppRunning))
.after(GltfBlueprintsSet::AfterSpawn) .after(GltfBlueprintsSet::AfterSpawn)
) )

View File

@ -56,22 +56,8 @@ def copy_animation_data(source, target):
# sort animations alphabetically (case insensitive) so they have a defined order and match Blender's Action list # sort animations alphabetically (case insensitive) so they have a defined order and match Blender's Action list
blender_actions.sort(key = lambda a: a.name.lower()) blender_actions.sort(key = lambda a: a.name.lower())
markers_per_animation = {}
for action in blender_actions: for action in blender_actions:
animation_name = blender_tracks[action.name] animations.append(blender_tracks[action.name])
animations.append(animation_name)
markers_per_animation[animation_name] = {}
print("markers", action.pose_markers, "for", action.name)
for marker in action.pose_markers:
if marker.frame not in markers_per_animation[animation_name]:
markers_per_animation[animation_name][marker.frame] = []
print(" marker", marker.name, marker.frame)
markers_per_animation[animation_name][marker.frame].append(marker.name)
print("animations", animations) print("animations", animations)
"""if target.animation_data == None: """if target.animation_data == None:
@ -81,29 +67,13 @@ def copy_animation_data(source, target):
with bpy.context.temp_override(active_object=source, selected_editable_objects=[target]): with bpy.context.temp_override(active_object=source, selected_editable_objects=[target]):
bpy.ops.object.make_links_data(type='ANIMATION') bpy.ops.object.make_links_data(type='ANIMATION')
# we add an "animated" flag component # we add an "animated" flag component
target['Animated'] = f'(animations: {animations})'.replace("'", '"') target['Animated'] = f'(animations: {animations})'.replace("'", '"') #'(animations: [])' #
markers_formated = '{'
for animation in markers_per_animation.keys():
markers_formated += f'"{animation}":'
markers_formated += "{"
for frame in markers_per_animation[animation].keys():
markers = markers_per_animation[animation][frame]
markers_formated += f"{frame}:{markers}, ".replace("'", '"')
markers_formated += '}, '
markers_formated += '}'
print("markers_formated", markers_formated)
target["AnimationMarkers"] = f'( {markers_formated} )'
#'({"animation_name": {5: ["Marker_1"]} })'
#f'({json.dumps(markers_per_animation)})'
"""print("copying animation data for", source.name, target.animation_data) """print("copying animation data for", source.name, target.animation_data)
properties = [p.identifier for p in source.animation_data.bl_rna.properties if not p.is_readonly] properties = [p.identifier for p in source.animation_data.bl_rna.properties if not p.is_readonly]
for prop in properties: for prop in properties:
print("copying stuff", prop) print("copying stuff", prop)
setattr(target.animation_data, prop, getattr(source.animation_data, prop))""" setattr(target.animation_data, prop, getattr(source.animation_data, prop))"""
def duplicate_object(object, parent, combine_mode, destination_collection, library_collections, legacy_mode, nester=""): def duplicate_object(object, parent, combine_mode, destination_collection, library_collections, legacy_mode, nester=""):
copy = None copy = None
@ -125,10 +95,6 @@ def duplicate_object(object, parent, combine_mode, destination_collection, libra
children_per_collection = {} children_per_collection = {}
get_sub_collections([object.instance_collection], root_node, children_per_collection) get_sub_collections([object.instance_collection], root_node, children_per_collection)
empty_obj["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})" empty_obj["BlueprintsList"] = f"({json.dumps(dict(children_per_collection))})"
# empty_obj["AnimationMarkers"] = '({"animation_name": {5: "Marker_1"} })'
#'({5: "sdf"})'#.replace('"',"'") #f"({json.dumps(dict(animation_foo))})"
#empty_obj["Assets"] = {"Animations": [], "Materials": [], "Models":[], "Textures":[], "Audio":[], "Other":[]} #empty_obj["Assets"] = {"Animations": [], "Materials": [], "Models":[], "Textures":[], "Audio":[], "Other":[]}
# we copy custom properties over from our original object to our empty # we copy custom properties over from our original object to our empty
@ -143,7 +109,10 @@ def duplicate_object(object, parent, combine_mode, destination_collection, libra
object.name = original_name + "____bak" object.name = original_name + "____bak"
copy = object.copy() copy = object.copy()
copy.name = original_name copy.name = original_name
# FIXME: orphan data comes from this one, not even sure if this copying is needed at all
"""if object.data:
data = object.data.copy()
obj_copy.data = data"""
destination_collection.objects.link(copy) destination_collection.objects.link(copy)