Scrolling and better hand stacking
This commit is contained in:
230
src/world.zig
230
src/world.zig
@@ -27,17 +27,25 @@ pub var max_order: Order = undefined;
|
||||
|
||||
const Object = struct {
|
||||
transform: Graphics.Transform = .{},
|
||||
target_transform: Graphics.Transform = .{},
|
||||
scale: Graphics.Transform.Scale,
|
||||
mesh: Graphics.Mesh,
|
||||
texture: Assets.Texture,
|
||||
order: Order,
|
||||
id: Id,
|
||||
index: u32,
|
||||
parent: enum {
|
||||
none,
|
||||
hand,
|
||||
} = .none,
|
||||
hand_index: u32 = 0,
|
||||
parent_infl: f32 = 0,
|
||||
influence: f32 = 0,
|
||||
|
||||
pub fn drawingTransform(self: @This()) Graphics.Transform {
|
||||
var transform = self.transform;
|
||||
transform.position += @as(@Vector(3, f32), @splat(self.influence)) * World.hand_transform.position;
|
||||
return transform;
|
||||
}
|
||||
};
|
||||
|
||||
const World = @This();
|
||||
@@ -54,6 +62,7 @@ pub fn initDebug() void {
|
||||
.texture = Assets.load(.texture, "data/yakuza.png"),
|
||||
.order = @intCast(i),
|
||||
.id = @intCast(i),
|
||||
.index = @intCast(i),
|
||||
};
|
||||
World.object_map.put(Game.alloc, @intCast(i), i) catch err.oom();
|
||||
}
|
||||
@@ -88,12 +97,13 @@ pub fn deinit() void {
|
||||
}
|
||||
|
||||
pub fn update(delta: f32) void {
|
||||
World.updateOrder();
|
||||
const hand_target = Graphics.camera.raycast(.{ Game.mouse.x_norm, Game.mouse.y_norm }, .{ 0, 0, 1, 0 });
|
||||
World.hand_transform.position = math.lerpTimeLn(
|
||||
World.hand_transform.position,
|
||||
hand_target + @Vector(3, f32){ World.hand_transform.scale[0] * 0.5, -World.hand_transform.scale[1] * 0.5, 0.25 },
|
||||
hand_target + @Vector(3, f32){ World.hand_transform.scale[0] * 0.5, -World.hand_transform.scale[1] * 0.5, 0.2 },
|
||||
delta,
|
||||
-16,
|
||||
-24,
|
||||
);
|
||||
World.hover = null;
|
||||
World.hand_objects = 0;
|
||||
@@ -103,21 +113,53 @@ pub fn update(delta: f32) void {
|
||||
for (World.objects.items) |*object| {
|
||||
updateObject(object, delta);
|
||||
}
|
||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) {
|
||||
World.panning = !World.tryPick();
|
||||
}
|
||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) {
|
||||
_ = World.tryRelease();
|
||||
}
|
||||
World.updateControls();
|
||||
World.updateCamera(delta);
|
||||
}
|
||||
|
||||
pub fn updateControls() void {
|
||||
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) {
|
||||
var left_to_scroll = @rem(Game.mouse.wheel, @as(i32, @intCast(World.hand_objects)));
|
||||
var i = World.objects.items.len - 1;
|
||||
while (left_to_scroll > 0) : (i -= 1) {
|
||||
const object = &World.objects.items[i];
|
||||
if (object.parent != .hand) continue;
|
||||
|
||||
World.bringToBottom(object);
|
||||
left_to_scroll -= 1;
|
||||
}
|
||||
}
|
||||
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 i: usize = 0;
|
||||
while (left_to_scroll > 0) : (i += 1) {
|
||||
const object = &World.objects.items[i];
|
||||
if (object.parent != .hand) continue;
|
||||
|
||||
World.bringToTop(object);
|
||||
left_to_scroll -= 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_LEFT)) {
|
||||
World.panning = !World.tryPick();
|
||||
}
|
||||
if (Game.mouse.buttons.is_just_pressed(sdl.BUTTON_RIGHT)) {
|
||||
_ = World.tryRelease();
|
||||
}
|
||||
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tryPick() bool {
|
||||
if (World.hover) |hover_id| {
|
||||
World.panning = false;
|
||||
World.getObject(hover_id).?.parent = .hand;
|
||||
return true;
|
||||
} else return false;
|
||||
const hover_id = World.hover orelse return false;
|
||||
const object = World.getObject(hover_id) orelse return false;
|
||||
World.panning = false;
|
||||
object.parent = .hand;
|
||||
World.bringToTop(object);
|
||||
return true;
|
||||
}
|
||||
pub fn tryRelease() bool {
|
||||
var last: ?*Object = null;
|
||||
@@ -126,6 +168,13 @@ pub fn tryRelease() bool {
|
||||
last = object;
|
||||
}
|
||||
if (last) |object| {
|
||||
object.transform = object.drawingTransform();
|
||||
object.target_transform.position = World.hand_transform.position + @Vector(3, f32){
|
||||
-World.hand_transform.scale[0] * 0.5,
|
||||
World.hand_transform.scale[1] * 0.5,
|
||||
0,
|
||||
};
|
||||
object.influence = 0;
|
||||
object.parent = .none;
|
||||
return true;
|
||||
}
|
||||
@@ -138,8 +187,8 @@ pub fn updateHover(object: *Object) void {
|
||||
World.hand_objects += 1;
|
||||
return;
|
||||
}
|
||||
if (Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.transform)) {
|
||||
if (World.hover == null or World.getObject(World.hover.?).?.transform.position[2] < object.transform.position[2]) {
|
||||
if (Graphics.camera.mouse_in_quad(.{ Game.mouse.x_norm, Game.mouse.y_norm }, object.target_transform)) {
|
||||
if (World.hover == null or World.getObject(World.hover.?).?.index < object.index) {
|
||||
World.hover = object.id;
|
||||
}
|
||||
}
|
||||
@@ -148,23 +197,13 @@ pub fn updateHover(object: *Object) void {
|
||||
pub fn updateObject(object: *Object, delta: f32) void {
|
||||
switch (object.parent) {
|
||||
.none => {
|
||||
object.transform.position[2] = math.lerpTimeLn(
|
||||
object.transform.position[2],
|
||||
if (World.hover == object.id) @as(f32, 0.125) else @as(f32, 0.0625),
|
||||
delta,
|
||||
-8,
|
||||
);
|
||||
object.transform.scale = math.lerpTimeLn(
|
||||
object.transform.scale,
|
||||
if (World.hover == object.id) object.scale * @as(@Vector(3, f32), @splat(1.25)) else object.scale,
|
||||
delta,
|
||||
-4,
|
||||
);
|
||||
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.scale = object.scale;
|
||||
},
|
||||
.hand => {
|
||||
var target_position = World.hand_transform.position;
|
||||
var target_position = @as(@Vector(3, f32), @splat(0));
|
||||
var target_scale = object.scale;
|
||||
target_position[2] *= 0.5;
|
||||
target_position[2] -= 0.001;
|
||||
const hand_order = hand_objects - object.hand_index - 1;
|
||||
switch (hand_order) {
|
||||
0 => {
|
||||
@@ -172,38 +211,47 @@ pub fn updateObject(object: *Object, delta: f32) void {
|
||||
target_position[1] += World.hand_transform.scale[1] * 0.5;
|
||||
},
|
||||
else => |i| {
|
||||
target_position[0] += World.hand_transform.scale[0] * if ((i - 1) & 1 == 0) @as(f32, 0.5) else @as(f32, 1);
|
||||
target_position[0] += World.hand_transform.scale[0] * if (i & 2 == 0) @as(f32, 0.5) else @as(f32, 1);
|
||||
target_position[1] += World.hand_transform.scale[1] * if ((i - 1) & 2 == 0) @as(f32, 0.25) else @as(f32, -0.25);
|
||||
target_position[2] -= @as(f32, @floatFromInt((hand_order - 1) / 4)) * 0.01;
|
||||
target_position[2] -= @as(f32, @floatFromInt((hand_order - 1) / 4)) * 0.001;
|
||||
target_scale = math.limit(target_scale, World.hand_transform.scale[1] * 0.5);
|
||||
},
|
||||
}
|
||||
object.transform.position = math.lerpTimeLn(
|
||||
object.transform.position,
|
||||
target_position,
|
||||
delta,
|
||||
-16,
|
||||
);
|
||||
object.transform.scale = math.lerpTimeLn(
|
||||
object.transform.scale,
|
||||
target_scale,
|
||||
delta,
|
||||
-4,
|
||||
);
|
||||
object.target_transform.position = target_position;
|
||||
object.target_transform.scale = target_scale;
|
||||
},
|
||||
}
|
||||
if (object.parent == .hand) {
|
||||
object.influence = math.lerpTimeLn(
|
||||
object.influence,
|
||||
1.0,
|
||||
delta,
|
||||
-8,
|
||||
);
|
||||
}
|
||||
object.transform.position = math.lerpTimeLn(
|
||||
object.transform.position,
|
||||
object.target_transform.position,
|
||||
delta,
|
||||
-8,
|
||||
);
|
||||
object.transform.scale = math.lerpTimeLn(
|
||||
object.transform.scale,
|
||||
object.target_transform.scale,
|
||||
delta,
|
||||
-8,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn draw() void {
|
||||
Graphics.drawMesh(World.table_mesh, World.texture, Graphics.Transform.matrix(.{ .scale = @splat(8) }));
|
||||
for (World.objects.items) |*object| {
|
||||
Graphics.drawMesh(object.mesh, object.texture, object.transform.matrix());
|
||||
Graphics.drawMesh(object.mesh, object.texture, object.drawingTransform().matrix());
|
||||
}
|
||||
Graphics.drawMesh(World.plane_mesh, World.hand_texture, World.hand_transform.matrix());
|
||||
}
|
||||
|
||||
pub fn updateCamera(delta: f32) void {
|
||||
World.zoom = std.math.clamp(World.zoom + Game.mouse.wheel, -4, 8);
|
||||
const zoom_factor = std.math.exp(@as(f32, @floatFromInt(zoom)) * @log(2.0) * -0.5);
|
||||
|
||||
if (Game.mouse.buttons.is_pressed(sdl.BUTTON_LEFT)) {
|
||||
@@ -258,48 +306,72 @@ fn bringToBottom(object: *Object) void {
|
||||
object.order = World.min_order;
|
||||
}
|
||||
|
||||
const CUBE_MESH_DATA = [_]f32{
|
||||
-0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
var even: bool = false;
|
||||
fn updateOrder() void {
|
||||
var i: usize = undefined;
|
||||
if (even) i = 0 else i = 1;
|
||||
even = !even;
|
||||
|
||||
0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
while (i + 1 < World.objects.items.len) : (i += 2) {
|
||||
const left = &World.objects.items[i];
|
||||
const right = &World.objects.items[i + 1];
|
||||
|
||||
if (left.order <= right.order) continue;
|
||||
std.mem.swap(u32, &left.index, &right.index);
|
||||
|
||||
World.object_map.putAssumeCapacity(left.id, left.index);
|
||||
World.object_map.putAssumeCapacity(right.id, right.index);
|
||||
|
||||
std.mem.swap(Object, left, right);
|
||||
}
|
||||
}
|
||||
|
||||
const CUBEMAP_MESH_DATA = CUBE_MESH_DATA;
|
||||
|
||||
const T1 = 1.0 / 3.0;
|
||||
const T2 = 2.0 / 3.0;
|
||||
const CUBE_MESH_DATA = [_]f32{
|
||||
-0.5, 0.5, -0.5, T2, 0,
|
||||
-0.5, -0.5, -0.5, T2, 0.5,
|
||||
0.5, 0.5, -0.5, 1, 0,
|
||||
0.5, -0.5, -0.5, 1, 0.5,
|
||||
0.5, 0.5, -0.5, 1, 0,
|
||||
-0.5, -0.5, -0.5, T2, 0.5,
|
||||
|
||||
0.5, 0.5, -0.5, 0, 1,
|
||||
0.5, -0.5, -0.5, T1, 1,
|
||||
0.5, 0.5, 0.5, 0, 0.5,
|
||||
0.5, -0.5, 0.5, T1, 0.5,
|
||||
0.5, 0.5, 0.5, 0, 0.5,
|
||||
0.5, -0.5, -0.5, T1, 1,
|
||||
|
||||
0.5, 0.5, 0.5, 1.0, 0.0,
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, 0.5, 1.0, 1.0,
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.5, 0.0, 1.0,
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, 0.5, 1.0, 1.0,
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, 0.5, T1, 0,
|
||||
-0.5, -0.5, 0.5, 0, 0,
|
||||
-0.5, 0.5, -0.5, T1, 0.5,
|
||||
-0.5, -0.5, -0.5, 0, 0.5,
|
||||
-0.5, 0.5, -0.5, T1, 0.5,
|
||||
-0.5, -0.5, 0.5, 0, 0,
|
||||
|
||||
-0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, -0.5, 0.0, 0.0,
|
||||
0.5, 0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, 0.5, 0.5, T1, 0.5,
|
||||
-0.5, 0.5, -0.5, T1, 1,
|
||||
0.5, 0.5, 0.5, T2, 0.5,
|
||||
0.5, 0.5, -0.5, T2, 1,
|
||||
0.5, 0.5, 0.5, T2, 0.5,
|
||||
-0.5, 0.5, -0.5, T1, 1,
|
||||
|
||||
-0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.5, 0.0, 0.0,
|
||||
0.5, -0.5, -0.5, 0.0, 0.0,
|
||||
-0.5, -0.5, -0.5, T2, 0.5,
|
||||
-0.5, -0.5, 0.5, T2, 0,
|
||||
0.5, -0.5, -0.5, T1, 0.5,
|
||||
0.5, -0.5, 0.5, T1, 0,
|
||||
0.5, -0.5, -0.5, T1, 0.5,
|
||||
-0.5, -0.5, 0.5, T2, 0,
|
||||
};
|
||||
const PLANE_MESH_DATA = [_]f32{
|
||||
-0.5, -0.5, 0, 0.0, 1.0,
|
||||
|
Reference in New Issue
Block a user