mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 19:28:49 -04:00
Add the ItemSlot component.
This commit is contained in:
parent
f158da89d4
commit
642624c94d
BIN
assets/cubyz/ui/inventory/slot.png
Normal file
BIN
assets/cubyz/ui/inventory/slot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 696 B |
110
src/gui/components/ItemSlot.zig
Normal file
110
src/gui/components/ItemSlot.zig
Normal file
@ -0,0 +1,110 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const main = @import("root");
|
||||
const ItemStack = main.items.ItemStack;
|
||||
const graphics = main.graphics;
|
||||
const draw = graphics.draw;
|
||||
const Texture = graphics.Texture;
|
||||
const TextBuffer = graphics.TextBuffer;
|
||||
const vec = main.vec;
|
||||
const Vec2f = vec.Vec2f;
|
||||
|
||||
const gui = @import("../gui.zig");
|
||||
const GuiComponent = gui.GuiComponent;
|
||||
|
||||
const ItemSlot = @This();
|
||||
|
||||
var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{32 + 2*border, 32 + 2*border},
|
||||
itemStack: *ItemStack,
|
||||
oldStack: ItemStack,
|
||||
text: TextBuffer,
|
||||
textSize: Vec2f = .{0, 0},
|
||||
hovered: bool = false,
|
||||
pressed: bool = false,
|
||||
|
||||
pub fn __init() !void {
|
||||
texture = try Texture.initFromFile("assets/cubyz/ui/inventory/slot.png");
|
||||
}
|
||||
|
||||
pub fn __deinit() void {
|
||||
texture.deinit();
|
||||
}
|
||||
|
||||
pub fn init(pos: Vec2f, itemStack: *ItemStack) Allocator.Error!*ItemSlot {
|
||||
const self = try gui.allocator.create(ItemSlot);
|
||||
var buf: [16]u8 = undefined;
|
||||
self.* = ItemSlot {
|
||||
.itemStack = itemStack,
|
||||
.oldStack = itemStack.*,
|
||||
.pos = pos,
|
||||
.text = try TextBuffer.init(gui.allocator, std.fmt.bufPrint(&buf, "{}", .{self.itemStack.amount}) catch "∞", .{}, false, .right),
|
||||
};
|
||||
self.textSize = try self.text.calculateLineBreaks(8, self.size[0] - 2*border);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const ItemSlot) void {
|
||||
self.text.deinit();
|
||||
gui.allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn refreshText(self: *ItemSlot) !void {
|
||||
self.text.deinit();
|
||||
var buf: [16]u8 = undefined;
|
||||
self.text = try TextBuffer.init(gui.allocator, std.fmt.bufPrint(&buf, "{}", .{self.itemStack.amount}) catch "∞", .{}, false, .right);
|
||||
self.textSize = try self.text.calculateLineBreaks(8, self.size[0] - 2*border);
|
||||
}
|
||||
|
||||
pub fn toComponent(self: *ItemSlot) GuiComponent {
|
||||
return GuiComponent{
|
||||
.itemSlot = self
|
||||
};
|
||||
}
|
||||
|
||||
pub fn updateHovered(self: *ItemSlot, _: Vec2f) void {
|
||||
self.hovered = true;
|
||||
}
|
||||
|
||||
pub fn mainButtonPressed(self: *ItemSlot, _: Vec2f) void {
|
||||
self.pressed = true;
|
||||
}
|
||||
|
||||
pub fn mainButtonReleased(self: *ItemSlot, mousePosition: Vec2f) void {
|
||||
if(self.pressed) {
|
||||
self.pressed = false;
|
||||
if(GuiComponent.contains(self.pos, self.size, mousePosition)) {
|
||||
//TODO: self.onAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: *ItemSlot, _: Vec2f) !void {
|
||||
const newStack = self.itemStack.*;
|
||||
if(newStack.amount != self.oldStack.amount) {
|
||||
try self.refreshText();
|
||||
}
|
||||
draw.setColor(0xffffffff);
|
||||
texture.bindTo(0);
|
||||
draw.boundImage(self.pos, self.size);
|
||||
if(self.itemStack.item) |item| {
|
||||
const itemTexture = try item.getTexture();
|
||||
itemTexture.bindTo(0);
|
||||
draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border));
|
||||
if(self.itemStack.amount > 1) {
|
||||
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);
|
||||
}
|
||||
}
|
||||
if(self.pressed) {
|
||||
draw.setColor(0x80808080);
|
||||
draw.rect(self.pos, self.size);
|
||||
} else if(self.hovered) {
|
||||
self.hovered = false;
|
||||
draw.setColor(0x300000ff);
|
||||
draw.rect(self.pos, self.size);
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ const Vec2f = vec.Vec2f;
|
||||
|
||||
const Button = @import("components/Button.zig");
|
||||
const CheckBox = @import("components/CheckBox.zig");
|
||||
const ItemSlot = @import("components/ItemSlot.zig");
|
||||
const ScrollBar = @import("components/ScrollBar.zig");
|
||||
const Slider = @import("components/Slider.zig");
|
||||
const TextInput = @import("components/TextInput.zig");
|
||||
@ -46,6 +47,7 @@ pub fn init(_allocator: Allocator) !void {
|
||||
try GuiWindow.__init();
|
||||
try Button.__init();
|
||||
try CheckBox.__init();
|
||||
try ItemSlot.__init();
|
||||
try ScrollBar.__init();
|
||||
try Slider.__init();
|
||||
try TextInput.__init();
|
||||
@ -65,6 +67,7 @@ pub fn deinit() void {
|
||||
GuiWindow.__deinit();
|
||||
Button.__deinit();
|
||||
CheckBox.__deinit();
|
||||
ItemSlot.__deinit();
|
||||
ScrollBar.__deinit();
|
||||
Slider.__deinit();
|
||||
TextInput.__deinit();
|
||||
|
@ -9,6 +9,7 @@ pub const GuiComponent = union(enum) {
|
||||
pub const Button = @import("components/Button.zig");
|
||||
pub const CheckBox = @import("components/CheckBox.zig");
|
||||
pub const HorizontalList = @import("components/HorizontalList.zig");
|
||||
pub const ItemSlot = @import("components/ItemSlot.zig");
|
||||
pub const Label = @import("components/Label.zig");
|
||||
pub const MutexComponent = @import("components/MutexComponent.zig");
|
||||
pub const Slider = @import("components/Slider.zig");
|
||||
@ -20,6 +21,7 @@ pub const GuiComponent = union(enum) {
|
||||
button: *Button,
|
||||
checkBox: *CheckBox,
|
||||
horizontalList: *HorizontalList,
|
||||
itemSlot: *ItemSlot,
|
||||
label: *Label,
|
||||
mutexComponent: *MutexComponent,
|
||||
scrollBar: *ScrollBar,
|
||||
|
@ -2,20 +2,45 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const main = @import("root");
|
||||
const Player = main.game.Player;
|
||||
const Vec2f = main.vec.Vec2f;
|
||||
|
||||
const gui = @import("../gui.zig");
|
||||
const GuiComponent = gui.GuiComponent;
|
||||
const GuiWindow = gui.GuiWindow;
|
||||
const HorizontalList = GuiComponent.HorizontalList;
|
||||
const ItemSlot = GuiComponent.ItemSlot;
|
||||
|
||||
var components: [1]GuiComponent = undefined;
|
||||
pub var window = GuiWindow {
|
||||
.contentSize = Vec2f{64*8, 64},
|
||||
.title = "Hotbar",
|
||||
.id = "cubyz:hotbar",
|
||||
.onOpenFn = &onOpen,
|
||||
.onCloseFn = &onClose,
|
||||
.renderFn = &render,
|
||||
.components = &components,
|
||||
.isHud = true,
|
||||
.showTitleBar = false,
|
||||
.hasBackground = false,
|
||||
};
|
||||
|
||||
pub fn render() Allocator.Error!void {
|
||||
pub fn onOpen() Allocator.Error!void {
|
||||
var list = try HorizontalList.init();
|
||||
for(0..8) |i| {
|
||||
try list.add(try ItemSlot.init(.{0, 0}, &Player.inventory__SEND_CHANGES_TO_SERVER.items[i]));
|
||||
}
|
||||
list.finish(.{0, 0}, .center);
|
||||
components[0] = list.toComponent();
|
||||
window.contentSize = components[0].size();
|
||||
gui.updateWindowPositions();
|
||||
}
|
||||
|
||||
pub fn onClose() void {
|
||||
for(&components) |*comp| {
|
||||
comp.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render() Allocator.Error!void {
|
||||
}
|
@ -570,7 +570,7 @@ pub const ItemDropRenderer = struct {
|
||||
.item = template.item,
|
||||
};
|
||||
// Find sizes and free index:
|
||||
const img = self.item.getTexture();
|
||||
const img = self.item.getImage();
|
||||
self.size = Vec3i{img.width, 1, img.height};
|
||||
var freeSlot: ?*ItemVoxelModel = null;
|
||||
for(freeSlots.items, 0..) |potentialSlot, i| {
|
||||
|
@ -67,7 +67,8 @@ const Material = struct {
|
||||
|
||||
|
||||
pub const BaseItem = struct {
|
||||
texture: graphics.Image,
|
||||
image: graphics.Image,
|
||||
texture: ?graphics.Texture, // TODO: Properly deinit
|
||||
id: []const u8,
|
||||
name: []const u8,
|
||||
|
||||
@ -78,7 +79,7 @@ pub const BaseItem = struct {
|
||||
|
||||
fn init(self: *BaseItem, allocator: Allocator, texturePath: []const u8, replacementTexturePath: []const u8, id: []const u8, json: JsonElement) !void {
|
||||
self.id = try allocator.dupe(u8, id);
|
||||
self.texture = graphics.Image.readFromFile(allocator, texturePath) catch graphics.Image.readFromFile(allocator, replacementTexturePath) catch blk: {
|
||||
self.image = graphics.Image.readFromFile(allocator, texturePath) catch graphics.Image.readFromFile(allocator, replacementTexturePath) catch blk: {
|
||||
std.log.err("Item texture not found in {s} and {s}.", .{texturePath, replacementTexturePath});
|
||||
break :blk graphics.Image.defaultImage;
|
||||
};
|
||||
@ -94,6 +95,7 @@ pub const BaseItem = struct {
|
||||
self.block = blk: {
|
||||
break :blk blocks.getByID(json.get(?[]const u8, "block", null) orelse break :blk null);
|
||||
};
|
||||
self.texture = null;
|
||||
self.foodValue = json.get(f32, "food", 0);
|
||||
}
|
||||
|
||||
@ -104,6 +106,14 @@ pub const BaseItem = struct {
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
fn getTexture(self: *BaseItem) !graphics.Texture {
|
||||
if(self.texture == null) {
|
||||
self.texture = graphics.Texture.init();
|
||||
try self.texture.?.generate(self.image);
|
||||
}
|
||||
return self.texture.?;
|
||||
}
|
||||
// TODO: Check if/how this is needed:
|
||||
// protected Item(int stackSize) {
|
||||
// id = Resource.EMPTY;
|
||||
@ -412,7 +422,7 @@ const TextureGenerator = struct {
|
||||
}
|
||||
|
||||
pub fn generate(tool: *Tool) !void {
|
||||
const img = tool.texture;
|
||||
const img = tool.image;
|
||||
var pixelMaterials: [16][16]PixelData = undefined;
|
||||
for(0..16) |x| {
|
||||
for(0..16) |y| {
|
||||
@ -869,7 +879,8 @@ const ToolPhysics = struct {
|
||||
const Tool = struct {
|
||||
craftingGrid: [25]?*const BaseItem,
|
||||
materialGrid: [16][16]?*const BaseItem,
|
||||
texture: graphics.Image,
|
||||
image: graphics.Image,
|
||||
texture: ?graphics.Texture,
|
||||
seed: u32,
|
||||
|
||||
/// Reduction factor to block breaking time.
|
||||
@ -901,12 +912,16 @@ const Tool = struct {
|
||||
|
||||
pub fn init() !*Tool {
|
||||
var self = try main.globalAllocator.create(Tool);
|
||||
self.texture = try graphics.Image.init(main.globalAllocator, 16, 16);
|
||||
self.image = try graphics.Image.init(main.globalAllocator, 16, 16);
|
||||
self.texture = null;
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const Tool) void {
|
||||
self.texture.deinit(main.globalAllocator);
|
||||
if(self.texture) |texture| {
|
||||
texture.deinit();
|
||||
}
|
||||
self.image.deinit(main.globalAllocator);
|
||||
main.globalAllocator.destroy(self);
|
||||
}
|
||||
|
||||
@ -961,6 +976,14 @@ const Tool = struct {
|
||||
return hash;
|
||||
}
|
||||
|
||||
fn getTexture(self: *Tool) !graphics.Texture {
|
||||
if(self.texture == null) {
|
||||
self.texture = graphics.Texture.init();
|
||||
try self.texture.?.generate(self.image);
|
||||
}
|
||||
return self.texture.?;
|
||||
}
|
||||
|
||||
pub fn getPowerByBlockClass(self: *Tool, blockClass: blocks.BlockClass) f32 {
|
||||
return switch(blockClass) {
|
||||
.fluid => 0,
|
||||
@ -979,8 +1002,8 @@ const Tool = struct {
|
||||
};
|
||||
|
||||
pub const Item = union(enum) {
|
||||
baseItem: *const BaseItem,
|
||||
tool: *const Tool,
|
||||
baseItem: *BaseItem,
|
||||
tool: *Tool,
|
||||
|
||||
pub fn init(json: JsonElement) !Item {
|
||||
if(reverseIndices.get(json.get([]const u8, "item", "null"))) |baseItem| {
|
||||
@ -1026,13 +1049,24 @@ pub const Item = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getTexture(self: Item) graphics.Image {
|
||||
pub fn getTexture(self: Item) !graphics.Texture {
|
||||
switch(self) {
|
||||
.baseItem => |_baseItem| {
|
||||
return _baseItem.texture;
|
||||
return try _baseItem.getTexture();
|
||||
},
|
||||
.tool => |_tool| {
|
||||
return _tool.texture;
|
||||
return try _tool.getTexture();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getImage(self: Item) graphics.Image {
|
||||
switch(self) {
|
||||
.baseItem => |_baseItem| {
|
||||
return _baseItem.image;
|
||||
},
|
||||
.tool => |_tool| {
|
||||
return _tool.image;
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1256,7 +1290,7 @@ pub fn deinit() void {
|
||||
arena.deinit();
|
||||
}
|
||||
|
||||
pub fn getByID(id: []const u8) ?*const BaseItem {
|
||||
pub fn getByID(id: []const u8) ?*BaseItem {
|
||||
if(reverseIndices.get(id)) |result| {
|
||||
return result;
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user