Skip to content

Add utils for rendering #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rlbot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rlbot_flat::planus::{self, ReadAsRoot};
use thiserror::Error;

pub mod agents;
pub mod render;
pub mod state_builder;
pub mod util;

Expand Down
208 changes: 208 additions & 0 deletions rlbot/src/render.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
use rlbot_flat::flat::{
Color, Line3D, PolyLine3D, Rect2D, Rect3D, RenderAnchor, RenderGroup, RenderMessage, String2D,
String3D, TextHAlign, TextVAlign, Vector3,
};

#[rustfmt::skip]
pub mod colors {
use rlbot_flat::flat::Color;
pub const TRANSPARENT: Color = Color { r: 0, g: 0, b: 0, a: 0 };
pub const BLACK: Color = Color { r: 0, g: 0, b: 0, a: 255 };
pub const WHITE: Color = Color { r: 255, g: 255, b: 255, a: 255 };
pub const RED: Color = Color { r: 255, g: 0, b: 0, a: 255 };
pub const GREEN: Color = Color { r: 0, g: 128, b: 0, a: 255 };
pub const BLUE: Color = Color { r: 0, g: 0, b: 255, a: 255 };
pub const LIME: Color = Color { r: 0, g: 255, b: 0, a: 255 };
pub const YELLOW: Color = Color { r: 255, g: 255, b: 0, a: 255 };
pub const ORANGE: Color = Color { r: 255, g: 128, b: 0, a: 255 };
pub const CYAN: Color = Color { r: 0, g: 255, b: 255, a: 255 };
pub const PINK: Color = Color { r: 255, g: 0, b: 255, a: 255 };
pub const PURPLE: Color = Color { r: 128, g: 0, b: 128, a: 255 };
pub const TEAL: Color = Color { r: 0, g: 128, b: 128, a: 255 };
}

/// The Renderer allows of easy construction of [RenderGroup]s for in-game debug rendering.
/// When done, call [build] and queue the resulting [RenderGroup] in the packet queue.
///
/// Example:
/// ```ignore
/// use rlbot::render::{Renderer};
/// use rlbot::render::colors::{BLUE, GREEN, RED};
/// let mut draw = Renderer::new(0);
/// draw.line_3d(car.pos, car.pos + car.forward() * 120., RED);
/// draw.line_3d(car.pos, car.pos + car.rightward() * 120., GREEN);
/// draw.line_3d(car.pos, car.pos + car.upward() * 120., BLUE);
/// packet_queue.push(draw.build());
/// ```
pub struct Renderer {
pub group: RenderGroup,
}

