More cleanup. Hooray!
This commit is contained in:
parent
faf42da522
commit
a51f5c6b57
4 changed files with 180 additions and 251 deletions
|
|
@ -4,10 +4,12 @@ import generator "../generator"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
PIXEL_WINDOW_HEIGHT :: 180
|
PIXEL_WINDOW_HEIGHT :: 180
|
||||||
FILE_DIALOG_SIZE :: 1000
|
|
||||||
|
|
||||||
scaling: f32 = 2
|
scaling: f32 = 2
|
||||||
|
|
||||||
|
@(rodata)
|
||||||
|
ATLAS_RENDER_SIZES := []i32{256, 512, 1024, 2048, 4096}
|
||||||
|
|
||||||
WindowInformation :: struct {
|
WindowInformation :: struct {
|
||||||
w: f32,
|
w: f32,
|
||||||
h: f32,
|
h: f32,
|
||||||
|
|
@ -22,9 +24,7 @@ MonitorInformation :: struct {
|
||||||
|
|
||||||
FileDialogType :: enum {
|
FileDialogType :: enum {
|
||||||
SourceFiles,
|
SourceFiles,
|
||||||
SourceFolder,
|
|
||||||
OutputFolder,
|
OutputFolder,
|
||||||
SaveFileAs,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PackerSettings :: struct {
|
PackerSettings :: struct {
|
||||||
|
|
@ -37,28 +37,16 @@ PackerSettings :: struct {
|
||||||
output_odin: bool,
|
output_odin: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationState :: struct {
|
window_info: WindowInformation
|
||||||
file_dialog_text_buffer: [FILE_DIALOG_SIZE + 1]u8,
|
monitor_info: MonitorInformation
|
||||||
is_packing_whole_source_folder: bool,
|
// Where the output files will be written (atlas.png json output, etc)
|
||||||
should_open_file_dialog: bool,
|
output_folder_path: Maybe(string)
|
||||||
window_info: WindowInformation,
|
// If a folder was chosen as input - the path
|
||||||
monitor_info: MonitorInformation,
|
source_files_to_pack: Maybe([]string)
|
||||||
// Where the output files will be written (atlas.png, json output, etc)
|
// Packer settings
|
||||||
output_folder_path: Maybe(string),
|
packer_settings: PackerSettings
|
||||||
// If files were chosen as input - their paths
|
atlas_render_texture_target: rl.RenderTexture2D
|
||||||
source_location_to_pack: Maybe(string),
|
atlas_checked_background: rl.RenderTexture2D
|
||||||
// If a folder was chosen as input - the path
|
atlas_render_has_preview: bool
|
||||||
source_files_to_pack: Maybe([]string),
|
atlas_render_size: i32
|
||||||
// What type of file dialog to open
|
atlas_metadata: Maybe([dynamic]generator.SpriteAtlasMetadata)
|
||||||
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
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package frontend
|
package frontend
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:c/libc"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
|
|
@ -12,59 +14,58 @@ import rl "vendor:raylib"
|
||||||
import diag "../../vendors/dialog"
|
import diag "../../vendors/dialog"
|
||||||
import generator "../generator"
|
import generator "../generator"
|
||||||
|
|
||||||
|
should_pack_atlas_and_render: bool
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
default_allocator := context.allocator
|
default_allocator := context.allocator
|
||||||
tracking_allocator: mem.Tracking_Allocator
|
tracking_allocator: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&tracking_allocator, default_allocator)
|
mem.tracking_allocator_init(&tracking_allocator, default_allocator)
|
||||||
context.allocator = mem.tracking_allocator(&tracking_allocator)
|
context.allocator = mem.tracking_allocator(&tracking_allocator)
|
||||||
|
|
||||||
mode: int = 0
|
context.logger = log.create_console_logger()
|
||||||
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
|
{
|
||||||
mode = os.S_IRUSR | os.S_IWUSR | os.S_IRGRP | os.S_IROTH
|
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 {
|
for !rl.WindowShouldClose() {
|
||||||
os.stdout = logh
|
update()
|
||||||
os.stderr = logh
|
draw()
|
||||||
}
|
|
||||||
|
|
||||||
logger :=
|
for b in tracking_allocator.bad_free_array {
|
||||||
logh_err == os.ERROR_NONE ? log.create_file_logger(logh) : log.create_console_logger()
|
log.errorf("Bad free at: %v", b.location)
|
||||||
context.logger = logger
|
}
|
||||||
defer if logh_err == os.ERROR_NONE {
|
|
||||||
log.destroy_file_logger(logger)
|
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.SetConfigFlags({.WINDOW_RESIZABLE})
|
||||||
rl.InitWindow(1400, 800, "YAAP - Yet Another Atlas Packer")
|
rl.InitWindow(1400, 800, "YAAP - Yet Another Atlas Packer")
|
||||||
defer rl.CloseWindow()
|
|
||||||
rl.SetWindowMinSize(1400, 800)
|
rl.SetWindowMinSize(1400, 800)
|
||||||
|
rl.SetTraceLogCallback(rl_log)
|
||||||
|
}
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
cleanup :: proc() {
|
||||||
update()
|
log.info("Bye")
|
||||||
draw()
|
rl.CloseWindow()
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update :: proc() {
|
update :: proc() {
|
||||||
// Update the width/height
|
// Update the width/height
|
||||||
win_info := &g_mem.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 / scaling
|
||||||
|
|
@ -73,10 +74,6 @@ update :: proc() {
|
||||||
// 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 / scaling
|
||||||
rl.SetMouseScale(mouse_scale, mouse_scale)
|
rl.SetMouseScale(mouse_scale, mouse_scale)
|
||||||
|
|
||||||
if g_mem.should_open_file_dialog {
|
|
||||||
open_file_dialog()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw :: proc() {
|
draw :: proc() {
|
||||||
|
|
@ -87,8 +84,8 @@ draw :: proc() {
|
||||||
|
|
||||||
draw_screen_ui()
|
draw_screen_ui()
|
||||||
|
|
||||||
if g_mem.should_render_atlas {
|
if should_pack_atlas_and_render {
|
||||||
draw_screen_target()
|
pack_atlas_and_render()
|
||||||
}
|
}
|
||||||
|
|
||||||
free_all(context.temp_allocator)
|
free_all(context.temp_allocator)
|
||||||
|
|
@ -100,41 +97,23 @@ ui_camera :: proc() -> rl.Camera2D {
|
||||||
|
|
||||||
draw_screen_ui :: proc() {
|
draw_screen_ui :: proc() {
|
||||||
rl.BeginMode2D(ui_camera())
|
rl.BeginMode2D(ui_camera())
|
||||||
defer rl.EndMode2D()
|
|
||||||
|
|
||||||
draw_atlas_settings_and_preview()
|
draw_settings_and_preview()
|
||||||
|
|
||||||
|
rl.EndMode2D()
|
||||||
}
|
}
|
||||||
|
|
||||||
pick_sources :: proc() {
|
save_atlas_to_file :: proc() {
|
||||||
g_mem.should_open_file_dialog = true
|
generator.save_output(output_folder_path, atlas_metadata, atlas_render_texture_target)
|
||||||
g_mem.source_location_type = .SourceFiles
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pick_output :: proc() {
|
save_to_atlas_to_file :: proc() {
|
||||||
g_mem.should_open_file_dialog = true
|
open_file_dialog(.OutputFolder)
|
||||||
g_mem.source_location_type = .OutputFolder
|
save_atlas_to_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_atlas :: proc() {
|
pack_atlas_and_render :: proc() {
|
||||||
g_mem.should_render_atlas = true
|
atlas_render_target := &atlas_render_texture_target
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
rl.BeginTextureMode(atlas_render_target^)
|
rl.BeginTextureMode(atlas_render_target^)
|
||||||
defer rl.EndTextureMode()
|
defer rl.EndTextureMode()
|
||||||
|
|
@ -142,28 +121,21 @@ draw_screen_target :: proc() {
|
||||||
atlas_entries: [dynamic]generator.AtlasEntry
|
atlas_entries: [dynamic]generator.AtlasEntry
|
||||||
delete(atlas_entries)
|
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)
|
generator.unmarshall_aseprite_files(files, &atlas_entries)
|
||||||
} else {
|
} else {
|
||||||
log.error("No source folder or files set! Can't pack the void!!!")
|
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
|
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)
|
// defer rl.UnloadImage(atlas)
|
||||||
|
|
||||||
padding_x :=
|
padding_x := packer_settings.pixel_padding_x_int if packer_settings.padding_enabled else 0
|
||||||
g_mem.packer_settings.pixel_padding_x_int if g_mem.packer_settings.padding_enabled else 0
|
padding_y := packer_settings.pixel_padding_y_int if 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
|
|
||||||
|
|
||||||
g_mem.atlas_metadata = generator.pack_atlas_entries(
|
atlas_metadata = generator.pack_atlas_entries(atlas_entries[:], &atlas, padding_x, padding_y)
|
||||||
atlas_entries[:],
|
|
||||||
&atlas,
|
|
||||||
padding_x,
|
|
||||||
padding_y,
|
|
||||||
)
|
|
||||||
|
|
||||||
// OpenGL's Y buffer is flipped
|
// OpenGL's Y buffer is flipped
|
||||||
rl.ImageFlipVertical(&atlas)
|
rl.ImageFlipVertical(&atlas)
|
||||||
|
|
@ -171,28 +143,27 @@ draw_screen_target :: proc() {
|
||||||
log.info("Packed everything!")
|
log.info("Packed everything!")
|
||||||
atlas_render_target.texture = rl.LoadTextureFromImage(atlas)
|
atlas_render_target.texture = rl.LoadTextureFromImage(atlas)
|
||||||
|
|
||||||
g_mem.should_render_atlas = false
|
should_pack_atlas_and_render = false
|
||||||
g_mem.atlas_render_has_preview = true
|
atlas_render_has_preview = true
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_atlas_settings_and_preview :: proc() {
|
draw_settings_and_preview :: proc() {
|
||||||
left_half_rect := rl.Rectangle {
|
left_half_rect := rl.Rectangle {
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
width = cast(f32)g_mem.window_info.width_scaled / 3,
|
width = cast(f32)window_info.width_scaled / 3,
|
||||||
height = cast(f32)g_mem.window_info.height_scaled,
|
height = cast(f32)window_info.height_scaled,
|
||||||
}
|
}
|
||||||
right_half_rect := rl.Rectangle {
|
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,
|
y = 0,
|
||||||
width = cast(f32)(g_mem.window_info.width_scaled / 3) * 2,
|
width = cast(f32)(window_info.width_scaled / 3) * 2,
|
||||||
height = cast(f32)g_mem.window_info.height_scaled,
|
height = cast(f32)window_info.height_scaled,
|
||||||
}
|
}
|
||||||
rl.DrawRectangleRec(left_half_rect, rl.WHITE)
|
rl.DrawRectangleRec(left_half_rect, rl.WHITE)
|
||||||
rl.DrawRectangleRec(right_half_rect, rl.MAROON)
|
rl.DrawRectangleRec(right_half_rect, rl.MAROON)
|
||||||
|
|
||||||
@(static)
|
@(static) spinner_edit_mode: bool
|
||||||
spinner_edit_mode: bool
|
|
||||||
|
|
||||||
small_offset := 10 * scaling
|
small_offset := 10 * scaling
|
||||||
big_offset := 30 * scaling
|
big_offset := 30 * scaling
|
||||||
|
|
@ -201,10 +172,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
rl.GuiPanel(left_half_rect, "Atlas Settings")
|
rl.GuiPanel(left_half_rect, "Atlas Settings")
|
||||||
elements_height += small_offset / 2
|
elements_height += small_offset / 2
|
||||||
|
|
||||||
@(static)
|
@(static) settings_dropdown_box_active_idx: i32
|
||||||
SettingsDropBoxEditMode: bool
|
|
||||||
@(static)
|
|
||||||
SettingsDropdownBoxActive: i32
|
|
||||||
|
|
||||||
elements_height += small_offset + 5 * scaling
|
elements_height += small_offset + 5 * scaling
|
||||||
|
|
||||||
|
|
@ -214,10 +182,8 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
)
|
)
|
||||||
elements_height += small_offset / 2
|
elements_height += small_offset / 2
|
||||||
|
|
||||||
@(static)
|
@(static) dropdown_resolution_edit_mode: bool
|
||||||
dropdown_resolution_edit_mode: bool
|
@(static) dropdown_resolution_mode: i32
|
||||||
@(static)
|
|
||||||
dropdown_resolution_mode: i32
|
|
||||||
|
|
||||||
dropdown_rect := rl.Rectangle {
|
dropdown_rect := rl.Rectangle {
|
||||||
x = small_offset,
|
x = small_offset,
|
||||||
|
|
@ -230,21 +196,21 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
if dropdown_resolution_edit_mode {rl.GuiLock()}
|
if dropdown_resolution_edit_mode {rl.GuiLock()}
|
||||||
|
|
||||||
if rl.GuiDropdownBox(
|
if rl.GuiDropdownBox(
|
||||||
dropdown_rect,
|
dropdown_rect,
|
||||||
"256x;512x;1024x;2048x;4096x",
|
"256x;512x;1024x;2048x;4096x",
|
||||||
&dropdown_resolution_mode,
|
&dropdown_resolution_mode,
|
||||||
dropdown_resolution_edit_mode,
|
dropdown_resolution_edit_mode,
|
||||||
) {
|
) {
|
||||||
dropdown_resolution_edit_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()
|
rl.GuiUnlock()
|
||||||
}
|
}
|
||||||
elements_height += small_offset * 2
|
elements_height += small_offset * 2
|
||||||
|
|
||||||
|
|
||||||
// General Options
|
// General Options
|
||||||
if SettingsDropdownBoxActive == 0 {
|
if settings_dropdown_box_active_idx == 0 {
|
||||||
padding_settings_y := elements_height
|
padding_settings_y := elements_height
|
||||||
{
|
{
|
||||||
defer {
|
defer {
|
||||||
|
|
@ -267,7 +233,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
rl.GuiCheckBox(
|
rl.GuiCheckBox(
|
||||||
enable_padding_rect,
|
enable_padding_rect,
|
||||||
" Enable padding",
|
" Enable padding",
|
||||||
&g_mem.packer_settings.padding_enabled,
|
&packer_settings.padding_enabled,
|
||||||
)
|
)
|
||||||
elements_height += small_offset * 2
|
elements_height += small_offset * 2
|
||||||
|
|
||||||
|
|
@ -282,7 +248,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
padding_x_spinner := rl.GuiSpinner(
|
padding_x_spinner := rl.GuiSpinner(
|
||||||
padding_x_spinner_rect,
|
padding_x_spinner_rect,
|
||||||
"",
|
"",
|
||||||
&g_mem.packer_settings.pixel_padding_x_int,
|
&packer_settings.pixel_padding_x_int,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
spinner_edit_mode,
|
spinner_edit_mode,
|
||||||
|
|
@ -291,7 +257,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
spinner_edit_mode = !spinner_edit_mode
|
spinner_edit_mode = !spinner_edit_mode
|
||||||
}
|
}
|
||||||
rl.GuiLabel(
|
rl.GuiLabel(
|
||||||
{
|
{
|
||||||
x = (small_offset * 2) + big_offset * 2,
|
x = (small_offset * 2) + big_offset * 2,
|
||||||
y = elements_height,
|
y = elements_height,
|
||||||
width = big_offset,
|
width = big_offset,
|
||||||
|
|
@ -313,7 +279,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
padding_y_spinner := rl.GuiSpinner(
|
padding_y_spinner := rl.GuiSpinner(
|
||||||
padding_y_spinner_rect,
|
padding_y_spinner_rect,
|
||||||
"",
|
"",
|
||||||
&g_mem.packer_settings.pixel_padding_y_int,
|
&packer_settings.pixel_padding_y_int,
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
spinner_edit_mode,
|
spinner_edit_mode,
|
||||||
|
|
@ -322,7 +288,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
spinner_edit_mode = !spinner_edit_mode
|
spinner_edit_mode = !spinner_edit_mode
|
||||||
}
|
}
|
||||||
rl.GuiLabel(
|
rl.GuiLabel(
|
||||||
{
|
{
|
||||||
x = (small_offset * 2) + big_offset * 2,
|
x = (small_offset * 2) + big_offset * 2,
|
||||||
y = elements_height,
|
y = elements_height,
|
||||||
width = big_offset,
|
width = big_offset,
|
||||||
|
|
@ -336,9 +302,6 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
}
|
}
|
||||||
elements_height += small_offset
|
elements_height += small_offset
|
||||||
|
|
||||||
// rl.GuiLine({y = elements_height, width = left_half_rect.width}, "Actions")
|
|
||||||
// elements_height += small_offset
|
|
||||||
|
|
||||||
{
|
{
|
||||||
actions_label_y := elements_height
|
actions_label_y := elements_height
|
||||||
|
|
||||||
|
|
@ -360,7 +323,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
height = small_offset,
|
height = small_offset,
|
||||||
}
|
}
|
||||||
if rl.GuiButton(pick_sources_rect, "Pick Source(s)") {
|
if rl.GuiButton(pick_sources_rect, "Pick Source(s)") {
|
||||||
pick_sources()
|
open_file_dialog(.SourceFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
pick_output_rect := rl.Rectangle {
|
pick_output_rect := rl.Rectangle {
|
||||||
|
|
@ -370,7 +333,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
height = small_offset,
|
height = small_offset,
|
||||||
}
|
}
|
||||||
if rl.GuiButton(pick_output_rect, "Pick Output") {
|
if rl.GuiButton(pick_output_rect, "Pick Output") {
|
||||||
pick_output()
|
open_file_dialog(.OutputFolder)
|
||||||
}
|
}
|
||||||
elements_height += small_offset * 2
|
elements_height += small_offset * 2
|
||||||
|
|
||||||
|
|
@ -381,7 +344,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
height = small_offset,
|
height = small_offset,
|
||||||
}
|
}
|
||||||
if rl.GuiButton(pack_atlas_rect, "Pack Atlas") {
|
if rl.GuiButton(pack_atlas_rect, "Pack Atlas") {
|
||||||
pack_atlas()
|
should_pack_atlas_and_render = true
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_atlas_rect := rl.Rectangle {
|
clear_atlas_rect := rl.Rectangle {
|
||||||
|
|
@ -402,7 +365,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
height = small_offset,
|
height = small_offset,
|
||||||
}
|
}
|
||||||
if rl.GuiButton(save_rect, "Save") {
|
if rl.GuiButton(save_rect, "Save") {
|
||||||
save()
|
save_atlas_to_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
save_to_rect := rl.Rectangle {
|
save_to_rect := rl.Rectangle {
|
||||||
|
|
@ -412,7 +375,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
height = small_offset,
|
height = small_offset,
|
||||||
}
|
}
|
||||||
if rl.GuiButton(save_to_rect, "Save To...") {
|
if rl.GuiButton(save_to_rect, "Save To...") {
|
||||||
save_to()
|
save_to_atlas_to_file()
|
||||||
}
|
}
|
||||||
elements_height += small_offset * 2
|
elements_height += small_offset * 2
|
||||||
}
|
}
|
||||||
|
|
@ -420,10 +383,9 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packing Options
|
// Packing Options
|
||||||
if SettingsDropdownBoxActive == 1 {
|
if settings_dropdown_box_active_idx == 1 {
|
||||||
|
|
||||||
@(static)
|
@(static) active_tab: i32
|
||||||
active_tab: i32
|
|
||||||
tabs: []cstring = {"One", "Two", "Three"}
|
tabs: []cstring = {"One", "Two", "Three"}
|
||||||
rl.GuiTabBar(
|
rl.GuiTabBar(
|
||||||
{x = small_offset, y = elements_height, width = 100, height = small_offset},
|
{x = small_offset, y = elements_height, width = 100, height = small_offset},
|
||||||
|
|
@ -434,9 +396,8 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Options
|
// Save Options
|
||||||
if SettingsDropdownBoxActive == 2 {
|
// if settings_dropdown_box_active_idx == 2 {
|
||||||
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
elements_height = 0
|
elements_height = 0
|
||||||
rl.GuiPanel(right_half_rect, "Atlas Preview")
|
rl.GuiPanel(right_half_rect, "Atlas Preview")
|
||||||
|
|
@ -450,11 +411,11 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
width = short_edge,
|
width = short_edge,
|
||||||
height = short_edge,
|
height = short_edge,
|
||||||
}
|
}
|
||||||
if !g_mem.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 := g_mem.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},
|
||||||
|
|
@ -463,9 +424,7 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
0,
|
0,
|
||||||
rl.WHITE,
|
rl.WHITE,
|
||||||
)
|
)
|
||||||
// preview_rect.x +=
|
atlas_texture := atlas_render_texture_target.texture
|
||||||
// 10;preview_rect.y += 10;preview_rect.height -= 20;preview_rect.width -= 20
|
|
||||||
atlas_texture := g_mem.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},
|
||||||
|
|
@ -477,96 +436,80 @@ draw_atlas_settings_and_preview :: proc() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open_file_dialog :: proc() {
|
open_file_dialog :: proc(dialog_type: FileDialogType) {
|
||||||
switch g_mem.source_location_type {
|
switch dialog_type {
|
||||||
case .SourceFiles:
|
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
|
// https://github.com/native-toolkit/libtinyfiledialogs/blob/master/tinyfiledialogs.c#L2706
|
||||||
file_paths_conc := cstring(
|
file_paths_conc := cstring(
|
||||||
diag.open_file_dialog(
|
diag.open_file_dialog("Select source files", nil, 0, nil, "", 1),
|
||||||
"Select source files",
|
|
||||||
cstring(&g_mem.file_dialog_text_buffer[0]),
|
|
||||||
0,
|
|
||||||
nil,
|
|
||||||
"",
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
if len(file_paths_conc) > 0 {
|
if len(file_paths_conc) > 0 {
|
||||||
// todo(stefan): Currently we're not doing any checks if the filepaths are valid at all,
|
// todo(stefan): We're assuming the filepaths returned libtinydialog are valid...
|
||||||
// this should be fine because it's returned by the OS' file picker but who knows...
|
source_files := strings.clone_from_cstring(file_paths_conc, context.allocator)
|
||||||
source_files_to_pack := strings.clone_from_cstring(file_paths_conc, context.allocator)
|
source_files_to_pack = strings.split(source_files, "|")
|
||||||
g_mem.source_files_to_pack = strings.split(source_files_to_pack, "|")
|
|
||||||
|
|
||||||
log.info(g_mem.source_files_to_pack)
|
log.info(source_files_to_pack)
|
||||||
} else {
|
} else {
|
||||||
log.error("No files were selected!")
|
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:
|
case .OutputFolder:
|
||||||
file := cstring(
|
file := cstring(diag.select_folder_dialog("Select source folder", nil))
|
||||||
diag.select_folder_dialog(
|
|
||||||
"Select source folder",
|
|
||||||
cstring(&g_mem.file_dialog_text_buffer[0]),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if len(file) > 0 {
|
if len(file) > 0 {
|
||||||
g_mem.output_folder_path = strings.clone_from_cstring(file)
|
output_folder_path = strings.clone_from_cstring(file)
|
||||||
log.info(g_mem.output_folder_path)
|
log.info(output_folder_path)
|
||||||
} else {
|
} else {
|
||||||
log.error("Got an empty path from the file dialog!")
|
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() {
|
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)
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,28 +182,27 @@ pack_atlas_entries :: proc(
|
||||||
atlas: ^rl.Image,
|
atlas: ^rl.Image,
|
||||||
offset_x: i32,
|
offset_x: i32,
|
||||||
offset_y: i32,
|
offset_y: i32,
|
||||||
allocator := context.allocator,
|
|
||||||
) -> [dynamic]SpriteAtlasMetadata {
|
) -> [dynamic]SpriteAtlasMetadata {
|
||||||
assert(atlas.width != 0, "Atlas width shouldn't be 0!")
|
assert(atlas.width != 0, "Atlas width shouldn't be 0!")
|
||||||
assert(atlas.height != 0, "Atlas height 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 &entry in entries {
|
||||||
for cell in entry.cells {
|
for cell in entry.cells {
|
||||||
append(&all_cell_images, cell.img)
|
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)
|
num_entries := len(all_cell_images)
|
||||||
nodes := make([]stbrp.Node, num_entries, allocator)
|
nodes := make([]stbrp.Node, num_entries)
|
||||||
rects := make([]stbrp.Rect, num_entries, allocator)
|
rects := make([]stbrp.Rect, num_entries)
|
||||||
|
|
||||||
EntryAndCell :: struct {
|
EntryAndCell :: struct {
|
||||||
entry: ^AtlasEntry,
|
entry: ^AtlasEntry,
|
||||||
cell_of_entry: ^CellData,
|
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
|
// Set the custom IDs
|
||||||
cellIdx: int
|
cellIdx: int
|
||||||
|
|
@ -241,15 +240,15 @@ pack_atlas_entries :: proc(
|
||||||
src_rect := rl.Rectangle {
|
src_rect := rl.Rectangle {
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
width = auto_cast cell.img.width,
|
width = f32(cell.img.width),
|
||||||
height = auto_cast cell.img.height,
|
height = f32(cell.img.height),
|
||||||
}
|
}
|
||||||
|
|
||||||
dst_rect := rl.Rectangle {
|
dst_rect := rl.Rectangle {
|
||||||
auto_cast rect.x + auto_cast offset_x,
|
f32(i32(rect.x) + offset_x),
|
||||||
auto_cast rect.y + auto_cast offset_y,
|
f32(i32(rect.y) + offset_y),
|
||||||
auto_cast cell.img.width,
|
f32(cell.img.width),
|
||||||
auto_cast cell.img.height,
|
f32(cell.img.height),
|
||||||
}
|
}
|
||||||
|
|
||||||
// note(stefan): drawing the sprite in the atlas in the packed coordinates
|
// 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)
|
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 {
|
for rect, rectIdx in rects {
|
||||||
entry_and_cell := rect_idx_to_entry_and_cell[auto_cast rectIdx]
|
entry_and_cell := rect_idx_to_entry_and_cell[auto_cast rectIdx]
|
||||||
entry := entry_and_cell.entry
|
entry := entry_and_cell.entry
|
||||||
|
|
@ -267,10 +266,9 @@ pack_atlas_entries :: proc(
|
||||||
cell_name: string
|
cell_name: string
|
||||||
if entry.layer_cell_count[cell.layer_index] > 1 {
|
if entry.layer_cell_count[cell.layer_index] > 1 {
|
||||||
cell_name = fmt.aprintf(
|
cell_name = fmt.aprintf(
|
||||||
"{0}_%d",
|
"{0}_{1}",
|
||||||
entry.layer_names[cell.layer_index],
|
entry.layer_names[cell.layer_index],
|
||||||
cell.frame_index,
|
cell.frame_index,
|
||||||
allocator,
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
cell_name = entry.layer_names[cell.layer_index]
|
cell_name = entry.layer_names[cell.layer_index]
|
||||||
|
|
@ -278,8 +276,8 @@ pack_atlas_entries :: proc(
|
||||||
cell_metadata := SpriteAtlasMetadata {
|
cell_metadata := SpriteAtlasMetadata {
|
||||||
name = cell_name,
|
name = cell_name,
|
||||||
location = {
|
location = {
|
||||||
auto_cast rect.x + auto_cast offset_x,
|
i32(rect.x) + offset_x,
|
||||||
auto_cast rect.y + auto_cast offset_y,
|
i32(rect.y) + offset_y,
|
||||||
},
|
},
|
||||||
size = {auto_cast cell.img.width, auto_cast cell.img.height},
|
size = {auto_cast cell.img.width, auto_cast cell.img.height},
|
||||||
}
|
}
|
||||||
|
|
@ -308,7 +306,7 @@ odin_source_generator_metadata := SourceCodeGeneratorMetadata {
|
||||||
},
|
},
|
||||||
array_data = {
|
array_data = {
|
||||||
name = "ATLAS_SPRITES",
|
name = "ATLAS_SPRITES",
|
||||||
type = "[]AtlasRect",
|
type = "[AtlasSprite]AtlasRect",
|
||||||
begin_line = "%v := %v {{\n",
|
begin_line = "%v := %v {{\n",
|
||||||
entry_line = "\t.%v = {{ x = %v, y = %v, w = %v, h = %v }},\n",
|
entry_line = "\t.%v = {{ x = %v, y = %v, w = %v, h = %v }},\n",
|
||||||
end_line = "}\n\n",
|
end_line = "}\n\n",
|
||||||
|
|
@ -369,7 +367,7 @@ generate_odin_enums_and_atlas_offsets_file_sb :: proc(
|
||||||
|
|
||||||
// start offsets array
|
// start offsets array
|
||||||
// todo(stefan): the name of the array can be based on the output name?
|
// 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
|
entry: string
|
||||||
for cell in metadata {
|
for cell in metadata {
|
||||||
|
|
|
||||||
4
vendors/dialog/build.sh
vendored
4
vendors/dialog/build.sh
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
gcc ./libtinyfiledialogs/tinyfiledialogs.c -c -o libtinyfiledialogs.o
|
gcc ./libtinyfiledialogs/tinyfiledialogs.c -c -o libtinyfiledialogs.o
|
||||||
|
|
||||||
ar rcs libtinyfiledialogs.a libtinyfiledialogs.o
|
ar rcs libtinyfiledialogs.a libtinyfiledialogs.o
|
||||||
|
|
||||||
rm libtinyfiledialogs.o
|
rm libtinyfiledialogs.o
|
||||||
Loading…
Add table
Add a link
Reference in a new issue