Reorganize globals and introduce an Atlas struct

This commit is contained in:
Stefan Stefanov 2026-01-02 19:03:06 +02:00
parent a51f5c6b57
commit b4f7fb4171
2 changed files with 46 additions and 41 deletions

View file

@ -5,27 +5,29 @@ import rl "vendor:raylib"
PIXEL_WINDOW_HEIGHT :: 180 PIXEL_WINDOW_HEIGHT :: 180
scaling: f32 = 2 ui_scaling: f32 = 2
@(rodata) @(rodata)
ATLAS_RENDER_SIZES := []i32{256, 512, 1024, 2048, 4096} ATLAS_RENDER_SIZES := []i32{256, 512, 1024, 2048, 4096}
FileDialogType :: enum {
SourceFiles,
OutputFolder,
}
WindowInformation :: struct { WindowInformation :: struct {
w: f32, w: f32,
h: f32, h: f32,
width_scaled: f32, width_scaled: f32,
height_scaled: f32, height_scaled: f32,
} }
window_info: WindowInformation
MonitorInformation :: struct { MonitorInformation :: struct {
max_width: f32, max_width: f32,
max_height: f32, max_height: f32,
} }
monitor_info: MonitorInformation
FileDialogType :: enum {
SourceFiles,
OutputFolder,
}
PackerSettings :: struct { PackerSettings :: struct {
atlas_size_x: i32, atlas_size_x: i32,
@ -36,17 +38,18 @@ PackerSettings :: struct {
output_json: bool, output_json: bool,
output_odin: bool, output_odin: bool,
} }
packer_settings: PackerSettings
window_info: WindowInformation
monitor_info: MonitorInformation
// Where the output files will be written (atlas.png json output, etc) // Where the output files will be written (atlas.png json output, etc)
output_folder_path: Maybe(string) output_folder_path: Maybe(string)
// If a folder was chosen as input - the path // If a folder was chosen as input - the path
source_files_to_pack: Maybe([]string) source_files_to_pack: Maybe([]string)
// Packer settings
packer_settings: PackerSettings Atlas :: struct {
atlas_render_texture_target: rl.RenderTexture2D render_texture_target: rl.RenderTexture2D,
atlas_checked_background: rl.RenderTexture2D checked_background: rl.RenderTexture2D,
atlas_render_has_preview: bool render_has_preview: bool,
atlas_render_size: i32 render_size: i32,
atlas_metadata: Maybe([dynamic]generator.SpriteAtlasMetadata) metadata: Maybe([dynamic]generator.SpriteAtlasMetadata),
}
atlas: Atlas

View file

@ -50,7 +50,7 @@ main :: proc() {
} }
init :: proc() { init :: proc() {
atlas_render_size = ATLAS_RENDER_SIZES[0] atlas.render_size = ATLAS_RENDER_SIZES[0]
rl.SetConfigFlags({.WINDOW_RESIZABLE}) rl.SetConfigFlags({.WINDOW_RESIZABLE})
rl.InitWindow(1400, 800, "YAAP - Yet Another Atlas Packer") rl.InitWindow(1400, 800, "YAAP - Yet Another Atlas Packer")
@ -68,11 +68,11 @@ update :: proc() {
win_info := &window_info win_info := &window_info
win_info.w = f32(rl.GetScreenWidth()) win_info.w = f32(rl.GetScreenWidth())
win_info.h = f32(rl.GetScreenHeight()) win_info.h = f32(rl.GetScreenHeight())
win_info.height_scaled = win_info.h / scaling win_info.height_scaled = win_info.h / ui_scaling
win_info.width_scaled = win_info.w / scaling win_info.width_scaled = win_info.w / ui_scaling
// Update the virtual mouse position (needed for GUI interaction to work properly for instance) // Update the virtual mouse position (needed for GUI interaction to work properly for instance)
mouse_scale := 1 / scaling mouse_scale := 1 / ui_scaling
rl.SetMouseScale(mouse_scale, mouse_scale) rl.SetMouseScale(mouse_scale, mouse_scale)
} }
@ -92,7 +92,7 @@ draw :: proc() {
} }
ui_camera :: proc() -> rl.Camera2D { ui_camera :: proc() -> rl.Camera2D {
return {zoom = scaling} return {zoom = ui_scaling}
} }
draw_screen_ui :: proc() { draw_screen_ui :: proc() {
@ -104,7 +104,7 @@ draw_screen_ui :: proc() {
} }
save_atlas_to_file :: proc() { save_atlas_to_file :: proc() {
generator.save_output(output_folder_path, atlas_metadata, atlas_render_texture_target) generator.save_output(output_folder_path, atlas.metadata, atlas.render_texture_target)
} }
save_to_atlas_to_file :: proc() { save_to_atlas_to_file :: proc() {
@ -113,9 +113,7 @@ save_to_atlas_to_file :: proc() {
} }
pack_atlas_and_render :: proc() { pack_atlas_and_render :: proc() {
atlas_render_target := &atlas_render_texture_target rl.BeginTextureMode(atlas.render_texture_target)
rl.BeginTextureMode(atlas_render_target^)
defer rl.EndTextureMode() defer rl.EndTextureMode()
atlas_entries: [dynamic]generator.AtlasEntry atlas_entries: [dynamic]generator.AtlasEntry
@ -129,22 +127,26 @@ pack_atlas_and_render :: proc() {
return return
} }
atlas: rl.Image = rl.GenImageColor(atlas_render_size, atlas_render_size, rl.BLANK) atlas_img: rl.Image = rl.GenImageColor(atlas.render_size, atlas.render_size, rl.BLANK)
// defer rl.UnloadImage(atlas)
padding_x := packer_settings.pixel_padding_x_int if 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 padding_y := packer_settings.pixel_padding_y_int if packer_settings.padding_enabled else 0
atlas_metadata = generator.pack_atlas_entries(atlas_entries[:], &atlas, padding_x, padding_y) atlas.metadata = generator.pack_atlas_entries(
atlas_entries[:],
&atlas_img,
padding_x,
padding_y,
)
// OpenGL's Y buffer is flipped // OpenGL's Y buffer is flipped
rl.ImageFlipVertical(&atlas) rl.ImageFlipVertical(&atlas_img)
// rl.UnloadTexture(atlas_render_target.texture) // rl.UnloadTexture(atlas_render_target.texture)
log.info("Packed everything!") log.info("Packed everything!")
atlas_render_target.texture = rl.LoadTextureFromImage(atlas) atlas.render_texture_target.texture = rl.LoadTextureFromImage(atlas_img)
should_pack_atlas_and_render = false should_pack_atlas_and_render = false
atlas_render_has_preview = true atlas.render_has_preview = true
} }
draw_settings_and_preview :: proc() { draw_settings_and_preview :: proc() {
@ -165,8 +167,8 @@ draw_settings_and_preview :: proc() {
@(static) spinner_edit_mode: bool @(static) spinner_edit_mode: bool
small_offset := 10 * scaling small_offset := 10 * ui_scaling
big_offset := 30 * scaling big_offset := 30 * ui_scaling
elements_height: f32 = 0 elements_height: f32 = 0
rl.GuiPanel(left_half_rect, "Atlas Settings") rl.GuiPanel(left_half_rect, "Atlas Settings")
@ -174,7 +176,7 @@ draw_settings_and_preview :: proc() {
@(static) settings_dropdown_box_active_idx: i32 @(static) settings_dropdown_box_active_idx: i32
elements_height += small_offset + 5 * scaling elements_height += small_offset + 5 * ui_scaling
rl.GuiLabel( rl.GuiLabel(
{x = small_offset, y = elements_height, width = left_half_rect.width}, {x = small_offset, y = elements_height, width = left_half_rect.width},
@ -202,7 +204,7 @@ draw_settings_and_preview :: proc() {
dropdown_resolution_edit_mode, dropdown_resolution_edit_mode,
) { ) {
dropdown_resolution_edit_mode = !dropdown_resolution_edit_mode dropdown_resolution_edit_mode = !dropdown_resolution_edit_mode
atlas_render_size = atlas.render_size =
ATLAS_RENDER_SIZES[max(i32(len(ATLAS_RENDER_SIZES) - 1), dropdown_resolution_mode)] ATLAS_RENDER_SIZES[max(i32(len(ATLAS_RENDER_SIZES) - 1), dropdown_resolution_mode)]
} }
rl.GuiUnlock() rl.GuiUnlock()
@ -411,11 +413,11 @@ draw_settings_and_preview :: proc() {
width = short_edge, width = short_edge,
height = short_edge, height = short_edge,
} }
if !atlas_render_has_preview { if !atlas.render_has_preview {
rl.GuiDummyRec(preview_rect, "PREVIEW") rl.GuiDummyRec(preview_rect, "PREVIEW")
} else { } else {
// rl.DrawRectangleRec(preview_rect, rl.WHITE) // rl.DrawRectangleRec(preview_rect, rl.WHITE)
bg_texture := atlas_checked_background.texture bg_texture := atlas.checked_background.texture
rl.DrawTexturePro( rl.DrawTexturePro(
bg_texture, bg_texture,
{width = auto_cast bg_texture.width, height = auto_cast bg_texture.height}, {width = auto_cast bg_texture.width, height = auto_cast bg_texture.height},
@ -424,7 +426,7 @@ draw_settings_and_preview :: proc() {
0, 0,
rl.WHITE, rl.WHITE,
) )
atlas_texture := atlas_render_texture_target.texture atlas_texture := atlas.render_texture_target.texture
rl.DrawTexturePro( rl.DrawTexturePro(
atlas_texture, atlas_texture,
{width = auto_cast atlas_texture.width, height = auto_cast -atlas_texture.height}, {width = auto_cast atlas_texture.width, height = auto_cast -atlas_texture.height},
@ -466,10 +468,10 @@ open_file_dialog :: proc(dialog_type: FileDialogType) {
} }
clear_atlas_data :: proc() { clear_atlas_data :: proc() {
if metadata, ok := atlas_metadata.([dynamic]generator.SpriteAtlasMetadata); ok { if metadata, ok := atlas.metadata.([dynamic]generator.SpriteAtlasMetadata); ok {
delete(metadata) delete(metadata)
} }
atlas_render_has_preview = false atlas.render_has_preview = false
} }
logger: log.Logger logger: log.Logger
rl_log_buf: []byte rl_log_buf: []byte