impl Renderer {
/// Create a new Renderer.
/// Each render group must have a unique id.
/// Re-using an id will result in overwriting (watch out when using hiveminds).
pub fn new(group_id: i32) -> Self {
Self {
group: RenderGroup {
render_messages: vec![],
id: group_id,
},
}
}

/// Get the resulting [RenderGroup].
pub fn build(self) -> RenderGroup {
self.group
}

/// Add a [RenderMessage] to this group.
pub fn push(&mut self, message: impl Into<RenderMessage>) {
self.group.render_messages.push(message.into());
}

/// Draws a line between two anchors in 3d space.
pub fn line_3d(
&mut self,
start: impl Into<RenderAnchor>,
end: impl Into<RenderAnchor>,
color: Color,
) {
self.group.render_messages.push(
Line3D {
start: Box::new(start.into()),
end: Box::new(end.into()),
color,
}
.into(),
);
}

/// Draws a line going through each of the provided points.
pub fn polyline_3d(
&mut self,
points: impl IntoIterator<Item = impl Into<Vector3>>,
color: Color,
) {
self.group.render_messages.push(
PolyLine3D {
points: points.into_iter().map(|p| p.into()).collect(),
color,
}
.into(),
);
}

/// Draws text in 2d space.
/// X and y uses screen-space coordinates, i.e. 0.1 is 10% of the screen width/height.
/// Use `set_resolution` to change to pixel coordinates.
/// Characters of the font are 20 pixels tall and 10 pixels wide when `scale == 1.0`.
/// Consider using [push] and `..default()` when using multiple default values.
pub fn string_2d(
&mut self,
text: String,
x: f32,
y: f32,
scale: f32,
foreground: Color,
background: Color,
h_align: TextHAlign,
v_align: TextVAlign,
) {
self.group.render_messages.push(
String2D {
text,
x,
y,
scale,
foreground,
background,
h_align,
v_align,
}
.into(),
);
}

/// Draws text anchored in 3d space.
/// Characters of the font are 20 pixels tall and 10 pixels wide when `scale == 1.0`.
/// Consider using [push] and `..default()` when using multiple default values.
pub fn string_3d(
&mut self,
text: String,
anchor: impl Into<RenderAnchor>,
scale: f32,
foreground: Color,
background: Color,
h_align: TextHAlign,
v_align: TextVAlign,
) {
self.group.render_messages.push(
String3D {
text,
anchor: Box::new(anchor.into()),
scale,
foreground,
background,
h_align,
v_align,
}
.into(),
);
}

/// Draws a rectangle anchored in 2d space.
/// X, y, width, and height uses screen-space coordinates, i.e. 0.1 is 10% of the screen width/height.
/// Use `set_resolution` to change to pixel coordinates.
/// Consider using [push] and `..default()` when using multiple default values.
pub fn rect_2d(
&mut self,
x: f32,
y: f32,
width: f32,
height: f32,
color: Color,
h_align: TextHAlign,
v_align: TextVAlign,
) {
self.group.render_messages.push(
Rect2D {
x,
y,
width,
height,
color,
h_align,
v_align,
}
.into(),
);
}

/// Draws a rectangle anchored in 3d space.
/// Width and height are screen-space sizes, i.e. 0.1 is 10% of the screen width/height.
/// Use `set_resolution` to change to pixel coordinates.
/// The size does not change based on distance to the camera.
/// Consider using [push] and `..default()` when using multiple default values.
pub fn rect_3d(
&mut self,
anchor: impl Into<RenderAnchor>,
width: f32,
height: f32,
color: Color,
h_align: TextHAlign,
v_align: TextVAlign,
) {
self.group.render_messages.push(
Rect3D {
anchor: Box::new(anchor.into()),
width,
height,
color,
h_align,
v_align,
}
.into(),
);
}
}
18 changes: 18 additions & 0 deletions rlbot_flat/src/glam_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,21 @@ impl From<glam::Vec3A> for flat::Vector3 {
}
}
}

impl From<glam::Vec3> for flat::RenderAnchor {
fn from(value: glam::Vec3) -> Self {
Self {
world: value.into(),
relative: None,
}
}
}

impl From<glam::Vec3A> for flat::RenderAnchor {
fn from(value: glam::Vec3A) -> Self {
Self {
world: value.into(),
relative: None,
}
}
}
47 changes: 47 additions & 0 deletions rlbot_flat/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,55 @@ impl From<flat::InterfaceMessage> for flat::InterfacePacket {
flat::InterfacePacket { message }
}
}

impl From<flat::CoreMessage> for flat::CorePacket {
fn from(message: flat::CoreMessage) -> Self {
flat::CorePacket { message }
}
}

macro_rules! from_render_message {
( $( $t:ident ),* ) => {
$(
impl From<flat::$t> for flat::RenderMessage {
fn from(value: flat::$t) -> Self {
Self {
variety: flat::RenderType::$t(Box::new(value)),
}
}
}
)*
};
}

from_render_message!(Line3D, PolyLine3D, String2D, String3D, Rect2D, Rect3D);

impl From<flat::Vector3> for flat::RenderAnchor {
fn from(value: flat::Vector3) -> Self {
Self {
world: value,
relative: None,
}
}
}
Comment on lines +76 to +83
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should consider something like this instead? It would also remove the need for this

Suggested change
impl From<flat::Vector3> for flat::RenderAnchor {
fn from(value: flat::Vector3) -> Self {
Self {
world: value,
relative: None,
}
}
}
impl flat::RenderAnchor {
pub fn from_vec(value: impl Into<flat::Vector3>) -> Self {
Self {
world: value.into(),
relative: None,
}
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like it because RenderAnchor::from_vec(v) is so much longer than v.into() 😅 And it would be inconsistent with From<CarAnchor> and From<BallAnchor> for relative.


impl From<flat::RelativeAnchor> for flat::RenderAnchor {
fn from(value: flat::RelativeAnchor) -> Self {
Self {
world: flat::Vector3::default(),
relative: Some(value),
}
}
}

impl From<flat::CarAnchor> for flat::RelativeAnchor {
fn from(value: flat::CarAnchor) -> Self {
flat::RelativeAnchor::CarAnchor(Box::new(value))
}
}

impl From<flat::BallAnchor> for flat::RelativeAnchor {
fn from(value: flat::BallAnchor) -> Self {
flat::RelativeAnchor::BallAnchor(Box::new(value))
}
}