sarkahn / bevy_ascii_terminal

A simple terminal for rendering ascii in bevy.
MIT License
95 stars 13 forks source link

ToWorld produces wrong coordinates on high DPI screens #13

Open rparrett opened 1 year ago

rparrett commented 1 year ago

To reproduce, edit the scale factor override in the example below and move the mouse around. With scale factors != 1.0, the cursor displayed in the terminal does not match the OS cursor.

Note: I discovered this while attempting to play a Bevy Jam 3 entry on a macbook.

use bevy::{
    prelude::*,
    window::{PrimaryWindow, WindowResolution},
};
use bevy_ascii_terminal::{prelude::*, TerminalPlugin, ToWorld};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                resolution: WindowResolution::default().with_scale_factor_override(1.25),
                ..default()
            }),
            ..default()
        }))
        .add_plugin(TerminalPlugin)
        .insert_resource(ClearColor(Color::BLACK))
        .add_startup_system(spawn_terminal)
        .add_system(cursor)
        .run()
}

fn spawn_terminal(mut commands: Commands) {
    let mut term = Terminal::new([20, 20]).with_border(Border::single_line());

    commands.spawn((TerminalBundle::from(term), AutoCamera, ToWorld::default()));
}

fn cursor(
    query: Query<&ToWorld>,
    mut term_query: Query<&mut Terminal>,
    window_query: Query<&Window, With<PrimaryWindow>>,
) {
    let Ok(to_world) = query.get_single() else {
        return
    };

    let Ok(window) = window_query.get_single() else {
        return
    };

    let Some(cursor_pos) = window.cursor_position() else {
        return
    };

    let Some(world_pos) = to_world.screen_to_world(cursor_pos) else {
        return
    };

    let Ok(mut term) = term_query.get_single_mut() else {
        return
    };

    let tile_pos = to_world.world_to_tile(world_pos);

    if !term.in_bounds(tile_pos) {
        return;
    }

    term.clear();
    term.put_char(tile_pos, 'X'.fg(Color::GREEN));
}