add odin-aseprite dependency & start of a generator

This commit is contained in:
Stefan Stefanov 2024-04-21 09:38:05 +03:00
parent 132b16df8f
commit c8e5cfcdef
9 changed files with 170 additions and 64 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/aseprite"]
path = src/aseprite
url = https://github.com/bersK/odin-aseprite.git

136
.vscode/tasks.json vendored
View file

@ -1,60 +1,80 @@
{
"version": "2.0.0",
"command": "",
"args": [],
"tasks": [
{
"label": "Build Debug",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_debug.bat",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_debug.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_debug.sh",
},
"group": "build"
},
{
"label": "Build Release",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_release.bat",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_release.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_release.sh",
},
"group": "build"
},
{
"label": "Build Hot Reload",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_hot_reload.bat; start game.exe",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_hot_reload.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_hot_reload.sh",
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"group": {
"kind": "build",
"isDefault": true
},
}
]
"version": "2.0.0",
"command": "",
"args": [],
"tasks": [
{
"label": "Build Debug",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_debug.bat",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_debug.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_debug.sh",
},
"group": "build"
},
{
"label": "Build Release",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_release.bat",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_release.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_release.sh",
},
"group": "build"
},
{
"label": "Build Hot Reload",
"type": "shell",
"windows": {
"command": "${workspaceFolder}/scripts/build_hot_reload.bat; start game.exe",
},
"linux": {
"command": "${workspaceFolder}/scripts/build_hot_reload.sh",
},
"osx": {
"command": "${workspaceFolder}/scripts/build_hot_reload.sh",
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true
},
"group": {
"kind": "build",
"isDefault": false
},
},
{
"label": "Build&Run Tile Generator Test",
"type": "shell",
"command": "odin run src/aseprite_odin_generator -out:build/aseprite_odin_generator.exe",
"options": {
"cwd": "${workspaceFolder}"
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": false,
"clear": true
},
"group": {
"kind": "build",
"isDefault": true
},
}
]
}

View file

@ -6,4 +6,6 @@ Yet-Another-Atlas-Packer by Stefan Stefanov
Simple atlas packer using `stb_rect_pack` from the `stb` family of header libraries & `raylib` for rendering/ui.
I'm using a custom marshall/unmarshall odin library for reading .aseprite files found [here](https://github.com/blob1807/odin-aseprite)
Project template provided by Karl Zylinski on github [here](https://github.com/karl-zylinski/odin-raylib-hot-reload-game-template).

1
src/aseprite Submodule

@ -0,0 +1 @@
Subproject commit f21bed838a6d1e6bc1178ea0876596eb14190192

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

View file

@ -0,0 +1,82 @@
package generator
import ase "../aseprite"
import "core:fmt"
import "core:mem"
import "core:os"
import fp "core:path/filepath"
import "core:slice"
import "core:strings"
import "core:testing"
import rl "vendor:raylib"
ATLAS_SIZE :: 512
EXPORT_PATH :: "E:/dev/odin-atlas-packer/src/aseprite_odin_generator/atlas.png"
main :: proc() {
fmt.println("Hello!")
ase_file, ase_ok := os.read_entire_file(
"E:/dev/odin-atlas-packer/src/aseprite_odin_generator/big.aseprite",
)
if !ase_ok {
fmt.panicf("Couldn't load file!")
}
doc: ase.Document
read, um_err := ase.unmarshal_from_slice(ase_file, &doc)
if um_err != nil {
fmt.panicf("Couldn't unmarshall file!")
} else {
fmt.printfln("Read {0} bytes from file", read)
}
fmt.println("Header:\n\t", doc.header)
// fmt.println("Frames:\n\t", doc.frames)
images: [dynamic]rl.Image
atlas: rl.Image = rl.GenImageColor(ATLAS_SIZE, ATLAS_SIZE, rl.BLANK)
for frame in doc.frames {
for chunk in frame.chunks {
cel_chunk, cok := chunk.(ase.Cel_Chunk)
if !cok {
continue
}
cel_img, ci_ok := cel_chunk.cel.(ase.Com_Image_Cel)
if !ci_ok {
continue
}
append(
&images,
rl.Image {
data = rawptr(&cel_img.pixel[0]),
width = auto_cast cel_img.width,
height = auto_cast cel_img.height,
format = .UNCOMPRESSED_R8G8B8A8,
},
)
}
}
curr_x, curr_y: i32
for img, img_i in images {
fmt.printfln("Image_{0}: {1}", img_i, img)
rl.ImageDraw(
&atlas,
img,
{0, 0, auto_cast img.width, auto_cast img.height},
{auto_cast curr_x, auto_cast curr_y, auto_cast img.width, auto_cast img.height},
rl.WHITE,
)
curr_x += img.width
curr_y += img.height
}
// todo: pack the rectangles
// todo: blit them to the atlas
// todo: generate metadata (json, odin enums)
rl.ExportImage(atlas, EXPORT_PATH)
}

View file

@ -293,7 +293,7 @@ draw_atlas_settings_and_preview :: proc() {
},
"Pack",
) {
g_mem.atlas_render = true
g_mem.atlas_render = true
}
elements_height += small_offset * 2
@ -307,7 +307,7 @@ draw_atlas_settings_and_preview :: proc() {
},
"Save",
) {
save_output()
save_output()
}
if rl.GuiButton(
{
@ -334,7 +334,7 @@ draw_atlas_settings_and_preview :: proc() {
height = short_edge,
}
rl.GuiDummyRec(preview_rect, "PREVIEW")
preview_rect.x += 10; preview_rect.y += 10; preview_rect.height-=20;preview_rect.width-=20
preview_rect.x += 10;preview_rect.y += 10;preview_rect.height -= 20;preview_rect.width -= 20
texture := &g_mem.atlas_render_texture_target.texture
rl.DrawTexturePro(
texture^,
@ -394,7 +394,7 @@ open_file_dialog_and_store_output_paths :: proc() {
}
draw_and_handle_source_files_logic :: proc() {
switch g_mem.app_screen {
#partial switch g_mem.app_screen {
case .SourceFilesPicker:
result := rl.GuiTextInputBox(
rl.Rectangle{width = (w / scaling), height = (h / scaling)},
@ -445,8 +445,6 @@ draw_and_handle_source_files_logic :: proc() {
handle_source_file_logic(file_dialg_type)
fmt.println("result: ", result)
}
case .PackSettingsAndPreview:
draw_packer_and_settings()
}
}