add nil graphics objects
This commit is contained in:
parent
ed560d3da1
commit
bf325b74b5
@ -42,13 +42,13 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 {
|
|||||||
|
|
||||||
const tile_size = Vec2.init(64, 64);
|
const tile_size = Vec2.init(64, 64);
|
||||||
|
|
||||||
const player_sprite = try Gfx.initSprite();
|
const player_sprite = Gfx.initSprite();
|
||||||
Gfx.setSprite(player_sprite, .{
|
Gfx.setSprite(player_sprite, .{
|
||||||
.image = spritesheet,
|
.image = spritesheet,
|
||||||
.rect = Rect.init(0, 4, 1, 1).multiply(tile_size)
|
.rect = Rect.init(0, 4, 1, 1).multiply(tile_size)
|
||||||
});
|
});
|
||||||
|
|
||||||
const wall_sprite = try Gfx.initSprite();
|
const wall_sprite = Gfx.initSprite();
|
||||||
Gfx.setSprite(wall_sprite, .{
|
Gfx.setSprite(wall_sprite, .{
|
||||||
.image = spritesheet,
|
.image = spritesheet,
|
||||||
.rect = Rect.init(1, 0, 1, 1).multiply(tile_size)
|
.rect = Rect.init(1, 0, 1, 1).multiply(tile_size)
|
||||||
|
|||||||
256
src/graphics.zig
256
src/graphics.zig
@ -38,12 +38,15 @@ const State = struct {
|
|||||||
|
|
||||||
textures_buffer: [Texture.max_textures]Texture.SlotMap.Slot,
|
textures_buffer: [Texture.max_textures]Texture.SlotMap.Slot,
|
||||||
textures: Texture.SlotMap,
|
textures: Texture.SlotMap,
|
||||||
|
nil_texture: Texture.Id,
|
||||||
|
|
||||||
spritesheets_buffer: [Spritesheet.max_spritesheets]Spritesheet.SlotMap.Slot,
|
spritesheets_buffer: [Spritesheet.max_spritesheets]Spritesheet.SlotMap.Slot,
|
||||||
spritesheets: Spritesheet.SlotMap,
|
spritesheets: Spritesheet.SlotMap,
|
||||||
|
nil_spritesheet: Spritesheet.Id,
|
||||||
|
|
||||||
sprites_buffer: [Sprite.max_sprites]Sprite.SlotMap.Slot,
|
sprites_buffer: [Sprite.max_sprites]Sprite.SlotMap.Slot,
|
||||||
sprites: Sprite.SlotMap,
|
sprites: Sprite.SlotMap,
|
||||||
|
nil_sprite: Sprite.Id,
|
||||||
};
|
};
|
||||||
|
|
||||||
var g_state: State = undefined;
|
var g_state: State = undefined;
|
||||||
@ -134,17 +137,52 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
.quads_buffer = undefined,
|
.quads_buffer = undefined,
|
||||||
.quads = .initBuffer(&self.quads_buffer),
|
.quads = .initBuffer(&self.quads_buffer),
|
||||||
.clear_color = .black,
|
.clear_color = .black,
|
||||||
.textures_buffer = undefined,
|
|
||||||
.textures = .init(.initBuffer(&self.textures_buffer)),
|
|
||||||
.default_sprite = undefined,
|
.default_sprite = undefined,
|
||||||
.error_sprite = undefined,
|
.error_sprite = undefined,
|
||||||
|
.default_spritesheet = undefined,
|
||||||
|
|
||||||
|
.textures_buffer = undefined,
|
||||||
|
.textures = .init(.initBuffer(&self.textures_buffer)),
|
||||||
|
.nil_texture = undefined,
|
||||||
|
|
||||||
.sprites_buffer = undefined,
|
.sprites_buffer = undefined,
|
||||||
.sprites = .init(.initBuffer(&self.sprites_buffer)),
|
.sprites = .init(.initBuffer(&self.sprites_buffer)),
|
||||||
.default_spritesheet = undefined,
|
.nil_sprite = undefined,
|
||||||
|
|
||||||
.spritesheets_buffer = undefined,
|
.spritesheets_buffer = undefined,
|
||||||
.spritesheets = .init(.initBuffer(&self.spritesheets_buffer))
|
.spritesheets = .init(.initBuffer(&self.spritesheets_buffer)),
|
||||||
|
.nil_spritesheet = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.nil_texture = self.textures.insertAssumeCapacity();
|
||||||
|
{
|
||||||
|
const nil_texture = self.textures.getAssumeExists(self.nil_texture);
|
||||||
|
nil_texture.* = Texture{
|
||||||
|
.image = .{ .id = sg.invalid_id },
|
||||||
|
.view = .{ .id = sg.invalid_id },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.nil_spritesheet = self.spritesheets.insertAssumeCapacity();
|
||||||
|
{
|
||||||
|
const nil_spritesheet = self.spritesheets.getAssumeExists(self.nil_spritesheet);
|
||||||
|
nil_spritesheet.* = Spritesheet{
|
||||||
|
.texture = self.nil_texture,
|
||||||
|
.size = .init(0, 0),
|
||||||
|
.stale = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.nil_sprite = self.sprites.insertAssumeCapacity();
|
||||||
|
{
|
||||||
|
const nil_sprite = self.sprites.getAssumeExists(self.nil_sprite);
|
||||||
|
nil_sprite.* = Sprite{
|
||||||
|
.spritesheet = self.nil_spritesheet,
|
||||||
|
.data = .none,
|
||||||
|
.position = null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const width = 8;
|
const width = 8;
|
||||||
const height = 8;
|
const height = 8;
|
||||||
@ -152,7 +190,7 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
var pixels: [width * height * 4]u8 = undefined;
|
var pixels: [width * height * 4]u8 = undefined;
|
||||||
@memset(&pixels, 0xFF);
|
@memset(&pixels, 0xFF);
|
||||||
|
|
||||||
self.default_sprite = try initSprite();
|
self.default_sprite = initSprite();
|
||||||
setSprite(self.default_sprite, .{
|
setSprite(self.default_sprite, .{
|
||||||
.image = ImageData{
|
.image = ImageData{
|
||||||
.width = width,
|
.width = width,
|
||||||
@ -186,7 +224,7 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.error_sprite = try initSprite();
|
self.error_sprite = initSprite();
|
||||||
setSprite(self.error_sprite, .{
|
setSprite(self.error_sprite, .{
|
||||||
.image = .{
|
.image = .{
|
||||||
.width = width,
|
.width = width,
|
||||||
@ -196,7 +234,7 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.default_spritesheet = try initSpritesheet();
|
self.default_spritesheet = initSpritesheet();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn deinit() void {
|
||||||
@ -343,15 +381,24 @@ pub fn drawLine(from: Vec2, to: Vec2, color: Vec4, width: f32) void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initTexture() !Texture.Id {
|
pub fn initTexture() Texture.Id {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
const id = try self.textures.insertBounded();
|
const id = self.textures.insertBounded() catch {
|
||||||
|
log.warn("Failed to create texture, limit reached! limit: {}", .{self.textures.slots.capacity});
|
||||||
|
return self.nil_texture;
|
||||||
|
};
|
||||||
|
|
||||||
const image = sg.allocImage();
|
const image = sg.allocImage();
|
||||||
assert(image.id != sg.invalid_id);
|
if (image.id == sg.invalid_id) {
|
||||||
|
log.warn("allocImage() failed!", .{});
|
||||||
|
return self.nil_texture;
|
||||||
|
}
|
||||||
|
|
||||||
const view = sg.allocView();
|
const view = sg.allocView();
|
||||||
assert(view.id != sg.invalid_id);
|
if (view.id == sg.invalid_id) {
|
||||||
|
log.warn("allocView() failed!", .{});
|
||||||
|
return self.nil_texture;
|
||||||
|
}
|
||||||
|
|
||||||
const texture = self.textures.getAssumeExists(id);
|
const texture = self.textures.getAssumeExists(id);
|
||||||
texture.* = .{
|
texture.* = .{
|
||||||
@ -363,6 +410,10 @@ pub fn initTexture() !Texture.Id {
|
|||||||
|
|
||||||
pub fn deinitTexture(id: Texture.Id) void {
|
pub fn deinitTexture(id: Texture.Id) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
if (id == self.nil_texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.textures.remove(id)) {
|
if (self.textures.remove(id)) {
|
||||||
const texture = self.textures_buffer[id.index];
|
const texture = self.textures_buffer[id.index];
|
||||||
const bound_view = &self.bindings.views[shd.VIEW_tex];
|
const bound_view = &self.bindings.views[shd.VIEW_tex];
|
||||||
@ -378,11 +429,14 @@ pub fn deinitTexture(id: Texture.Id) void {
|
|||||||
|
|
||||||
pub fn setTexture(id: Texture.Id, texture_data: ImageData) void {
|
pub fn setTexture(id: Texture.Id, texture_data: ImageData) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
if (!self.textures.exists(id)) {
|
if (id == self.nil_texture) {
|
||||||
log.warn("Attempt to set data for texture that doesn't exist: {}", .{id});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const texture = self.textures.getAssumeExists(id);
|
|
||||||
|
const texture = self.textures.get(id) orelse {
|
||||||
|
log.warn("Attempt to set texture that doesn't exist: {}", .{id});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if (sg.queryImageState(texture.image) == .VALID) {
|
if (sg.queryImageState(texture.image) == .VALID) {
|
||||||
sg.uninitImage(texture.image);
|
sg.uninitImage(texture.image);
|
||||||
@ -400,13 +454,19 @@ pub fn setTexture(id: Texture.Id, texture_data: ImageData) void {
|
|||||||
.pixel_format = .RGBA8,
|
.pixel_format = .RGBA8,
|
||||||
.data = image_data,
|
.data = image_data,
|
||||||
});
|
});
|
||||||
assert(sg.queryImageState(texture.image) == .VALID);
|
if (sg.queryImageState(texture.image) != .VALID) {
|
||||||
|
log.warn("initImage() failed", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sg.queryViewState(texture.view) == .ALLOC) {
|
if (sg.queryViewState(texture.view) == .ALLOC) {
|
||||||
sg.initView(texture.view, .{
|
sg.initView(texture.view, .{
|
||||||
.texture = .{ .image = texture.image }
|
.texture = .{ .image = texture.image }
|
||||||
});
|
});
|
||||||
assert(sg.queryViewState(texture.view) == .VALID);
|
if (sg.queryViewState(texture.view) != .VALID) {
|
||||||
|
log.warn("initView() failed", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,22 +491,31 @@ pub fn draw(opts: DrawOptions) void {
|
|||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
|
||||||
var quad = opts.quad;
|
var quad = opts.quad;
|
||||||
var texture = opts.texture;
|
|
||||||
if (!self.textures.exists(texture)) {
|
|
||||||
if (getSpriteUVRect(self.error_sprite)) |error_uv| {
|
|
||||||
quad.setUVRect(error_uv);
|
|
||||||
quad.setColor(.white);
|
|
||||||
|
|
||||||
const sprite = self.sprites.getAssumeExists(self.error_sprite);
|
var view: sg.View = .{ .id = sg.invalid_id };
|
||||||
const spritesheet = self.spritesheets.getAssumeExists(sprite.spritesheet);
|
if (opts.texture != self.nil_texture and self.textures.exists(opts.texture)) {
|
||||||
texture = spritesheet.texture;
|
const texture = self.textures.getAssumeExists(opts.texture);
|
||||||
} else {
|
view = texture.view;
|
||||||
log.err("Failed to draw error texture", .{});
|
}
|
||||||
|
|
||||||
|
if (sg.queryViewState(view) != .VALID) {
|
||||||
|
if (self.sprites.get(self.error_sprite)) |sprite| {
|
||||||
|
if (self.spritesheets.get(sprite.spritesheet)) |spritesheet| {
|
||||||
|
if (self.textures.get(spritesheet.texture)) |texture| {
|
||||||
|
if (getSpriteUVRect(self.error_sprite)) |uv| {
|
||||||
|
quad.setUVRect(uv);
|
||||||
|
quad.setColor(.white);
|
||||||
|
view = texture.view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sg.queryViewState(view) != .VALID) {
|
||||||
|
log.warn("Failed to draw error image", .{});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const view = self.textures.getAssumeExists(texture).view;
|
|
||||||
|
|
||||||
const bound_view = &self.bindings.views[shd.VIEW_tex];
|
const bound_view = &self.bindings.views[shd.VIEW_tex];
|
||||||
if (bound_view.id != view.id) {
|
if (bound_view.id != view.id) {
|
||||||
@ -461,9 +530,12 @@ pub fn draw(opts: DrawOptions) void {
|
|||||||
self.quads.appendAssumeCapacity(quad);
|
self.quads.appendAssumeCapacity(quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initSprite() !Sprite.Id {
|
pub fn initSprite() Sprite.Id {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
const id = try self.sprites.insertBounded();
|
const id = self.sprites.insertBounded() catch {
|
||||||
|
log.warn("Failed to create sprite, limit reached! limit: {}", .{self.sprites.slots.capacity});
|
||||||
|
return self.nil_sprite;
|
||||||
|
};
|
||||||
|
|
||||||
const sprite = self.sprites.getAssumeExists(id);
|
const sprite = self.sprites.getAssumeExists(id);
|
||||||
sprite.* = .{
|
sprite.* = .{
|
||||||
@ -477,6 +549,10 @@ pub fn initSprite() !Sprite.Id {
|
|||||||
|
|
||||||
pub fn deinitSprite(id: Sprite.Id) void {
|
pub fn deinitSprite(id: Sprite.Id) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
if (id == self.nil_sprite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.sprites.exists(id)) {
|
if (self.sprites.exists(id)) {
|
||||||
const sprite = self.sprites.getAssumeExists(id);
|
const sprite = self.sprites.getAssumeExists(id);
|
||||||
if (sprite.data) |data| {
|
if (sprite.data) |data| {
|
||||||
@ -484,7 +560,6 @@ pub fn deinitSprite(id: Sprite.Id) void {
|
|||||||
}
|
}
|
||||||
self.sprites.removeAssumeExists(id);
|
self.sprites.removeAssumeExists(id);
|
||||||
|
|
||||||
|
|
||||||
if (self.spritesheets.get(sprite.spritesheet)) |spritesheet| {
|
if (self.spritesheets.get(sprite.spritesheet)) |spritesheet| {
|
||||||
spritesheet.stale = true;
|
spritesheet.stale = true;
|
||||||
}
|
}
|
||||||
@ -498,12 +573,16 @@ const SetSpriteOptions = struct {
|
|||||||
|
|
||||||
pub fn setSprite(id: Sprite.Id, opts: SetSpriteOptions) void {
|
pub fn setSprite(id: Sprite.Id, opts: SetSpriteOptions) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
if (!self.sprites.exists(id)) {
|
if (id == self.nil_sprite) {
|
||||||
log.warn("Attempt to set data for sprite that doesn't exist: {}", .{id});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sprite_data: ImageData = .empty;
|
const sprite = self.sprites.get(id) orelse {
|
||||||
|
log.warn("Attempt to set sprite that doesn't exist: {}", .{id});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
var sprite_data: ImageData = .none;
|
||||||
errdefer sprite_data.deinit(self.gpa);
|
errdefer sprite_data.deinit(self.gpa);
|
||||||
|
|
||||||
if (opts.rect) |rect| {
|
if (opts.rect) |rect| {
|
||||||
@ -525,7 +604,6 @@ pub fn setSprite(id: Sprite.Id, opts: SetSpriteOptions) void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const sprite = self.sprites.getAssumeExists(id);
|
|
||||||
if (sprite.data) |old_sprite_data| {
|
if (sprite.data) |old_sprite_data| {
|
||||||
old_sprite_data.deinit(self.gpa);
|
old_sprite_data.deinit(self.gpa);
|
||||||
}
|
}
|
||||||
@ -537,8 +615,12 @@ pub fn setSprite(id: Sprite.Id, opts: SetSpriteOptions) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn packSprites(id: Spritesheet.Id) !void {
|
pub fn packSpritesheet(id: Spritesheet.Id) !void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
if (id == self.nil_spritesheet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const spritesheet = self.spritesheets.get(id) orelse {
|
const spritesheet = self.spritesheets.get(id) orelse {
|
||||||
log.warn("Attempt to pack spritesheet that doesn't exist: {}", .{id});
|
log.warn("Attempt to pack spritesheet that doesn't exist: {}", .{id});
|
||||||
return;
|
return;
|
||||||
@ -555,28 +637,32 @@ pub fn packSprites(id: Spritesheet.Id) !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var nodes: [32]STBRectPack.Node = undefined;
|
var nodes: [32]STBRectPack.Node = undefined;
|
||||||
var rects: [Sprite.max_sprites]STBRectPack.Rect = undefined;
|
|
||||||
|
|
||||||
for (&texture_sizes) |texture_size| {
|
var sprites_buffer: [Sprite.max_sprites]*Sprite = undefined;
|
||||||
var ctx: STBRectPack = undefined;
|
var sprites = std.ArrayList(*Sprite).initBuffer(&sprites_buffer);
|
||||||
ctx.init(texture_size, texture_size, &nodes);
|
|
||||||
ctx.setupAllowOutOfMem(true);
|
|
||||||
|
|
||||||
@memset(&rects, .{});
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
var i: usize = 0;
|
|
||||||
var sprite_iter = self.sprites.iterator();
|
var sprite_iter = self.sprites.iterator();
|
||||||
while (sprite_iter.next()) |sprite_id| : (i += 1) {
|
while (sprite_iter.next()) |sprite_id| {
|
||||||
const sprite = self.sprites.getAssumeExists(sprite_id);
|
const sprite = self.sprites.getAssumeExists(sprite_id);
|
||||||
const sprite_data = sprite.data orelse continue;
|
if (sprite.data != null and sprite.spritesheet == id) {
|
||||||
|
sprites.appendAssumeCapacity(sprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rects: [Sprite.max_sprites]STBRectPack.Rect = undefined;
|
||||||
|
@memset(&rects, .{});
|
||||||
|
for (0.., sprites.items) |i, sprite| {
|
||||||
|
const sprite_data = sprite.data.?;
|
||||||
rects[i] = .{
|
rects[i] = .{
|
||||||
.w = @intCast(sprite_data.width),
|
.w = @intCast(sprite_data.width),
|
||||||
.h = @intCast(sprite_data.height),
|
.h = @intCast(sprite_data.height),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
for (&texture_sizes) |texture_size| {
|
||||||
|
var ctx: STBRectPack = undefined;
|
||||||
|
ctx.init(texture_size, texture_size, &nodes);
|
||||||
|
ctx.setupAllowOutOfMem(true);
|
||||||
|
|
||||||
const success = ctx.packRects(&rects);
|
const success = ctx.packRects(&rects);
|
||||||
std.debug.print("success {} {}\n", .{texture_size, success});
|
std.debug.print("success {} {}\n", .{texture_size, success});
|
||||||
@ -587,13 +673,8 @@ pub fn packSprites(id: Spritesheet.Id) !void {
|
|||||||
const image_data = try ImageData.initRGBA8(self.gpa, texture_size, texture_size);
|
const image_data = try ImageData.initRGBA8(self.gpa, texture_size, texture_size);
|
||||||
defer image_data.deinit(self.gpa);
|
defer image_data.deinit(self.gpa);
|
||||||
|
|
||||||
{
|
for (0.., sprites.items) |i, sprite| {
|
||||||
var i: usize = 0;
|
const sprite_data = sprite.data.?;
|
||||||
var sprite_iter = self.sprites.iterator();
|
|
||||||
while (sprite_iter.next()) |sprite_id| : (i += 1) {
|
|
||||||
const sprite = self.sprites.getAssumeExists(sprite_id);
|
|
||||||
const sprite_data = sprite.data orelse continue;
|
|
||||||
|
|
||||||
assert(rects[i].was_packed == 1);
|
assert(rects[i].was_packed == 1);
|
||||||
const x: u32 = @intCast(rects[i].x);
|
const x: u32 = @intCast(rects[i].x);
|
||||||
const y: u32 = @intCast(rects[i].y);
|
const y: u32 = @intCast(rects[i].y);
|
||||||
@ -608,7 +689,6 @@ pub fn packSprites(id: Spritesheet.Id) !void {
|
|||||||
sprite_data.height
|
sprite_data.height
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setTexture(spritesheet.texture, image_data);
|
setTexture(spritesheet.texture, image_data);
|
||||||
|
|
||||||
@ -617,32 +697,30 @@ pub fn packSprites(id: Spritesheet.Id) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const max_texture_size = texture_sizes[texture_sizes.len-1];
|
const max_texture_size = texture_sizes[texture_sizes.len-1];
|
||||||
log.warn("Failed to pack sprites, couldn't create a texture that is large enough. Max size tried: {}x{}", .{max_texture_size, max_texture_size});
|
log.warn("Failed to pack sprites, couldn't create a texture that is large enough. Max size tried: {}x{}", .{max_texture_size, max_texture_size});
|
||||||
|
return error.TooManySprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getSpriteUVRect(id: Sprite.Id) ?Rect {
|
pub fn getSpriteUVRect(id: Sprite.Id) ?Rect {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
if (id == self.nil_sprite) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!self.sprites.exists(id)) {
|
const sprite = self.sprites.get(id) orelse return null;
|
||||||
return null;
|
const sprite_data = sprite.data orelse return null;
|
||||||
}
|
|
||||||
const sprite = self.sprites.getAssumeExists(id);
|
|
||||||
if (sprite.data == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const spritesheet = self.spritesheets.get(sprite.spritesheet) orelse return null;
|
const spritesheet = self.spritesheets.get(sprite.spritesheet) orelse return null;
|
||||||
|
|
||||||
packSprites(sprite.spritesheet) catch |e| {
|
packSpritesheet(sprite.spritesheet) catch |e| {
|
||||||
log.warn("Failed to pack sprites: {}", .{e});
|
log.warn("Failed to pack sprites: {}", .{e});
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(sprite.position != null);
|
assert(sprite.position != null);
|
||||||
|
|
||||||
const sprite_size = Vec2.initFromInt(u32, sprite.data.?.width, sprite.data.?.height);
|
const sprite_size = Vec2.initFromInt(u32, sprite_data.width, sprite_data.height);
|
||||||
return Rect{
|
return Rect{
|
||||||
.pos = sprite.position.?.divide(spritesheet.size),
|
.pos = sprite.position.?.divide(spritesheet.size),
|
||||||
.size = sprite_size.divide(spritesheet.size),
|
.size = sprite_size.divide(spritesheet.size),
|
||||||
@ -657,6 +735,7 @@ pub fn drawSprite(id: Sprite.Id, pos: Vec2, size: Vec2, color: Color) void {
|
|||||||
quad.setRect(.{ .pos = pos, .size = size });
|
quad.setRect(.{ .pos = pos, .size = size });
|
||||||
|
|
||||||
var texture: ?Texture.Id = null;
|
var texture: ?Texture.Id = null;
|
||||||
|
if (id != self.nil_sprite) {
|
||||||
if (getSpriteUVRect(id)) |sprite_uv| {
|
if (getSpriteUVRect(id)) |sprite_uv| {
|
||||||
quad.setUVRect(sprite_uv);
|
quad.setUVRect(sprite_uv);
|
||||||
if (self.sprites.get(id)) |sprite| {
|
if (self.sprites.get(id)) |sprite| {
|
||||||
@ -664,39 +743,25 @@ pub fn drawSprite(id: Sprite.Id, pos: Vec2, size: Vec2, color: Color) void {
|
|||||||
texture = spritesheet.texture;
|
texture = spritesheet.texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture == null) {
|
|
||||||
if (getSpriteUVRect(self.error_sprite)) |error_uv| {
|
|
||||||
quad.setUVRect(error_uv);
|
|
||||||
quad.setColor(.white);
|
|
||||||
|
|
||||||
const sprite = self.sprites.getAssumeExists(self.error_sprite);
|
|
||||||
const spritesheet = self.spritesheets.getAssumeExists(sprite.spritesheet);
|
|
||||||
texture = spritesheet.texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture == null) {
|
|
||||||
log.warn("Failed to draw sprite", .{});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(.{
|
draw(.{
|
||||||
.texture = texture.?,
|
.texture = texture orelse self.nil_texture,
|
||||||
.quad = quad
|
.quad = quad
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initSpritesheet() !Spritesheet.Id {
|
pub fn initSpritesheet() Spritesheet.Id {
|
||||||
// TODO: self.spritesheet_texture = try initTexture();
|
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
const id = try self.spritesheets.insertBounded();
|
const id = self.spritesheets.insertBounded() catch {
|
||||||
|
log.warn("Failed to create spritesheet, limit reached! limit: {}", .{self.spritesheets.slots.capacity});
|
||||||
|
return self.nil_spritesheet;
|
||||||
|
};
|
||||||
|
|
||||||
const spritesheet = self.spritesheets.getAssumeExists(id);
|
const spritesheet = self.spritesheets.getAssumeExists(id);
|
||||||
spritesheet.* = .{
|
spritesheet.* = .{
|
||||||
.texture = try initTexture(),
|
.texture = initTexture(),
|
||||||
.size = .init(0, 0),
|
.size = .init(0, 0),
|
||||||
.stale = false,
|
.stale = false,
|
||||||
};
|
};
|
||||||
@ -705,7 +770,16 @@ pub fn initSpritesheet() !Spritesheet.Id {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinitSpritesheet(id: Spritesheet.Id) void {
|
pub fn deinitSpritesheet(id: Spritesheet.Id) void {
|
||||||
_ = id; // autofix
|
const self = &g_state;
|
||||||
|
if (id == self.nil_spritesheet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.spritesheets.get(id)) {
|
||||||
|
const spritesheet = self.spritesheets.getAssumeExists(id);
|
||||||
|
deinitTexture(spritesheet.texture);
|
||||||
|
self.spritesheets.removeAssumeExists(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ImageData = struct {
|
pub const ImageData = struct {
|
||||||
@ -718,7 +792,7 @@ pub const ImageData = struct {
|
|||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
|
||||||
pub const empty = ImageData{
|
pub const none = ImageData{
|
||||||
.pixels = .none,
|
.pixels = .none,
|
||||||
.width = 0,
|
.width = 0,
|
||||||
.height = 0,
|
.height = 0,
|
||||||
|
|||||||
@ -281,18 +281,38 @@ fn PlatformType(App: type) type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const input = &self.input;
|
||||||
|
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
.MOUSE_DOWN => {
|
.MOUSE_DOWN => {
|
||||||
|
if (input.mouse_position == null) {
|
||||||
|
self.pushEvent(.{
|
||||||
|
.mouse_enter = .init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.pushEvent(.{
|
self.pushEvent(.{
|
||||||
.mouse_pressed = Input.MouseButton.fromSokol(e.mouse_button) orelse return false,
|
.mouse_pressed = Input.MouseButton.fromSokol(e.mouse_button) orelse return false,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.MOUSE_UP => {
|
.MOUSE_UP => {
|
||||||
|
if (input.mouse_position == null) {
|
||||||
|
self.pushEvent(.{
|
||||||
|
.mouse_enter = .init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.pushEvent(.{
|
self.pushEvent(.{
|
||||||
.mouse_released = Input.MouseButton.fromSokol(e.mouse_button) orelse return false,
|
.mouse_released = Input.MouseButton.fromSokol(e.mouse_button) orelse return false,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.MOUSE_MOVE => {
|
.MOUSE_MOVE => {
|
||||||
|
if (input.mouse_position == null) {
|
||||||
|
self.pushEvent(.{
|
||||||
|
.mouse_enter = .init(e.mouse_x, e.mouse_y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.pushEvent(.{
|
self.pushEvent(.{
|
||||||
.mouse_move = .init(e.mouse_x, e.mouse_y)
|
.mouse_move = .init(e.mouse_x, e.mouse_y)
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user