{gfx,examples}: simplify text rendering API a bit

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-05-13 22:38:40 +02:00
parent 393320aa68
commit 122a1ea9a7
5 changed files with 153 additions and 117 deletions

View file

@ -88,7 +88,6 @@ pub fn printTitle(
args: anytype,
) !void {
// Free any previous window title slice
// TODO: reuse allocations
if (core.get(window_id, .title)) |slice| core.state().allocator.free(slice);
// Allocate and assign a new window title slice.

View file

@ -12,6 +12,8 @@ const vec4 = math.vec4;
const Mat3x3 = math.Mat3x3;
const Mat4x4 = math.Mat4x4;
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
pub const name = .mach_gfx_text;
pub const Mod = mach.Mod(@This());
@ -51,6 +53,8 @@ pub const components = .{
};
pub const systems = .{
.init = .{ .handler = init },
.deinit = .{ .handler = deinit },
.update = .{ .handler = update },
};
@ -58,6 +62,52 @@ const BuiltText = struct {
glyphs: std.ArrayListUnmanaged(gfx.TextPipeline.Glyph),
};
allocator: std.mem.Allocator,
pub fn init(text: *Mod) void {
text.init(.{ .allocator = gpa.allocator() });
}
pub fn deinit(text: *Mod) void {
_ = text;
// TODO: help with cleaning up allocPrintText, which is currently a little difficult to track
// since it is a per-entity allocation
}
/// Helper to set text components on an entity simply/easily via heap allocating strings
///
/// ```
/// try mach.Text.allocPrintText(text, my_text_entity, my_style_entity, "Hello, {s}!", .{"Mach"});
/// ```
pub fn allocPrintText(
text: *Mod,
id: mach.EntityID,
style: mach.EntityID,
comptime fmt: []const u8,
args: anytype,
) !void {
freeText(text, id);
const str = try std.fmt.allocPrint(text.state().allocator, fmt, args);
const styles = try text.state().allocator.alloc(mach.EntityID, 1);
styles[0] = style;
const strings = try text.state().allocator.alloc([]const u8, 1);
strings[0] = str;
try text.set(id, .style, styles);
try text.set(id, .text, strings);
try text.set(id, .dirty, true);
}
/// Free's an entity's .text and .style slices that were previously allocated via e.g. allocPrintText
pub fn freeText(text: *Mod, id: mach.EntityID) void {
if (text.get(id, .text)) |slice| {
text.state().allocator.free(slice[0]);
text.state().allocator.free(slice);
}
if (text.get(id, .style)) |slice| text.state().allocator.free(slice);
}
fn update(
entities: *mach.Entities.Mod,
text: *Mod,
@ -149,8 +199,8 @@ fn updatePipeline(
// Load the font
// TODO(text): allow specifying a custom font
// TODO(text): keep fonts around for reuse later
const font_name = text_style.get(style, .font_name).?;
_ = font_name; // TODO: actually use font name
// const font_name = text_style.get(style, .font_name).?;
// _ = font_name; // TODO: actually use font name
const font_bytes = @import("font-assets").fira_sans_regular_ttf;
var font = if (font_once) |f| f else blk: {
font_once = try gfx.Font.initBytes(font_bytes);
@ -160,12 +210,9 @@ fn updatePipeline(
const font_size = text_style.get(style, .font_size).?;
// TODO(text): respect these style parameters
const font_weight = text_style.get(style, .font_weight).?;
const italic = text_style.get(style, .italic).?;
const color = text_style.get(style, .color).?;
_ = font_weight;
_ = italic;
_ = color;
// const font_weight = text_style.get(style, .font_weight).?;
// const italic = text_style.get(style, .italic).?;
// const color = text_style.get(style, .color).?;
// Create a text shaper
var run = try gfx.TextRun.init();

View file

@ -5,11 +5,11 @@ pub const name = .mach_gfx_text_style;
pub const Mod = mach.Mod(@This());
pub const components = .{
// TODO: ship a default font
.font_name = .{ .type = []const u8, .description =
\\ Desired font to render text with.
\\ TODO(text): this is not currently implemented
},
// // TODO: ship a default font
// .font_name = .{ .type = []const u8, .description =
// \\ Desired font to render text with.
// \\ TODO(text): this is not currently implemented
// },
// e.g. 12 * mach.gfx.px_per_pt // 12pt
.font_size = .{ .type = f32, .description =
@ -17,23 +17,23 @@ pub const components = .{
\\ TODO(text): this is not currently implemented
},
// e.g. mach.gfx.font_weight_normal
.font_weight = .{ .type = u16, .description =
\\ Font weight
\\ TODO(text): this is not currently implemented
},
// // e.g. mach.gfx.font_weight_normal
// .font_weight = .{ .type = u16, .description =
// \\ Font weight
// \\ TODO(text): this is not currently implemented
// },
// e.g. false
.italic = .{ .type = bool, .description =
\\ Italic text
\\ TODO(text): this is not currently implemented
},
// // e.g. false
// .italic = .{ .type = bool, .description =
// \\ Italic text
// \\ TODO(text): this is not currently implemented
// },
// e.g. vec4(0, 0, 0, 1.0)
.color = .{ .type = math.Vec4, .description =
\\ Fill color
\\ TODO(text): this is not currently implemented
},
// // e.g. vec4(0, 0, 0, 1.0)
// .color = .{ .type = math.Vec4, .description =
// \\ Fill color
// \\ TODO(text): this is not currently implemented
// },
// TODO(text): allow user to specify projection matrix (3d-space flat text etc.)
};