Name Message Date
📄 main.rs Dog looks at cursor 6 days ago
📄 src/main.rs
use bevy::{
    DefaultPlugins,
    app::{App, Startup, Update},
    asset::AssetServer,
    camera::{Camera, Camera3d, OrthographicProjection, Projection, ScalingMode},
    ecs::{
        component::Component,
        query::With,
        system::{Commands, Res, Single},
    },
    gltf::GltfAssetLabel,
    light::DirectionalLight,
    math::{Dir3, Vec3, primitives::InfinitePlane3d},
    scene::SceneRoot,
    transform::components::{GlobalTransform, Transform},
    window::Window,
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, control_dog)
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn((
        Camera3d::default(),
        Projection::from(OrthographicProjection {
            scaling_mode: ScalingMode::FixedVertical {
                viewport_height: 10.0,
            },
            ..OrthographicProjection::default_3d()
        }),
        Transform::from_xyz(0.0, 10.0, 0.0).looking_to(Vec3::NEG_Y, Vec3::Z),
    ));

    commands.spawn((
        SceneRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animal-dog.glb"))),
        Transform::from_xyz(0.0, 0.0, 0.0),
        Dog::default(),
    ));

    commands.spawn((
        DirectionalLight {
            illuminance: 15000.0,
            ..Default::default()
        },
        Transform::from_xyz(0.0, 0.0, 0.0).looking_to(Vec3::NEG_Y, Vec3::Z),
    ));
}

#[derive(Component, Default)]
struct Dog;

fn control_dog(
    window: Single<&Window>,
    camera: Single<(&Camera, &GlobalTransform)>,
    mut dog: Single<&mut Transform, With<Dog>>,
) {
    let (camera, camera_transform) = *camera;

    let Some(cursor_position) = window
        .cursor_position()
        .and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
    else {
        return;
    };

    let Some(cursor_position) =
        cursor_position.plane_intersection_point(Vec3::ZERO, InfinitePlane3d { normal: Dir3::Y })
    else {
        return;
    };

    dog.look_at(-cursor_position, Vec3::Y);
}