clippy: add AR face ^_^
This commit is contained in:
parent
817a5e2a96
commit
d064680d60
|
@ -7,6 +7,8 @@ These cubes are interchangeable, solar panel plated, driven by strong reaction w
|
|||
|
||||
The shape of a Clippy™ can change quickly to solve a variety of space problems. Off-the-shelf plug-and-play Clippy™ modules further enhance their agency with additional tools, such as propulsion modules, sensors, or manipulators.
|
||||
|
||||
A Clippy™ Convenience Companion will broadcast an Augmented Reality overlay that resembles a face, in the somewhat antiquated "kaomoji" style of the late 1900's, typically a friendly face to instill trust and kindness in viewers. How a unified persona with aligned intentions emerges from the interactions of the individual Clippy™ cubes is, as of writing, still subject to debate.
|
||||
|
||||
Clippy™ is inspired by [self-assembling cube robots](https://www.youtube.com/watch?v=hI5UDKaWJOo), by the [paperclip maximizer thought experiment](https://en.wikipedia.org/w/index.php?title=Instrumental_convergence&oldid=1210129297#Paperclip_maximizer) (which is also the source of the name), by [Star Gate's Replicators](https://stargate.fandom.com/wiki/Replicator), and finally, by [Fallout New Vegas' "Yes Man" robot](https://fallout.fandom.com/wiki/Yes_Man).
|
||||
|
||||
## MeteorAceGT™ Sports Racing Capsule
|
||||
|
|
BIN
assets/models/clippy_ar.glb
Normal file
BIN
assets/models/clippy_ar.glb
Normal file
Binary file not shown.
|
@ -67,6 +67,7 @@ struct ParserState {
|
|||
suit_integrity: f32,
|
||||
light_brightness: f32,
|
||||
light_color: Option<Color>,
|
||||
ar_model: Option<String>,
|
||||
|
||||
// Chat fields
|
||||
delay: f64,
|
||||
|
@ -121,6 +122,7 @@ impl Default for ParserState {
|
|||
suit_integrity: 1.0,
|
||||
light_brightness: 0.0,
|
||||
light_color: None,
|
||||
ar_model: None,
|
||||
|
||||
delay: 0.0,
|
||||
text: "".to_string(),
|
||||
|
@ -453,6 +455,9 @@ pub fn load_defs(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
["armodel", asset_name] => {
|
||||
state.ar_model = Some(asset_name.to_string());
|
||||
}
|
||||
|
||||
// Parsing chats
|
||||
["chat", chat_name] => {
|
||||
|
@ -571,6 +576,8 @@ fn spawn_entities(
|
|||
}
|
||||
}
|
||||
else if state.class == DefClass::Actor {
|
||||
let actor_entity;
|
||||
{
|
||||
let mut actor = commands.spawn_empty();
|
||||
actor.insert(actor::Actor {
|
||||
id: state.id.clone(),
|
||||
|
@ -699,6 +706,24 @@ fn spawn_entities(
|
|||
..default()
|
||||
});
|
||||
}
|
||||
if let Some(_) = state.ar_model {
|
||||
actor.insert(hud::AugmentedRealityOverlayBroadcaster);
|
||||
}
|
||||
actor_entity = actor.id();
|
||||
}
|
||||
|
||||
if let Some(ar_asset_name) = &state.ar_model {
|
||||
commands.spawn((
|
||||
hud::AugmentedRealityOverlay {
|
||||
owner: actor_entity,
|
||||
},
|
||||
SceneBundle {
|
||||
scene: asset_server.load(world::asset_name_to_path(ar_asset_name)),
|
||||
visibility: Visibility::Hidden,
|
||||
..default()
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ actor -3300 10 0 pizzeria
|
|||
actor -33 0 4 clippy
|
||||
name "Clippy™ Convenience Companion"
|
||||
relativeto pizzeria
|
||||
armodel clippy_ar
|
||||
angularmomentum 0 0 0
|
||||
wants maxrotation 0
|
||||
wants maxvelocity 0
|
||||
|
|
51
src/hud.rs
51
src/hud.rs
|
@ -24,6 +24,7 @@ impl Plugin for HudPlugin {
|
|||
app.add_systems(Startup, setup);
|
||||
app.add_systems(Update, (
|
||||
update_hud,
|
||||
update_ar_overlays,
|
||||
handle_input,
|
||||
handle_target_event,
|
||||
));
|
||||
|
@ -33,6 +34,9 @@ impl Plugin for HudPlugin {
|
|||
.after(camera::apply_input_to_player)
|
||||
.before(TransformSystem::TransformPropagate),
|
||||
));
|
||||
app.insert_resource(AugmentedRealityState {
|
||||
overlays_visible: false,
|
||||
});
|
||||
app.insert_resource(Log {
|
||||
logs: VecDeque::with_capacity(LOG_MAX),
|
||||
needs_rerendering: true,
|
||||
|
@ -52,6 +56,17 @@ impl Plugin for HudPlugin {
|
|||
#[derive(Component)] struct Selectagon;
|
||||
#[derive(Component)] pub struct IsTargeted;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct AugmentedRealityState {
|
||||
pub overlays_visible: bool,
|
||||
}
|
||||
|
||||
#[derive(Component)] pub struct AugmentedRealityOverlayBroadcaster;
|
||||
#[derive(Component)]
|
||||
pub struct AugmentedRealityOverlay {
|
||||
pub owner: Entity,
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct FPSUpdateTimer(Timer);
|
||||
|
||||
|
@ -645,3 +660,39 @@ fn update_target_selectagon(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_ar_overlays (
|
||||
q_owners: Query<(Entity, &Transform, &Visibility), (With<AugmentedRealityOverlayBroadcaster>, Without<AugmentedRealityOverlay>)>,
|
||||
mut q_overlays: Query<(&mut Transform, &mut Visibility, &mut AugmentedRealityOverlay)>,
|
||||
settings: ResMut<settings::Settings>,
|
||||
mut state: ResMut<AugmentedRealityState>,
|
||||
) {
|
||||
let (need_activate, need_clean, need_update);
|
||||
if settings.hud_active {
|
||||
need_activate = !state.overlays_visible;
|
||||
need_clean = false;
|
||||
}
|
||||
else {
|
||||
need_activate = false;
|
||||
need_clean = state.overlays_visible;
|
||||
}
|
||||
need_update = settings.hud_active;
|
||||
state.overlays_visible = settings.hud_active;
|
||||
|
||||
if need_update || need_clean || need_activate {
|
||||
'outer: for (mut trans, mut vis, ar) in &mut q_overlays {
|
||||
for (owner_id, owner_trans, owner_vis) in &q_owners {
|
||||
if owner_id == ar.owner {
|
||||
*trans = *owner_trans;
|
||||
if need_clean {
|
||||
*vis = Visibility::Hidden;
|
||||
}
|
||||
else {
|
||||
*vis = *owner_vis;
|
||||
}
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ pub fn asset_name_to_path(name: &str) -> &'static str {
|
|||
"pizzasign" => "models/pizzasign.glb#Scene0",
|
||||
"selectagon" => "models/selectagon.glb#Scene0",
|
||||
"clippy" => "models/clippy.glb#Scene0",
|
||||
"clippy_ar" => "models/clippy_ar.glb#Scene0",
|
||||
_ => "models/error.glb#Scene0",
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue