diff --git a/src/frontend/globals.odin b/src/frontend/globals.odin index c9aae32..4f54a6b 100644 --- a/src/frontend/globals.odin +++ b/src/frontend/globals.odin @@ -4,10 +4,12 @@ import generator "../generator" import rl "vendor:raylib" PIXEL_WINDOW_HEIGHT :: 180 -FILE_DIALOG_SIZE :: 1000 scaling: f32 = 2 +@(rodata) +ATLAS_RENDER_SIZES := []i32{256, 512, 1024, 2048, 4096} + WindowInformation :: struct { w: f32, h: f32, @@ -22,9 +24,7 @@ MonitorInformation :: struct { FileDialogType :: enum { SourceFiles, - SourceFolder, OutputFolder, - SaveFileAs, } PackerSettings :: struct { @@ -37,28 +37,16 @@ PackerSettings :: struct { output_odin: bool, } -ApplicationState :: struct { - file_dialog_text_buffer: [FILE_DIALOG_SIZE + 1]u8, - is_packing_whole_source_folder: bool, - should_open_file_dialog: bool, - window_info: WindowInformation, - monitor_info: MonitorInformation, - // Where the output files will be written (atlas.png, json output, etc) - output_folder_path: Maybe(string), - // If files were chosen as input - their paths - source_location_to_pack: Maybe(string), - // If a folder was chosen as input - the path - source_files_to_pack: Maybe([]string), - // What type of file dialog to open - source_location_type: FileDialogType, - // Packer settings - packer_settings: PackerSettings, - atlas_render_texture_target: rl.RenderTexture2D, - atlas_checked_background: rl.RenderTexture2D, - should_render_atlas: bool, - atlas_render_has_preview: bool, - atlas_render_size: i32, - atlas_metadata: Maybe([dynamic]generator.SpriteAtlasMetadata), -} - -g_mem: ApplicationState +window_info: WindowInformation +monitor_info: MonitorInformation +// Where the output files will be written (atlas.png json output, etc) +output_folder_path: Maybe(string) +// If a folder was chosen as input - the path +source_files_to_pack: Maybe([]string) +// Packer settings +packer_settings: PackerSettings +atlas_render_texture_target: rl.RenderTexture2D +atlas_checked_background: rl.RenderTexture2D +atlas_render_has_preview: bool +atlas_render_size: i32 +atlas_metadata: Maybe([dynamic]generator.SpriteAtlasMetadata) diff --git a/src/frontend/main.odin b/src/frontend/main.odin index 5962de0..4efe66c 100644 --- a/src/frontend/main.odin +++ b/src/frontend/main.odin @@ -1,5 +1,7 @@ package frontend +import "base:runtime" +import "core:c/libc" import "core:fmt" import "core:log" import "core:math" @@ -12,59 +14,58 @@ import rl "vendor:raylib" import diag "../../vendors/dialog" import generator "../generator" +should_pack_atlas_and_render: bool + main :: proc() { default_allocator := context.allocator tracking_allocator: mem.Tracking_Allocator mem.tracking_allocator_init(&tracking_allocator, default_allocator) context.allocator = mem.tracking_allocator(&tracking_allocator) - mode: int = 0 - when ODIN_OS == .Linux || ODIN_OS == .Darwin { - mode = os.S_IRUSR | os.S_IWUSR | os.S_IRGRP | os.S_IROTH - } + context.logger = log.create_console_logger() + { + init() - logh, logh_err := os.open("log.txt", (os.O_CREATE | os.O_TRUNC | os.O_RDWR), mode) + defer cleanup() - if logh_err == os.ERROR_NONE { - os.stdout = logh - os.stderr = logh - } + for !rl.WindowShouldClose() { + update() + draw() - logger := - logh_err == os.ERROR_NONE ? log.create_file_logger(logh) : log.create_console_logger() - context.logger = logger - defer if logh_err == os.ERROR_NONE { - log.destroy_file_logger(logger) + for b in tracking_allocator.bad_free_array { + log.errorf("Bad free at: %v", b.location) + } + + clear(&tracking_allocator.bad_free_array) + + free_all(context.temp_allocator) + } } + log.destroy_console_logger(context.logger) + + for key, value in tracking_allocator.allocation_map { + log.errorf("%v: Leaked %v bytes\n", value.location, value.size) + } + mem.tracking_allocator_destroy(&tracking_allocator) +} + +init :: proc() { + atlas_render_size = ATLAS_RENDER_SIZES[0] rl.SetConfigFlags({.WINDOW_RESIZABLE}) rl.InitWindow(1400, 800, "YAAP - Yet Another Atlas Packer") - defer rl.CloseWindow() rl.SetWindowMinSize(1400, 800) + rl.SetTraceLogCallback(rl_log) +} - for !rl.WindowShouldClose() { - update() - draw() - - for b in tracking_allocator.bad_free_array { - log.error("Bad free at: %v", b.location) - } - - clear(&tracking_allocator.bad_free_array) - - free_all(context.temp_allocator) - } - - for key, value in tracking_allocator.allocation_map { - log.error("%v: Leaked %v bytes\n", value.location, value.size) - } - - mem.tracking_allocator_destroy(&tracking_allocator) +cleanup :: proc() { + log.info("Bye") + rl.CloseWindow() } update :: proc() { // Update the width/height - win_info := &g_mem.window_info + win_info := &window_info win_info.w = f32(rl.GetScreenWidth()) win_info.h = f32(rl.GetScreenHeight()) win_info.height_scaled = win_info.h / scaling @@ -73,10 +74,6 @@ update :: proc() { // Update the virtual mouse position (needed for GUI interaction to work properly for instance) mouse_scale := 1 / scaling rl.SetMouseScale(mouse_scale, mouse_scale) - - if g_mem.should_open_file_dialog { - open_file_dialog() - } } draw :: proc() { @@ -87,8 +84,8 @@ draw :: proc() { draw_screen_ui() - if g_mem.should_render_atlas { - draw_screen_target() + if should_pack_atlas_and_render { + pack_atlas_and_render() } free_all(context.temp_allocator) @@ -100,41 +97,23 @@ ui_camera :: proc() -> rl.Camera2D { draw_screen_ui :: proc() { rl.BeginMode2D(ui_camera()) - defer rl.EndMode2D() - draw_atlas_settings_and_preview() + draw_settings_and_preview() + + rl.EndMode2D() } -pick_sources :: proc() { - g_mem.should_open_file_dialog = true - g_mem.source_location_type = .SourceFiles +save_atlas_to_file :: proc() { + generator.save_output(output_folder_path, atlas_metadata, atlas_render_texture_target) } -pick_output :: proc() { - g_mem.should_open_file_dialog = true - g_mem.source_location_type = .OutputFolder +save_to_atlas_to_file :: proc() { + open_file_dialog(.OutputFolder) + save_atlas_to_file() } -pack_atlas :: proc() { - g_mem.should_render_atlas = true -} - -save :: proc() { - generator.save_output( - g_mem.output_folder_path, - g_mem.atlas_metadata, - g_mem.atlas_render_texture_target, - ) -} - -save_to :: proc() { - // if output_folder, ok := g_mem.output_folder_path.(string); ok { - // generator.save_metadata_simple(output_folder, g_mem.atlas_metadata, nil, nil, nil) - // } -} - -draw_screen_target :: proc() { - atlas_render_target := &g_mem.atlas_render_texture_target +pack_atlas_and_render :: proc() { + atlas_render_target := &atlas_render_texture_target rl.BeginTextureMode(atlas_render_target^) defer rl.EndTextureMode() @@ -142,28 +121,21 @@ draw_screen_target :: proc() { atlas_entries: [dynamic]generator.AtlasEntry delete(atlas_entries) - if files, ok := g_mem.source_files_to_pack.([]string); ok { + if files, ok := source_files_to_pack.([]string); ok { generator.unmarshall_aseprite_files(files, &atlas_entries) } else { log.error("No source folder or files set! Can't pack the void!!!") - g_mem.should_render_atlas = false + should_pack_atlas_and_render = false return } - atlas: rl.Image = rl.GenImageColor(g_mem.atlas_render_size, g_mem.atlas_render_size, rl.BLANK) + atlas: rl.Image = rl.GenImageColor(atlas_render_size, atlas_render_size, rl.BLANK) // defer rl.UnloadImage(atlas) - padding_x := - g_mem.packer_settings.pixel_padding_x_int if g_mem.packer_settings.padding_enabled else 0 - padding_y := - g_mem.packer_settings.pixel_padding_y_int if g_mem.packer_settings.padding_enabled else 0 + padding_x := packer_settings.pixel_padding_x_int if packer_settings.padding_enabled else 0 + padding_y := packer_settings.pixel_padding_y_int if packer_settings.padding_enabled else 0 - g_mem.atlas_metadata = generator.pack_atlas_entries( - atlas_entries[:], - &atlas, - padding_x, - padding_y, - ) + atlas_metadata = generator.pack_atlas_entries(atlas_entries[:], &atlas, padding_x, padding_y) // OpenGL's Y buffer is flipped rl.ImageFlipVertical(&atlas) @@ -171,28 +143,27 @@ draw_screen_target :: proc() { log.info("Packed everything!") atlas_render_target.texture = rl.LoadTextureFromImage(atlas) - g_mem.should_render_atlas = false - g_mem.atlas_render_has_preview = true + should_pack_atlas_and_render = false + atlas_render_has_preview = true } -draw_atlas_settings_and_preview :: proc() { +draw_settings_and_preview :: proc() { left_half_rect := rl.Rectangle { x = 0, y = 0, - width = cast(f32)g_mem.window_info.width_scaled / 3, - height = cast(f32)g_mem.window_info.height_scaled, + width = cast(f32)window_info.width_scaled / 3, + height = cast(f32)window_info.height_scaled, } right_half_rect := rl.Rectangle { - x = cast(f32)g_mem.window_info.width_scaled / 3, + x = cast(f32)window_info.width_scaled / 3, y = 0, - width = cast(f32)(g_mem.window_info.width_scaled / 3) * 2, - height = cast(f32)g_mem.window_info.height_scaled, + width = cast(f32)(window_info.width_scaled / 3) * 2, + height = cast(f32)window_info.height_scaled, } rl.DrawRectangleRec(left_half_rect, rl.WHITE) rl.DrawRectangleRec(right_half_rect, rl.MAROON) - @(static) - spinner_edit_mode: bool + @(static) spinner_edit_mode: bool small_offset := 10 * scaling big_offset := 30 * scaling @@ -201,10 +172,7 @@ draw_atlas_settings_and_preview :: proc() { rl.GuiPanel(left_half_rect, "Atlas Settings") elements_height += small_offset / 2 - @(static) - SettingsDropBoxEditMode: bool - @(static) - SettingsDropdownBoxActive: i32 + @(static) settings_dropdown_box_active_idx: i32 elements_height += small_offset + 5 * scaling @@ -214,10 +182,8 @@ draw_atlas_settings_and_preview :: proc() { ) elements_height += small_offset / 2 - @(static) - dropdown_resolution_edit_mode: bool - @(static) - dropdown_resolution_mode: i32 + @(static) dropdown_resolution_edit_mode: bool + @(static) dropdown_resolution_mode: i32 dropdown_rect := rl.Rectangle { x = small_offset, @@ -230,21 +196,21 @@ draw_atlas_settings_and_preview :: proc() { if dropdown_resolution_edit_mode {rl.GuiLock()} if rl.GuiDropdownBox( - dropdown_rect, - "256x;512x;1024x;2048x;4096x", - &dropdown_resolution_mode, - dropdown_resolution_edit_mode, - ) { + dropdown_rect, + "256x;512x;1024x;2048x;4096x", + &dropdown_resolution_mode, + dropdown_resolution_edit_mode, + ) { dropdown_resolution_edit_mode = !dropdown_resolution_edit_mode - g_mem.atlas_render_size = 256 * auto_cast math.pow(2, f32(dropdown_resolution_mode)) + atlas_render_size = + ATLAS_RENDER_SIZES[max(i32(len(ATLAS_RENDER_SIZES) - 1), dropdown_resolution_mode)] } rl.GuiUnlock() } elements_height += small_offset * 2 - // General Options - if SettingsDropdownBoxActive == 0 { + if settings_dropdown_box_active_idx == 0 { padding_settings_y := elements_height { defer { @@ -267,7 +233,7 @@ draw_atlas_settings_and_preview :: proc() { rl.GuiCheckBox( enable_padding_rect, " Enable padding", - &g_mem.packer_settings.padding_enabled, + &packer_settings.padding_enabled, ) elements_height += small_offset * 2 @@ -282,7 +248,7 @@ draw_atlas_settings_and_preview :: proc() { padding_x_spinner := rl.GuiSpinner( padding_x_spinner_rect, "", - &g_mem.packer_settings.pixel_padding_x_int, + &packer_settings.pixel_padding_x_int, 0, 10, spinner_edit_mode, @@ -291,7 +257,7 @@ draw_atlas_settings_and_preview :: proc() { spinner_edit_mode = !spinner_edit_mode } rl.GuiLabel( - { + { x = (small_offset * 2) + big_offset * 2, y = elements_height, width = big_offset, @@ -313,7 +279,7 @@ draw_atlas_settings_and_preview :: proc() { padding_y_spinner := rl.GuiSpinner( padding_y_spinner_rect, "", - &g_mem.packer_settings.pixel_padding_y_int, + &packer_settings.pixel_padding_y_int, 0, 10, spinner_edit_mode, @@ -322,7 +288,7 @@ draw_atlas_settings_and_preview :: proc() { spinner_edit_mode = !spinner_edit_mode } rl.GuiLabel( - { + { x = (small_offset * 2) + big_offset * 2, y = elements_height, width = big_offset, @@ -336,9 +302,6 @@ draw_atlas_settings_and_preview :: proc() { } elements_height += small_offset - // rl.GuiLine({y = elements_height, width = left_half_rect.width}, "Actions") - // elements_height += small_offset - { actions_label_y := elements_height @@ -360,7 +323,7 @@ draw_atlas_settings_and_preview :: proc() { height = small_offset, } if rl.GuiButton(pick_sources_rect, "Pick Source(s)") { - pick_sources() + open_file_dialog(.SourceFiles) } pick_output_rect := rl.Rectangle { @@ -370,7 +333,7 @@ draw_atlas_settings_and_preview :: proc() { height = small_offset, } if rl.GuiButton(pick_output_rect, "Pick Output") { - pick_output() + open_file_dialog(.OutputFolder) } elements_height += small_offset * 2 @@ -381,7 +344,7 @@ draw_atlas_settings_and_preview :: proc() { height = small_offset, } if rl.GuiButton(pack_atlas_rect, "Pack Atlas") { - pack_atlas() + should_pack_atlas_and_render = true } clear_atlas_rect := rl.Rectangle { @@ -402,7 +365,7 @@ draw_atlas_settings_and_preview :: proc() { height = small_offset, } if rl.GuiButton(save_rect, "Save") { - save() + save_atlas_to_file() } save_to_rect := rl.Rectangle { @@ -412,7 +375,7 @@ draw_atlas_settings_and_preview :: proc() { height = small_offset, } if rl.GuiButton(save_to_rect, "Save To...") { - save_to() + save_to_atlas_to_file() } elements_height += small_offset * 2 } @@ -420,10 +383,9 @@ draw_atlas_settings_and_preview :: proc() { } // Packing Options - if SettingsDropdownBoxActive == 1 { + if settings_dropdown_box_active_idx == 1 { - @(static) - active_tab: i32 + @(static) active_tab: i32 tabs: []cstring = {"One", "Two", "Three"} rl.GuiTabBar( {x = small_offset, y = elements_height, width = 100, height = small_offset}, @@ -434,9 +396,8 @@ draw_atlas_settings_and_preview :: proc() { } // Save Options - if SettingsDropdownBoxActive == 2 { - - } + // if settings_dropdown_box_active_idx == 2 { + // } elements_height = 0 rl.GuiPanel(right_half_rect, "Atlas Preview") @@ -450,11 +411,11 @@ draw_atlas_settings_and_preview :: proc() { width = short_edge, height = short_edge, } - if !g_mem.atlas_render_has_preview { + if !atlas_render_has_preview { rl.GuiDummyRec(preview_rect, "PREVIEW") } else { // rl.DrawRectangleRec(preview_rect, rl.WHITE) - bg_texture := g_mem.atlas_checked_background.texture + bg_texture := atlas_checked_background.texture rl.DrawTexturePro( bg_texture, {width = auto_cast bg_texture.width, height = auto_cast bg_texture.height}, @@ -463,9 +424,7 @@ draw_atlas_settings_and_preview :: proc() { 0, rl.WHITE, ) - // preview_rect.x += - // 10;preview_rect.y += 10;preview_rect.height -= 20;preview_rect.width -= 20 - atlas_texture := g_mem.atlas_render_texture_target.texture + atlas_texture := atlas_render_texture_target.texture rl.DrawTexturePro( atlas_texture, {width = auto_cast atlas_texture.width, height = auto_cast -atlas_texture.height}, @@ -477,96 +436,80 @@ draw_atlas_settings_and_preview :: proc() { } } -open_file_dialog :: proc() { - switch g_mem.source_location_type { +open_file_dialog :: proc(dialog_type: FileDialogType) { + switch dialog_type { case .SourceFiles: - // `open_file_dialog` returns a single cstring with one or more paths, divided by a separator ('|'), + // `open_file_dialog` returns a single cstring with one or more paths divided by a separator ('|'), // https://github.com/native-toolkit/libtinyfiledialogs/blob/master/tinyfiledialogs.c#L2706 file_paths_conc := cstring( - diag.open_file_dialog( - "Select source files", - cstring(&g_mem.file_dialog_text_buffer[0]), - 0, - nil, - "", - 1, - ), + diag.open_file_dialog("Select source files", nil, 0, nil, "", 1), ) if len(file_paths_conc) > 0 { - // todo(stefan): Currently we're not doing any checks if the filepaths are valid at all, - // this should be fine because it's returned by the OS' file picker but who knows... - source_files_to_pack := strings.clone_from_cstring(file_paths_conc, context.allocator) - g_mem.source_files_to_pack = strings.split(source_files_to_pack, "|") + // todo(stefan): We're assuming the filepaths returned libtinydialog are valid... + source_files := strings.clone_from_cstring(file_paths_conc, context.allocator) + source_files_to_pack = strings.split(source_files, "|") - log.info(g_mem.source_files_to_pack) + log.info(source_files_to_pack) } else { log.error("No files were selected!") } - case .SourceFolder: - file := cstring( - diag.select_folder_dialog( - "Select source folder", - cstring(&g_mem.file_dialog_text_buffer[0]), - ), - ) - if len(file) > 0 { - g_mem.source_location_to_pack = strings.clone_from_cstring(file) - log.info(g_mem.source_location_to_pack) - } else { - log.error("Got an empty path from the file dialog!") - } - case .OutputFolder: - file := cstring( - diag.select_folder_dialog( - "Select source folder", - cstring(&g_mem.file_dialog_text_buffer[0]), - ), - ) + file := cstring(diag.select_folder_dialog("Select source folder", nil)) if len(file) > 0 { - g_mem.output_folder_path = strings.clone_from_cstring(file) - log.info(g_mem.output_folder_path) + output_folder_path = strings.clone_from_cstring(file) + log.info(output_folder_path) } else { log.error("Got an empty path from the file dialog!") } - - case .SaveFileAs: - file_path: cstring - patterns: []cstring = {"*.png"} - if default_path, ok := g_mem.output_folder_path.(string); ok { - default_path_filename := strings.concatenate( - {default_path, generator.OS_FILE_SEPARATOR, "atlas.png"}, - ) - default_path_to_save: cstring = strings.clone_to_cstring(default_path_filename) - file_path = cstring( - diag.save_file_dialog( - "Save as...", - default_path_to_save, - 1, - &patterns[0], - "Atlas", - ), - ) - } else { - file_path = cstring(diag.save_file_dialog("Save as...", "", 1, &patterns[0], "Atlas")) - } - if file_path != nil { - generator.save_output( - g_mem.output_folder_path, - g_mem.atlas_metadata, - g_mem.atlas_render_texture_target, - ) - } } - - - g_mem.should_open_file_dialog = false } clear_atlas_data :: proc() { - if metadata, ok := g_mem.atlas_metadata.([dynamic]generator.SpriteAtlasMetadata); ok { + if metadata, ok := atlas_metadata.([dynamic]generator.SpriteAtlasMetadata); ok { delete(metadata) } - g_mem.atlas_render_has_preview = false + atlas_render_has_preview = false +} +logger: log.Logger +rl_log_buf: []byte +rl_log :: proc "c" (logLevel: rl.TraceLogLevel, text: cstring, args: ^libc.va_list) { + context = runtime.default_context() + context.logger = logger + + level: log.Level + switch logLevel { + case .TRACE, .DEBUG: + level = .Debug + case .ALL, .NONE, .INFO: + level = .Info + case .WARNING: + level = .Warning + case .ERROR: + level = .Error + case .FATAL: + level = .Fatal + } + + if level < logger.lowest_level { + return + } + + if rl_log_buf == nil { + rl_log_buf = make([]byte, 1024) + } + + defer mem.zero_slice(rl_log_buf) + + n: int + for { + va := args + n = int(libc.vsnprintf(raw_data(rl_log_buf), len(rl_log_buf), text, va)) + if n < len(rl_log_buf) do break + log.infof("Resizing raylib log buffer from %m to %m", len(rl_log_buf), len(rl_log_buf) * 2) + rl_log_buf, _ = mem.resize_bytes(rl_log_buf, len(rl_log_buf) * 2) + } + + formatted := string(rl_log_buf[:n]) + log.log(level, formatted) } diff --git a/src/generator/generator.odin b/src/generator/generator.odin index 34d6ab5..a3745af 100644 --- a/src/generator/generator.odin +++ b/src/generator/generator.odin @@ -182,28 +182,27 @@ pack_atlas_entries :: proc( atlas: ^rl.Image, offset_x: i32, offset_y: i32, - allocator := context.allocator, ) -> [dynamic]SpriteAtlasMetadata { assert(atlas.width != 0, "Atlas width shouldn't be 0!") assert(atlas.height != 0, "Atlas height shouldn't be 0!") - all_cell_images := make([dynamic]rl.Image, allocator) // it's fine to store it like this, rl.Image just stores a pointer to the data + all_cell_images := make([dynamic]rl.Image) // it's fine to store it like this, rl.Image just stores a pointer to the data for &entry in entries { for cell in entry.cells { append(&all_cell_images, cell.img) } - entry.layer_cell_count = make([dynamic]i32, len(entry.cells), allocator) + entry.layer_cell_count = make([dynamic]i32, len(entry.cells)) } num_entries := len(all_cell_images) - nodes := make([]stbrp.Node, num_entries, allocator) - rects := make([]stbrp.Rect, num_entries, allocator) + nodes := make([]stbrp.Node, num_entries) + rects := make([]stbrp.Rect, num_entries) EntryAndCell :: struct { entry: ^AtlasEntry, cell_of_entry: ^CellData, } - rect_idx_to_entry_and_cell := make(map[int]EntryAndCell, 100, allocator) + rect_idx_to_entry_and_cell := make(map[int]EntryAndCell, 100) // Set the custom IDs cellIdx: int @@ -241,15 +240,15 @@ pack_atlas_entries :: proc( src_rect := rl.Rectangle { x = 0, y = 0, - width = auto_cast cell.img.width, - height = auto_cast cell.img.height, + width = f32(cell.img.width), + height = f32(cell.img.height), } dst_rect := rl.Rectangle { - auto_cast rect.x + auto_cast offset_x, - auto_cast rect.y + auto_cast offset_y, - auto_cast cell.img.width, - auto_cast cell.img.height, + f32(i32(rect.x) + offset_x), + f32(i32(rect.y) + offset_y), + f32(cell.img.width), + f32(cell.img.height), } // note(stefan): drawing the sprite in the atlas in the packed coordinates @@ -258,7 +257,7 @@ pack_atlas_entries :: proc( log.infof("Src rect: {0}\nDst rect:{1}", src_rect, dst_rect) } - metadata := make([dynamic]SpriteAtlasMetadata, allocator) + metadata := make([dynamic]SpriteAtlasMetadata) for rect, rectIdx in rects { entry_and_cell := rect_idx_to_entry_and_cell[auto_cast rectIdx] entry := entry_and_cell.entry @@ -267,10 +266,9 @@ pack_atlas_entries :: proc( cell_name: string if entry.layer_cell_count[cell.layer_index] > 1 { cell_name = fmt.aprintf( - "{0}_%d", + "{0}_{1}", entry.layer_names[cell.layer_index], cell.frame_index, - allocator, ) } else { cell_name = entry.layer_names[cell.layer_index] @@ -278,8 +276,8 @@ pack_atlas_entries :: proc( cell_metadata := SpriteAtlasMetadata { name = cell_name, location = { - auto_cast rect.x + auto_cast offset_x, - auto_cast rect.y + auto_cast offset_y, + i32(rect.x) + offset_x, + i32(rect.y) + offset_y, }, size = {auto_cast cell.img.width, auto_cast cell.img.height}, } @@ -308,7 +306,7 @@ odin_source_generator_metadata := SourceCodeGeneratorMetadata { }, array_data = { name = "ATLAS_SPRITES", - type = "[]AtlasRect", + type = "[AtlasSprite]AtlasRect", begin_line = "%v := %v {{\n", entry_line = "\t.%v = {{ x = %v, y = %v, w = %v, h = %v }},\n", end_line = "}\n\n", @@ -369,7 +367,7 @@ generate_odin_enums_and_atlas_offsets_file_sb :: proc( // start offsets array // todo(stefan): the name of the array can be based on the output name? - strings.write_string(&sb, "ATLAS_SPRITES := []AtlasRect {\n") + strings.write_string(&sb, "ATLAS_SPRITES := [AtlasSprite]AtlasRect {\n") { entry: string for cell in metadata { diff --git a/vendors/dialog/build.sh b/vendors/dialog/build.sh index bea45c2..43b3bbc 100644 --- a/vendors/dialog/build.sh +++ b/vendors/dialog/build.sh @@ -1,7 +1,7 @@ #!/usr/bin/env sh +set -e + gcc ./libtinyfiledialogs/tinyfiledialogs.c -c -o libtinyfiledialogs.o - ar rcs libtinyfiledialogs.a libtinyfiledialogs.o - rm libtinyfiledialogs.o \ No newline at end of file