1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::graphics::gpu::{self, Font, Gpu, TargetView, Texture, Vertex};
use crate::graphics::{Color, Transformation};
/// A rendering target.
///
/// In Coffee, all the draw operations need an explicit [`Target`]. You can
/// obtain one from a [`Frame`] or a [`Canvas`].
///
/// The default coordinate system of a [`Target`] has the origin `(0, 0)` at
/// its top-left corner and `(Target::width, Target::height)` at its bottom-right
/// corner.
///
/// [`Target`]: struct.Target.html
/// [`Frame`]: struct.Frame.html
/// [`Canvas`]: struct.Canvas.html
pub struct Target<'a> {
gpu: &'a mut Gpu,
view: &'a TargetView,
transformation: Transformation,
}
impl<'a> Target<'a> {
pub(super) fn new(
gpu: &'a mut Gpu,
view: &'a TargetView,
width: f32,
height: f32,
) -> Self {
Target {
gpu,
view,
transformation: Transformation::orthographic(width, height),
}
}
pub(super) fn with_transformation(
gpu: &'a mut Gpu,
view: &'a TargetView,
width: f32,
height: f32,
transformation: Transformation,
) -> Self {
let mut target = Self::new(gpu, view, width, height);
target.transformation = transformation * target.transformation;
target
}
/// Creates a new [`Target`] applying the given transformation.
///
/// This is equivalent to multiplying the current [`Target`] transform by
/// the provided transform.
///
/// You can use blocks to emulate a transformation stack! Imagine we want to
/// apply a camera translation with some zoom, but only use it to draw a
/// particular scene. We can simply do:
///
/// ```
/// use coffee::graphics::{Frame, Transformation, Vector};
///
/// fn draw_something(frame: &mut Frame) {
/// let mut target = frame.as_target();
///
/// // We can draw stuff on `target` here
/// // ...
///
/// {
/// let transformation = Transformation::scale(2.0)
/// * Transformation::translate(Vector::new(10.0, 10.0));
///
/// let mut camera = target.transform(transformation);
///
/// // Use `camera` to draw the particular scene here
/// // ...
/// }
///
/// // We can keep using `target` as if no transformation happened
/// // ...
/// }
/// ```
///
/// [`Target`]: struct.Target.html
pub fn transform(&mut self, transformation: Transformation) -> Target<'_> {
Target {
gpu: self.gpu,
view: self.view,
transformation: self.transformation * transformation,
}
}
/// Clears the [`Target`] with the given [`Color`].
///
/// [`Target`]: struct.Target.html
/// [`Color`]: struct.Color.html
pub fn clear(&mut self, color: Color) {
self.gpu.clear(&self.view, color);
}
pub(super) fn draw_triangles(
&mut self,
vertices: &[Vertex],
indices: &[u32],
) {
self.gpu.draw_triangles(
vertices,
indices,
&self.view,
&self.transformation,
);
}
pub(super) fn draw_texture_quads(
&mut self,
texture: &Texture,
instances: &[gpu::Quad],
) {
self.gpu.draw_texture_quads(
texture,
instances,
&self.view,
&self.transformation,
);
}
pub(in crate::graphics) fn draw_font(&mut self, font: &mut Font) {
self.gpu.draw_font(font, &self.view, self.transformation);
}
}
impl<'a> std::fmt::Debug for Target<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Target {{ transformation: {:?} }}", self.transformation)
}
}