The code is getting real messy...
This commit is contained in:
duck
2025-08-31 07:08:29 +05:00
parent 1d3f89e5f5
commit 39db8ed3a1

View File

@@ -12,10 +12,10 @@ const Order = i32;
pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{}; pub var object_map: std.AutoHashMapUnmanaged(Id, usize) = .{};
pub var objects: std.ArrayListUnmanaged(Object) = .{}; pub var objects: std.ArrayListUnmanaged(Object) = .{};
pub var plane_mesh: Graphics.Mesh = undefined; pub var hand_mesh: Graphics.Mesh = undefined;
pub var cube_mesh: Graphics.Mesh = undefined; pub var cube_mesh: Graphics.Mesh = undefined;
pub var table_mesh: Graphics.Mesh = undefined; pub var table_mesh: Graphics.Mesh = undefined;
pub var texture: Assets.Texture = undefined; pub var table_texture: Assets.Texture = undefined;
pub var hand_texture: Assets.Texture = undefined; pub var hand_texture: Assets.Texture = undefined;
pub var camera_position: @Vector(2, f32) = @splat(0); pub var camera_position: @Vector(2, f32) = @splat(0);
@@ -34,7 +34,12 @@ pub var dock_spacing: f32 = 0;
pub var min_order: Order = undefined; pub var min_order: Order = undefined;
pub var max_order: Order = undefined; pub var max_order: Order = undefined;
const DOCK_TILT = 0.03;
const DOCK_TILT_SIN = std.math.sin(DOCK_TILT);
const DOCK_TILT_COS = std.math.cos(DOCK_TILT);
const Object = struct { const Object = struct {
type: Type,
transform: Graphics.Transform = .{}, transform: Graphics.Transform = .{},
target_transform: Graphics.Transform = .{}, target_transform: Graphics.Transform = .{},
width: f32, width: f32,
@@ -44,14 +49,21 @@ const Object = struct {
order: Order, order: Order,
id: Id, id: Id,
index: u32, index: u32,
z: u32 = 0,
parent: Parent = .none, parent: Parent = .none,
parent_index: u32 = 0, parent_index: u32 = 0,
child_last_id: u32 = 0,
influence: f32 = 0, influence: f32 = 0,
const Parent = enum { const Type = enum {
card,
deck,
};
const Parent = union(enum) {
none, none,
hand, hand,
dock, dock,
deck: Id,
}; };
pub fn reparent(self: *@This(), new_parent: Parent) void { pub fn reparent(self: *@This(), new_parent: Parent) void {
@@ -64,7 +76,8 @@ const Object = struct {
const parent_transform = switch (self.parent) { const parent_transform = switch (self.parent) {
.hand => World.hand_transform, .hand => World.hand_transform,
.dock => World.dock_transform, .dock => World.dock_transform,
else => return transform, .deck => |deck| if (World.getObject(deck)) |object| object.drawingTransform() else Graphics.Transform{},
.none => return transform,
}; };
return Graphics.Transform.combineTransforms( return Graphics.Transform.combineTransforms(
transform, transform,
@@ -80,22 +93,48 @@ const Object = struct {
const World = @This(); const World = @This();
pub fn initDebug() void { pub fn initDebug() void {
for (0..10) |i| { for (0..10) |i| {
(World.objects.addOne(Game.alloc) catch err.oom()).* = .{ World.objects.append(Game.alloc, .{
.type = .card,
.width = 0.5, .width = 0.5,
.height = 0.5, .height = 0.5,
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(15.0 / 16.0, @as(f32, @floatFromInt(i)) / 16.0, 16.0 / 16.0, @as(f32, @floatFromInt(i + 1)) / 16.0, 0.5, 0.5))), .mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
15.0 / 16.0,
@as(f32, @floatFromInt(i)) / 16.0,
16.0 / 16.0,
@as(f32, @floatFromInt(i + 1)) / 16.0,
0.5,
0.5,
))),
.texture = Assets.load(.texture, "data/yakuza.png"), .texture = Assets.load(.texture, "data/yakuza.png"),
.order = @intCast(i), .order = @intCast(i),
.id = @intCast(i), .id = @intCast(i),
.index = @intCast(i), .index = @intCast(i),
}; .parent = .{ .deck = 10 },
}) catch err.oom();
World.object_map.put(Game.alloc, @intCast(i), i) catch err.oom(); World.object_map.put(Game.alloc, @intCast(i), i) catch err.oom();
} }
Assets.free(Assets.load(.texture, "data/yakuza.png")); World.objects.append(Game.alloc, .{
.type = .deck,
.width = 1,
.height = 1,
.mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(
0.0 / 8.0,
4.0 / 8.0,
1.0 / 8.0,
5.0 / 8.0,
1,
1,
))),
.texture = Assets.load(.texture, "data/yakuza.png"),
.order = 10,
.id = 10,
.index = 10,
}) catch err.oom();
World.object_map.put(Game.alloc, 10, 10) catch err.oom();
World.plane_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
World.table_mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(0, 0, 0.5, 0.5, 8, 8))); World.table_mesh = Graphics.loadMesh(@ptrCast(&Graphics.generatePlane(0, 0, 0.5, 0.5, 8, 8)));
World.texture = Assets.load(.texture, "data/yakuza.png"); World.hand_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
World.table_texture = Assets.load(.texture, "data/yakuza.png");
World.hand_texture = Assets.load(.texture, "data/hand.png"); World.hand_texture = Assets.load(.texture, "data/hand.png");
World.camera_position = @splat(0); World.camera_position = @splat(0);
@@ -110,13 +149,13 @@ pub fn initDebug() void {
World.panning = false; World.panning = false;
World.dock_focused = false; World.dock_focused = false;
World.min_order = 0; World.min_order = 0;
World.max_order = 9; World.max_order = 10;
} }
pub fn deinit() void { pub fn deinit() void {
Graphics.unloadMesh(World.plane_mesh);
Graphics.unloadMesh(World.table_mesh); Graphics.unloadMesh(World.table_mesh);
Assets.free(World.texture); Graphics.unloadMesh(World.hand_mesh);
Assets.free(World.table_texture);
Assets.free(World.hand_texture); Assets.free(World.hand_texture);
for (World.objects.items) |*object| { for (World.objects.items) |*object| {
Assets.free(object.texture); Assets.free(object.texture);
@@ -166,7 +205,6 @@ pub fn update(delta: f32) void {
pub fn updateControls() void { pub fn updateControls() void {
if (Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) { if (Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) World.panning = true;
if (Game.mouse.wheel > 0 and World.hand_objects > 0) { if (Game.mouse.wheel > 0 and World.hand_objects > 0) {
var left_to_scroll = @rem(Game.mouse.wheel, @as(i32, @intCast(World.hand_objects))); var left_to_scroll = @rem(Game.mouse.wheel, @as(i32, @intCast(World.hand_objects)));
var i = World.objects.items.len - 1; var i = World.objects.items.len - 1;
@@ -190,14 +228,14 @@ pub fn updateControls() void {
} }
} }
} else { } else {
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
}
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) { if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) {
World.panning = !World.tryPick(); World.panning = !World.tryPick();
} }
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) { if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) {
_ = World.tryRelease(); _ = World.tryRelease();
} }
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
}
if (Game.mouse.y_norm <= -0.8) { if (Game.mouse.y_norm <= -0.8) {
World.dock_focused = true; World.dock_focused = true;
} }
@@ -208,7 +246,19 @@ pub fn updateControls() void {
pub fn tryPick() bool { pub fn tryPick() bool {
const hover_id = World.hover orelse return false; const hover_id = World.hover orelse return false;
const object = World.getObject(hover_id) orelse return false; var object = World.getObject(hover_id) orelse return false;
switch (object.type) {
.card => {},
.deck => {
if (!Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
for (World.objects.items) |*child| {
if (child.parent == .deck and child.parent.deck == object.id and child.id == object.child_last_id) {
object = child;
}
}
}
},
}
World.panning = false; World.panning = false;
object.reparent(.hand); object.reparent(.hand);
World.bringToTop(object); World.bringToTop(object);
@@ -230,18 +280,35 @@ pub fn tryRelease() bool {
}; };
object.target_transform.position = World.hand_transform.position; object.target_transform.position = World.hand_transform.position;
World.bringToTop(object); World.bringToTop(object);
if (World.dock_focused) if (!Game.keyboard.keys.is_pressed(sdl.SDL_SCANCODE_LSHIFT)) {
object.reparent(.dock) if (World.hover) |hover_id| {
else if (World.getObject(hover_id)) |hover_object| {
if (hover_object.type == .deck) {
object.reparent(.{ .deck = hover_id });
return true;
}
}
}
}
if (World.dock_focused) {
object.reparent(.dock);
return true;
} else {
object.reparent(.none); object.reparent(.none);
return true; return true;
}
} }
pub fn updateHover(object: *Object) void { pub fn updateHover(object: *Object) void {
switch (object.parent) { switch (object.parent) {
.deck => |id| {
if (World.getObject(id)) |deck| {
deck.child_last_id = object.id;
}
},
.none => { .none => {
if (!World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform, object.width, object.height)) { if (!World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.drawingTransform(), object.width, object.height)) {
if (World.hover == null or World.getObject(World.hover.?).?.index < object.index) { if (World.hover == null or World.getObject(World.hover.?).?.z < object.z) {
World.hover = object.id; World.hover = object.id;
} }
} }
@@ -255,7 +322,7 @@ pub fn updateHover(object: *Object) void {
World.dock_last_width = object.width * object.target_transform.scale; World.dock_last_width = object.width * object.target_transform.scale;
World.dock_objects += 1; World.dock_objects += 1;
if (World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform.combineTransforms(World.dock_transform), object.width, object.height)) { if (World.dock_focused and Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform.combineTransforms(World.dock_transform), object.width, object.height)) {
if (World.hover == null or World.getObject(World.hover.?).?.index < object.index) { if (World.hover == null or World.getObject(World.hover.?).?.z < object.z) {
World.hover = object.id; World.hover = object.id;
} }
} }
@@ -266,8 +333,8 @@ pub fn updateHover(object: *Object) void {
pub fn updateObject(object: *Object, delta: f32) void { pub fn updateObject(object: *Object, delta: f32) void {
switch (object.parent) { switch (object.parent) {
.none => { .none => {
object.target_transform.position[2] = if (World.hover == object.id) @as(f32, 0.1) else @as(f32, 0.001) * @as(f32, @floatFromInt(object.index + 1)); object.target_transform.position[2] = @as(f32, 0.001) * @as(f32, @floatFromInt(object.index + 1));
object.target_transform.scale = 1.0; object.target_transform.scale = if (World.hover == object.id) @as(f32, 1.1) else @as(f32, 1);
}, },
.hand => { .hand => {
var target_position = @as(@Vector(3, f32), @splat(0)); var target_position = @as(@Vector(3, f32), @splat(0));
@@ -287,24 +354,32 @@ pub fn updateObject(object: *Object, delta: f32) void {
object.target_transform.scale = target_scale; object.target_transform.scale = target_scale;
}, },
.dock => { .dock => {
var topleft_x = -World.dock_last_width * 0.5 + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5); var topleft_x = -World.dock_last_width * 0.5 * DOCK_TILT_COS + World.dock_spacing * (@as(f32, @floatFromInt(object.parent_index)) - @as(f32, @floatFromInt(World.dock_objects - 1)) * 0.5);
const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width; const total_w = @as(f32, @floatFromInt(World.dock_objects - 1)) * World.dock_spacing + World.dock_last_width * DOCK_TILT_COS;
if (total_w > Graphics.camera.aspect * 2) { if (total_w > Graphics.camera.aspect * 2) {
topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, Game.mouse.x_norm); topleft_x += math.lerp(0, Graphics.camera.aspect - total_w * 0.5, Game.mouse.x_norm);
} }
const hit = World.hover == object.id; const hit = World.hover == object.id;
const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2); const topleft_y = if (World.dock_focused) if (hit) @as(f32, 0.5) else @as(f32, 0.3) else @as(f32, 0.2);
object.target_transform.position = .{ object.target_transform.position = .{
topleft_x + object.width * 0.5 * object.target_transform.scale, topleft_x + object.width * 0.5 * object.target_transform.scale * DOCK_TILT_COS,
topleft_y - object.height * 0.5 * object.target_transform.scale, topleft_y - object.height * 0.5 * object.target_transform.scale,
if (hit) @as(f32, 0.02) else @as(f32, 0), if (hit) @as(f32, 0.02) else -object.width * 0.5 * DOCK_TILT_SIN,
}; };
object.target_transform.rotation = if (hit) object.target_transform.rotation = if (hit)
Graphics.Transform.ZERO.rotation Graphics.Transform.ZERO.rotation
else else
Graphics.Transform.rotationByAxis(.{ 0, 1, 0 }, 0.001); Graphics.Transform.rotationByAxis(.{ 0, 1, 0 }, DOCK_TILT);
},
.deck => {
object.target_transform.position = .{ 0, 0, @as(f32, 0.001) };
object.target_transform.scale = if (World.hover == object.id) @as(f32, 1.1) else @as(f32, 1);
}, },
} }
object.z = switch (object.parent) {
.deck => |deck_id| if (World.getObject(deck_id)) |deck| deck.z + object.index else object.index,
.none, .hand, .dock => object.index,
};
if (object.parent != .none) { if (object.parent != .none) {
object.influence = math.lerpTimeLn( object.influence = math.lerpTimeLn(
object.influence, object.influence,
@@ -322,15 +397,25 @@ pub fn updateObject(object: *Object, delta: f32) void {
} }
pub fn draw() void { pub fn draw() void {
Graphics.drawMesh(World.table_mesh, &World.texture, .{}); Graphics.drawMesh(World.table_mesh, &World.table_texture, .{});
for (World.objects.items) |*object| { for (World.objects.items) |*object| {
if (object.parent != .dock) sw: switch (object.parent) {
.none, .hand => {
Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform()); Graphics.drawMesh(object.mesh, &object.texture, object.drawingTransform());
},
.dock => {},
.deck => |id| {
if (World.getObject(id)) |deck| {
if (deck.child_last_id != object.id) continue;
}
continue :sw .none;
},
}
} }
Graphics.drawMesh( Graphics.drawMesh(
World.plane_mesh, World.hand_mesh,
&World.hand_texture, &World.hand_texture,
Graphics.Transform.combineTransforms( Graphics.Transform.combineTransforms(
.{ .{