diff --git a/src/Pixi.zig b/src/Pixi.zig index a1dcc05..78d706a 100644 --- a/src/Pixi.zig +++ b/src/Pixi.zig @@ -1,28 +1,33 @@ +// Imports const std = @import("std"); - const mach = @import("mach"); -const Core = mach.Core; const gpu = mach.gpu; const zstbi = @import("zstbi"); const zm = @import("zmath"); const nfd = @import("nfd"); - const imgui = @import("zig-imgui"); const imgui_mach = imgui.backends.mach; // Modules +const Core = mach.Core; pub const App = @This(); pub const Editor = @import("editor/Editor.zig"); +// Global pointers +pub var core: *Core = undefined; +pub var app: *App = undefined; +pub var editor: *Editor = undefined; + +// Mach module, systems, and main pub const mach_module = .app; pub const mach_systems = .{ .main, .init, .lateInit, .tick, .deinit }; - pub const main = mach.schedule(.{ .{ Core, .init }, .{ App, .init }, .{ Core, .main }, }); +// App fields timer: mach.time.Timer, window: mach.ObjectID, @@ -39,8 +44,6 @@ recents: Recents = undefined, previous_atlas_export: ?[:0]const u8 = null, open_files: std.ArrayList(storage.Internal.PixiFile) = undefined, open_references: std.ArrayList(storage.Internal.Reference) = undefined, -pack_target: PackTarget = .project, -pack_camera: gfx.Camera = .{}, packer: Packer = undefined, atlas: storage.Internal.Atlas = .{}, open_file_index: usize = 0, @@ -88,10 +91,6 @@ test { _ = input; } -pub var app: *App = undefined; -pub var core: *Core = undefined; -pub var editor: *Editor = undefined; - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; pub const Colors = @import("Colors.zig"); @@ -133,12 +132,6 @@ pub const Fonts = struct { fa_small_solid: *imgui.Font = undefined, }; -pub const PackTarget = enum { - project, - all_open, - single_open, -}; - pub fn init(_app: *App, _core: *Core, app_mod: mach.Mod(App), _editor: *Editor) !void { app = _app; core = _core; diff --git a/src/editor/artboard/canvas_pack.zig b/src/editor/artboard/canvas_pack.zig index d2da8d1..4cd1d02 100644 --- a/src/editor/artboard/canvas_pack.zig +++ b/src/editor/artboard/canvas_pack.zig @@ -13,35 +13,41 @@ pub fn draw(mode: PackTexture) void { .diffusemap => Pixi.app.atlas.diffusemap, .heightmap => Pixi.app.atlas.heightmap, }) |texture| { - const window_width = imgui.getWindowWidth(); - const window_height = imgui.getWindowHeight(); - const file_width = @as(f32, @floatFromInt(texture.image.width)); - const file_height = @as(f32, @floatFromInt(texture.image.height)); - - var camera = &Pixi.app.pack_camera; - - // Handle zooming, panning and extents - { - var sprite_camera: Pixi.gfx.Camera = .{ - .zoom = @min(window_width / file_width, window_height / file_height), - }; - sprite_camera.setNearestZoomFloor(); - if (!camera.zoom_initialized) { - camera.zoom_initialized = true; - camera.zoom = sprite_camera.zoom; + var canvas_flags: imgui.WindowFlags = 0; + canvas_flags |= imgui.WindowFlags_HorizontalScrollbar; + if (imgui.beginChild( + "PackerCanvas", + .{ .x = 0.0, .y = 0.0 }, + imgui.ChildFlags_None, + canvas_flags, + )) { + const window_width = imgui.getWindowWidth(); + const window_height = imgui.getWindowHeight(); + const file_width = @as(f32, @floatFromInt(texture.image.width)); + const file_height = @as(f32, @floatFromInt(texture.image.height)); + + var camera = &Pixi.app.packer.camera; + + // Handle zooming, panning and extents + { + var sprite_camera: Pixi.gfx.Camera = .{ + .zoom = @min(window_width / file_width, window_height / file_height), + }; + sprite_camera.setNearestZoomFloor(); + if (!camera.zoom_initialized) { + camera.zoom_initialized = true; + camera.zoom = sprite_camera.zoom; + } + sprite_camera.setNearestZoomFloor(); + camera.min_zoom = @min(sprite_camera.zoom, 1.0); + + camera.processPanZoom(.packer); } - sprite_camera.setNearestZoomFloor(); - camera.min_zoom = @min(sprite_camera.zoom, 1.0); - camera.processPanZoom(.primary); - } - - if (imgui.isWindowHovered(imgui.HoveredFlags_None)) { - camera.processZoomTooltip(); - } + if (imgui.isWindowHovered(imgui.HoveredFlags_None)) { + camera.processZoomTooltip(); + } - // Draw the packed atlas texture - { const width: f32 = @floatFromInt(texture.image.width); const height: f32 = @floatFromInt(texture.image.height); @@ -49,5 +55,9 @@ pub fn draw(mode: PackTexture) void { camera.drawTexture(texture.view_handle, texture.image.width, texture.image.height, center_offset, 0xFFFFFFFF); camera.drawRect(.{ center_offset[0], center_offset[1], width, height }, 2.0, Pixi.editor.theme.text_secondary.toU32()); } + imgui.endChild(); + + // Draw the packed atlas texture + {} } } diff --git a/src/editor/explorer/pack.zig b/src/editor/explorer/pack.zig index c238395..480ea85 100644 --- a/src/editor/explorer/pack.zig +++ b/src/editor/explorer/pack.zig @@ -14,20 +14,20 @@ pub fn draw() !void { const window_size = imgui.getContentRegionAvail(); - switch (Pixi.app.pack_target) { + switch (Pixi.app.packer.target) { .all_open => { if (Pixi.app.open_files.items.len <= 1) { - Pixi.app.pack_target = .project; + Pixi.app.packer.target = .project; } }, .single_open => { if (Pixi.app.open_files.items.len == 0) - Pixi.app.pack_target = .project; + Pixi.app.packer.target = .project; }, else => {}, } - const preview_text = switch (Pixi.app.pack_target) { + const preview_text = switch (Pixi.app.packer.target) { .project => "Full Project", .all_open => "All Open Files", .single_open => "Current Open File", @@ -36,20 +36,20 @@ pub fn draw() !void { if (imgui.beginCombo("Files", preview_text.ptr, imgui.ComboFlags_None)) { defer imgui.endCombo(); if (imgui.menuItem("Full Project")) { - Pixi.app.pack_target = .project; + Pixi.app.packer.target = .project; } { const enabled = if (Pixi.Editor.getFile(Pixi.app.open_file_index)) |_| true else false; if (imgui.menuItemEx("Current Open File", null, false, enabled)) { - Pixi.app.pack_target = .single_open; + Pixi.app.packer.target = .single_open; } } { const enabled = if (Pixi.app.open_files.items.len > 1) true else false; if (imgui.menuItemEx("All Open Files", null, false, enabled)) { - Pixi.app.pack_target = .all_open; + Pixi.app.packer.target = .all_open; } } } @@ -64,8 +64,8 @@ pub fn draw() !void { { var packable: bool = true; - if (Pixi.app.pack_target == .project and Pixi.app.project_folder == null) packable = false; - if (Pixi.app.pack_target == .all_open and Pixi.app.open_files.items.len <= 1) packable = false; + if (Pixi.app.packer.target == .project and Pixi.app.project_folder == null) packable = false; + if (Pixi.app.packer.target == .all_open and Pixi.app.open_files.items.len <= 1) packable = false; if (Pixi.Editor.saving()) { imgui.pushStyleColorImVec4(imgui.Col_Text, Pixi.editor.theme.text_background.toImguiVec4()); defer imgui.popStyleColor(); @@ -76,7 +76,7 @@ pub fn draw() !void { if (!packable) imgui.beginDisabled(true); if (imgui.buttonEx("Pack", .{ .x = window_size.x, .y = 0.0 })) { - switch (Pixi.app.pack_target) { + switch (Pixi.app.packer.target) { .project => { if (Pixi.app.project_folder) |folder| { try Pixi.Packer.recurseFiles(Pixi.app.allocator, folder); @@ -100,7 +100,7 @@ pub fn draw() !void { if (!packable) imgui.endDisabled(); - if (Pixi.app.pack_target == .project and Pixi.app.project_folder == null) { + if (Pixi.app.packer.target == .project and Pixi.app.project_folder == null) { imgui.pushStyleColorImVec4(imgui.Col_Text, Pixi.editor.theme.text_background.toImguiVec4()); defer imgui.popStyleColor(); imgui.textWrapped("Select a project folder to pack."); diff --git a/src/gfx/camera.zig b/src/gfx/camera.zig index 8a9a408..3abc7cd 100644 --- a/src/gfx/camera.zig +++ b/src/gfx/camera.zig @@ -654,6 +654,7 @@ pub const Camera = struct { primary, flipbook, reference, + packer, }; pub fn processPanZoom(camera: *Camera, target: PanZoomTarget) void { @@ -661,20 +662,25 @@ pub const Camera = struct { if (Pixi.app.settings.input_scheme != .trackpad) zoom_key = true; if (Pixi.app.mouse.magnify != null) zoom_key = true; + if (target == .packer and Pixi.app.atlas.diffusemap == null) return; + const canvas_center_offset = switch (target) { .primary => Pixi.app.open_files.items[Pixi.app.open_file_index].canvasCenterOffset(.primary), .flipbook => Pixi.app.open_files.items[Pixi.app.open_file_index].canvasCenterOffset(.flipbook), .reference => Pixi.app.open_references.items[Pixi.app.open_reference_index].canvasCenterOffset(), + .packer => .{ -@as(f32, @floatFromInt(Pixi.app.atlas.diffusemap.?.image.width)) / 2.0, -@as(f32, @floatFromInt(Pixi.app.atlas.diffusemap.?.image.height)) / 2.0 }, }; const canvas_width = switch (target) { .primary, .flipbook => Pixi.app.open_files.items[Pixi.app.open_file_index].width, .reference => Pixi.app.open_references.items[Pixi.app.open_reference_index].texture.image.width, + .packer => Pixi.app.atlas.diffusemap.?.image.width, }; const canvas_height = switch (target) { .primary, .flipbook => Pixi.app.open_files.items[Pixi.app.open_file_index].height, .reference => Pixi.app.open_references.items[Pixi.app.open_reference_index].texture.image.height, + .packer => Pixi.app.atlas.diffusemap.?.image.height, }; const previous_zoom = camera.zoom; @@ -773,7 +779,7 @@ pub const Camera = struct { } switch (target) { - .primary, .reference => { + .primary, .reference, .packer => { // Lock camera from zooming in or out too far for the flipbook camera.zoom = std.math.clamp(camera.zoom, camera.min_zoom, Pixi.app.settings.zoom_steps[Pixi.app.settings.zoom_steps.len - 1]); diff --git a/src/tools/Packer.zig b/src/tools/Packer.zig index 58695e9..de4ad6a 100644 --- a/src/tools/Packer.zig +++ b/src/tools/Packer.zig @@ -41,11 +41,19 @@ id_counter: u32 = 0, placeholder: Image, contains_height: bool = false, open_files: std.ArrayList(Pixi.storage.Internal.PixiFile), +target: PackTarget = .project, +camera: Pixi.gfx.Camera = .{}, allocator: std.mem.Allocator, ldtk: bool = false, ldtk_tilesets: std.ArrayList(LDTKTileset), +pub const PackTarget = enum { + project, + all_open, + single_open, +}; + pub fn init(allocator: std.mem.Allocator) !Packer { const pixels: [][4]u8 = try allocator.alloc([4]u8, 4); for (pixels) |*pixel| {