Generate skeleton attention and genepool catalogs (#49)
Some checks failed
Native code generation / deterministic (push) Successful in 5m4s
Imaging and meshing gate / native (push) Failing after 17s
JPEG 2000 feature / linux (push) Failing after 59s
Skia feature / linux (push) Failing after 1m31s

This commit is contained in:
2026-08-09 09:28:40 +00:00
parent 5f83ce61e1
commit 4a32025e37
18 changed files with 7018 additions and 423 deletions

View File

@@ -0,0 +1,208 @@
//! Golden fixtures for skeleton, attention, and genepool generation.
#![allow(clippy::float_cmp)] // Golden XML values must retain their exact f32 representation.
use libremetaverse::rendering::Joint;
use libremetaverse::{Genepool, LindenAttentions, LookAtType};
fn skeleton_counts(root: &Joint) -> (usize, usize) {
let mut bones = 1;
let mut collision_volumes = root.collision_volume().len();
if let Some(children) = root.bone() {
for child in children {
let (child_bones, child_collision_volumes) = skeleton_counts(&child);
bones += child_bones;
collision_volumes += child_collision_volumes;
}
}
(bones, collision_volumes)
}
#[test]
fn default_skeleton_matches_the_complete_pinned_hierarchy() {
let skeleton = libremetaverse::rendering::LindenSkeleton::get_default().unwrap();
assert_eq!(skeleton.version(), 2.0);
assert!(!skeleton.version_specified());
assert_eq!(skeleton.num_bones(), "133");
assert_eq!(skeleton.num_collision_volumes(), "26");
assert_eq!(skeleton_counts(&skeleton.bone()), (133, 26));
assert_eq!(skeleton.get_all_joints().unwrap().count(), 133);
let pelvis = skeleton.bone();
assert_eq!(pelvis.base.name(), "mPelvis");
assert_eq!(pelvis.base.pos(), vec![0.0, 0.0, 1.067]);
assert_eq!(pelvis.base.rot(), vec![0.0, 0.0, 0.0]);
assert_eq!(pelvis.base.scale(), vec![1.0, 1.0, 1.0]);
assert_eq!(pelvis.base.end(), vec![0.0, 0.0, 0.084]);
assert_eq!(pelvis.pivot(), vec![0.0, 0.0, 1.067_015]);
assert_eq!(pelvis.base.group(), "Torso");
assert_eq!(pelvis.base.support(), "base");
assert!(pelvis.base.reposition());
assert!(!pelvis.connected());
assert_eq!(
pelvis.get_aliases_list().unwrap(),
["hip", "avatar_mPelvis"]
);
assert_eq!(pelvis.collision_volume().len(), 2);
assert_eq!(pelvis.collision_volume()[0].base.name(), "PELVIS");
let by_alias = skeleton.get_bone("hip".to_owned()).unwrap().unwrap();
assert_eq!(by_alias.base.name(), "mPelvis");
assert_eq!(
libremetaverse::rendering::LindenSkeleton::load_with_method().unwrap(),
skeleton
);
assert_eq!(
libremetaverse::rendering::LindenSkeleton::load_with_string(None).unwrap(),
skeleton
);
}
#[test]
fn skeleton_records_preserve_mutable_mapped_properties() {
let mut base = libremetaverse::rendering::JointBase::new().unwrap();
base.set_name("joint".to_owned());
base.set_pos(vec![1.0, 2.0, 3.0]);
base.set_rot(vec![4.0, 5.0, 6.0]);
base.set_scale(vec![7.0, 8.0, 9.0]);
base.set_group("group".to_owned());
base.set_support("extended".to_owned());
base.set_end(vec![10.0, 11.0, 12.0]);
base.set_reposition(true);
assert_eq!(base.name(), "joint");
assert_eq!(base.pos(), vec![1.0, 2.0, 3.0]);
assert_eq!(base.rot(), vec![4.0, 5.0, 6.0]);
assert_eq!(base.scale(), vec![7.0, 8.0, 9.0]);
assert_eq!(base.group(), "group");
assert_eq!(base.support(), "extended");
assert_eq!(base.end(), vec![10.0, 11.0, 12.0]);
assert!(base.reposition());
let mut joint = libremetaverse::rendering::Joint::new().unwrap();
joint.base = base;
joint.set_aliases("one two".to_owned());
joint.set_pivot(vec![13.0, 14.0, 15.0]);
joint.set_connected(true);
joint.set_collision_volume(vec![
libremetaverse::rendering::CollisionVolume::new().unwrap(),
]);
joint.set_bone(None);
assert_eq!(joint.aliases(), "one two");
assert_eq!(joint.pivot(), vec![13.0, 14.0, 15.0]);
assert!(joint.connected());
assert_eq!(joint.collision_volume().len(), 1);
assert!(joint.bone().is_none());
let mut skeleton = libremetaverse::rendering::LindenSkeleton::new().unwrap();
skeleton.set_bone(joint);
skeleton.set_version(3.0);
skeleton.set_version_specified(true);
skeleton.set_num_bones("1".to_owned());
skeleton.set_num_collision_volumes("1".to_owned());
assert_eq!(skeleton.version(), 3.0);
assert!(skeleton.version_specified());
assert_eq!(skeleton.num_bones(), "1");
assert_eq!(skeleton.num_collision_volumes(), "1");
}
#[test]
fn attention_catalogs_match_default_and_updated_fixtures() {
let default = LindenAttentions::default();
let updated = LindenAttentions::updated();
assert_eq!(default.len(), 2);
assert_eq!(updated.len(), 2);
assert_eq!(default[0].name(), "Masculine");
assert_eq!(default[1].name(), "Feminine");
assert!(
default
.iter()
.chain(&updated)
.all(|set| set.entries().len() == 11)
);
let none = default[0].get(LookAtType::None).unwrap();
assert_eq!(none.priority(), 0.0);
assert_eq!(none.timeout(), 0.0);
let clear = default[0].get(LookAtType::Clear).unwrap();
assert_eq!(clear.priority(), 0.0);
assert_eq!(clear.timeout(), 0.0);
let default_conversation = default[0].get(LookAtType::Conversation).unwrap();
assert_eq!(default_conversation.priority(), 0.0);
assert_eq!(default_conversation.timeout(), -1.0);
let updated_conversation = updated[0].get(LookAtType::Conversation).unwrap();
assert_eq!(updated_conversation.priority(), 5.0);
assert_eq!(updated_conversation.timeout(), 3.0);
assert_eq!(
LindenAttentions::updated_feminine()
.get(LookAtType::Focus)
.unwrap()
.timeout(),
10.0
);
assert_eq!(LindenAttentions::default_masculine(), default[0]);
assert_eq!(LindenAttentions::default_feminine(), default[1]);
assert_eq!(LindenAttentions::updated_masculine(), updated[0]);
assert_eq!(LindenAttentions::updated_feminine(), updated[1]);
let mut changed = updated_conversation;
changed.set_priority(8.0);
changed.set_timeout(9.0);
assert_eq!(changed.priority(), 8.0);
assert_eq!(changed.timeout(), 9.0);
let mut set = default[0].clone();
set.set_name("Changed".to_owned());
set.set_entries(vec![changed.clone()]);
assert_eq!(set.name(), "Changed");
assert_eq!(set.entries(), vec![changed]);
assert_eq!(
set.get(LookAtType::Clear),
Err(libremetaverse::Error::IndexOutOfRange)
);
}
#[test]
fn genepool_matches_every_pinned_archetype_and_supports_lookup() {
let archetypes = Genepool::archetypes();
assert_eq!(archetypes.len(), 24);
assert!(
archetypes
.iter()
.all(|archetype| archetype.params().len() == 140)
);
assert_eq!(
archetypes
.iter()
.map(|archetype| archetype.params().len())
.sum::<usize>(),
3360
);
assert_eq!(archetypes[0].name(), "M W Skinny");
assert_eq!(Genepool::find_index("M W Skinny".to_owned()).unwrap(), 0);
assert_eq!(Genepool::find_index("missing".to_owned()).unwrap(), -1);
assert_eq!(Genepool::get(0).unwrap(), archetypes[0]);
assert_eq!(
Genepool::get(-1),
Err(libremetaverse::Error::IndexOutOfRange)
);
assert_eq!(
Genepool::get(24),
Err(libremetaverse::Error::IndexOutOfRange)
);
let mut first = archetypes[0].params()[0].clone();
assert_eq!(first.id(), 1);
assert_eq!(first.name(), "Big_Brow");
assert_eq!(first.value(), 1.54);
first.set_id(99);
first.set_name("Changed".to_owned());
first.set_value(0.25);
assert_eq!(first.id(), 99);
assert_eq!(first.name(), "Changed");
assert_eq!(first.value(), 0.25);
let mut archetype = archetypes[0].clone();
archetype.set_name("Changed archetype".to_owned());
archetype.set_params(vec![first.clone()]);
assert_eq!(archetype.name(), "Changed archetype");
assert_eq!(archetype.params(), vec![first]);
}