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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
//! Target for off-screen 2D rendering into a texture.
const sf = struct {
pub usingnamespace @import("../sfml.zig");
pub usingnamespace sf.system;
pub usingnamespace sf.graphics;
};
const RenderTexture = @This();
// Constructor/destructor
/// Inits a render texture with a size (use createWithDepthBuffer if you want a depth buffer)
pub fn create(size: sf.Vector2u) !RenderTexture {
var rtex = sf.c.sfRenderTexture_create(size.x, size.y, 0); //0 means no depth buffer
if (rtex) |t| {
return RenderTexture{ ._ptr = t };
} else return sf.Error.nullptrUnknownReason;
}
/// Inits a render texture with a size, it will have a depth buffer
pub fn createWithDepthBuffer(size: sf.Vector2u) !RenderTexture {
var rtex = sf.c.sfRenderTexture_create(size.x, size.y, 1);
if (rtex) |t| {
return .{ ._ptr = t };
} else return sf.Error.nullptrUnknownReason;
}
/// Destroys this render texture
pub fn destroy(self: *RenderTexture) void {
sf.c.sfRenderTexture_destroy(self._ptr);
}
// Drawing functions
/// Clears the drawing target with a color
pub fn clear(self: *RenderTexture, color: sf.Color) void {
sf.c.sfRenderTexture_clear(self._ptr, color._toCSFML());
}
/// Updates the texture with what has been drawn on the render area
pub fn display(self: *RenderTexture) void {
sf.c.sfRenderTexture_display(self._ptr);
}
/// Draw something on the texture (won't be visible until display is called)
/// Object must have a sfDraw function (look at CircleShape for reference)
/// You can pass a render state or null for default
pub fn draw(self: *RenderTexture, to_draw: anytype, states: ?sf.RenderStates) void {
const T = @TypeOf(to_draw);
if (comptime @import("std").meta.trait.hasFn("sfDraw")(T)) {
// Inline call of object's draw function
if (states) |s| {
var cstates = s._toCSFML();
@call(.{ .modifier = .always_inline }, T.sfDraw, .{ to_draw, self.*, &cstates });
} else
@call(.{ .modifier = .always_inline }, T.sfDraw, .{ to_draw, self.*, null });
// to_draw.sfDraw(self, states);
} else @compileError("You must provide a drawable object (struct with \"sfDraw\" method).");
}
/// Gets a const reference to the target texture (the reference doesn't change)
pub fn getTexture(self: RenderTexture) sf.Texture {
const tex = sf.c.sfRenderTexture_getTexture(self._ptr);
return sf.Texture{ ._const_ptr = tex.? };
}
// Texture related stuff
/// Generates a mipmap for the current texture data, returns true if the operation succeeded
pub fn generateMipmap(self: *RenderTexture) bool {
return sf.c.sfRenderTexture_generateMipmap(self._ptr) != 0;
}
/// Tells whether or not the texture is to be smoothed
pub fn isSmooth(self: RenderTexture) bool {
return sf.c.sfRenderTexture_isSmooth(self._ptr) != 0;
}
/// Enables or disables texture smoothing
pub fn setSmooth(self: *RenderTexture, smooth: bool) void {
sf.c.sfRenderTexture_setSmooth(self._ptr, @boolToInt(smooth));
}
/// Tells whether or not the texture should repeat when rendering outside its bounds
pub fn isRepeated(self: RenderTexture) bool {
return sf.c.sfRenderTexture_isRepeated(self._ptr) != 0;
}
/// Enables or disables texture repeating
pub fn setRepeated(self: *RenderTexture, repeated: bool) void {
sf.c.sfRenderTexture_setRepeated(self._ptr, @boolToInt(repeated));
}
/// Gets the size of this window
pub fn getSize(self: RenderTexture) sf.Vector2u {
return sf.Vector2u._fromCSFML(sf.c.sfRenderTexture_getSize(self._ptr));
}
// Target related stuff
/// Gets the current view of the target
/// Unlike in SFML, you don't get a const pointer but a copy
pub fn getView(self: RenderTexture) sf.View {
return sf.View._fromCSFML(sf.c.sfRenderTexture_getView(self._ptr).?);
}
/// Gets the default view of this target
/// Unlike in SFML, you don't get a const pointer but a copy
pub fn getDefaultView(self: RenderTexture) sf.View {
return sf.View._fromCSFML(sf.c.sfRenderTexture_getDefaultView(self._ptr).?);
}
/// Sets the view of this target
pub fn setView(self: *RenderTexture, view: sf.View) void {
var cview = view._toCSFML();
defer sf.c.sfView_destroy(cview);
sf.c.sfRenderTexture_setView(self._ptr, cview);
}
/// Gets the viewport of this target
pub fn getViewport(self: RenderTexture, view: sf.View) sf.IntRect {
return sf.IntRect._fromCSFML(sf.c.sfRenderTexture_getViewPort(self._ptr, view._ptr));
}
/// Convert a point from target coordinates to world coordinates, using the current view (or the specified view)
pub fn mapPixelToCoords(self: RenderTexture, pixel: sf.Vector2i, view: ?sf.View) sf.Vector2f {
if (view) |v| {
var cview = v._toCSFML();
defer sf.c.sfView_destroy(cview);
return sf.Vector2f._fromCSFML(sf.c.sfRenderTexture_mapPixelToCoords(self._ptr, pixel._toCSFML(), cview));
} else return sf.Vector2f._fromCSFML(sf.c.sfRenderTexture_mapPixelToCoords(self._ptr, pixel._toCSFML(), null));
}
/// Convert a point from world coordinates to target coordinates, using the current view (or the specified view)
pub fn mapCoordsToPixel(self: RenderTexture, coords: sf.Vector2f, view: ?sf.View) sf.Vector2i {
if (view) |v| {
var cview = v._toCSFML();
defer sf.c.sfView_destroy(cview);
return sf.Vector2i._fromCSFML(sf.c.sfRenderTexture_mapCoordsToPixel(self._ptr, coords._toCSFML(), cview));
} else return sf.Vector2i._fromCSFML(sf.c.sfRenderTexture_mapCoordsToPixel(self._ptr, coords._toCSFML(), null));
}
/// Pointer to the csfml structure
_ptr: *sf.c.sfRenderTexture,
test "rendertexture tests" {
const tst = @import("std").testing;
var rentex = try RenderTexture.create(.{ .x = 10, .y = 10 });
defer rentex.destroy();
rentex.setRepeated(true);
rentex.setSmooth(true);
rentex.clear(sf.Color.Red);
{
var rect = try sf.RectangleShape.create(.{ .x = 5, .y = 5 });
defer rect.destroy();
rect.setFillColor(sf.Color.Blue);
rentex.draw(rect, null);
}
rentex.display();
_ = rentex.generateMipmap();
try tst.expect(rentex.isRepeated());
try tst.expect(rentex.isSmooth());
const tex = rentex.getTexture();
try tst.expectEqual(sf.Vector2u{ .x = 10, .y = 10 }, tex.getSize());
try tst.expectEqual(sf.Vector2u{ .x = 10, .y = 10 }, rentex.getSize());
var img = tex.copyToImage();
defer img.destroy();
try tst.expectEqual(sf.Color.Blue, img.getPixel(.{ .x = 1, .y = 1 }));
try tst.expectEqual(sf.Color.Red, img.getPixel(.{ .x = 6, .y = 3 }));
}
|