@@ 1,12 1,212 @@
package main
+import "base:runtime"
+import "core:encoding/ini"
import "core:fmt"
import "core:math"
+import path "core:path/filepath"
+import "core:strconv"
+import "core:strings"
import win "core:sys/windows"
import sdl "vendor:sdl2"
+import sdl_img "vendor:sdl2/image"
+
+Vec2 :: [2]int
+
+FrameLayout :: enum {
+ Column,
+ Row,
+}
+
+Anim :: struct {
+ frame_layout: FrameLayout,
+ fps: f64,
+ frames: int,
+ size, grab, off: Vec2,
+}
+
+Character :: struct {
+ spritesheet, name: string,
+ animations: map[string]Anim,
+}
+
+ini_value_or_common :: proc(m: ini.Map, section, key: string) -> (string, bool) {
+ value, ok := m[section][key]
+ if !ok do return m["common"][key]
+ return value, true
+}
+
+Character_delete :: proc(ch: ^Character) -> runtime.Allocator_Error {
+ return delete(ch.animations)
+}
+
+Character_load :: proc(dir: string = ".") -> (ch: Character, ok: bool) {
+ ini_path := path.join({dir, "settings.ini"})
+ defer delete(ini_path)
+
+ ini, ini_err, ok_ini := ini.load_map_from_path(
+ ini_path,
+ context.allocator,
+ {key_lower_case = true},
+ )
+ if !ok_ini {
+ fmt.println("ERROR: Failed to read INI file:", ini_err)
+ return
+ }
+
+ fmt.println(ini)
+
+ ch.name = ini["general"]["name"]
+ ch.spritesheet = ini["general"]["spritesheet"]
+
+ required_animations := []string{"idle", "walk", "fall"}
+ for &anim in required_animations {
+ _, ok = ini[anim]
+ if !ok {
+ fmt.printf("ERROR: Required section {} not found\n", anim)
+ return
+ }
+ }
+
+ animations := []string {
+ "idle",
+ "walk",
+ "walk_left",
+ "walk_right",
+ "grab",
+ "grab_left",
+ "grab_right",
+ "fall",
+ "drag",
+ "drag_left",
+ "drag_right",
+ }
+ for anim in animations {
+ a := Anim{}
+ { // Frame layout
+ frame_layout_raw_value, ok := ini_value_or_common(ini, anim, "frame_layout")
+ if ok {
+ frame_layout_value := strings.to_lower(frame_layout_raw_value)
+ defer delete(frame_layout_value)
+ a.frame_layout = .Row if frame_layout_value == "row" else .Column
+ } else {
+ fmt.println("WARNING: No frame layout specified. Defaulting to column.")
+ a.frame_layout = .Column
+ }
+ }
+
+ { // FPS
+ fps_value, ok := ini_value_or_common(ini, anim, "fps")
+ if !ok {
+ fmt.println("ERROR: FPS not specified.")
+ return
+ }
+ a.fps, ok = strconv.parse_f64(fps_value)
+ if !ok {
+ fmt.println("ERROR: Invalid FPS value specified.")
+ return
+ }
+ }
+
+ { // Frames
+ frames_value, ok := ini_value_or_common(ini, anim, "frames")
+ if !ok {
+ fmt.println("ERROR: Frames not specified.")
+ return
+ }
+ a.frames, ok = strconv.parse_int(frames_value)
+ if !ok {
+ fmt.println("ERROR: Invalid frames value specified.")
+ return
+ }
+ }
+
+ { // Size
+ w_value, ok := ini_value_or_common(ini, anim, "w")
+ if !ok {
+ fmt.println("ERROR: No width specified")
+ return
+ }
+ a.size.x, ok = strconv.parse_int(w_value)
+ if !ok {
+ fmt.println("ERROR: Invalid width specified")
+ return
+ }
+
+ h_value, ok1 := ini_value_or_common(ini, anim, "h")
+ if !ok1 {
+ fmt.println("ERROR: No height specified")
+ return
+ }
+ a.size.y, ok1 = strconv.parse_int(h_value)
+ if !ok1 {
+ fmt.println("ERROR: Invalid height specified")
+ return
+ }
+ }
+
+ { // Offset
+ x_value, ok := ini_value_or_common(ini, anim, "offx")
+ if !ok {
+ fmt.println("ERROR: No X offset specified")
+ return
+ }
+ a.off.x, ok = strconv.parse_int(x_value)
+ if !ok {
+ fmt.println("ERROR: Invalid X offset specified")
+ return
+ }
+
+ y_value, ok1 := ini_value_or_common(ini, anim, "offy")
+ a.off.y, ok1 = strconv.parse_int(y_value)
+ if !ok1 {
+ fmt.println("ERROR: Invalid Y offset specified")
+ return
+ }
+ }
+
+ if strings.has_prefix(anim, "grab") || strings.has_prefix(anim, "drag") {
+ // Grab offset
+ x_value, ok := ini_value_or_common(ini, anim, "grabx")
+ if !ok {
+ fmt.println("ERROR: No X grab offset specified")
+ return
+ }
+ a.grab.x, ok = strconv.parse_int(x_value)
+ if !ok {
+ fmt.println("ERROR: Invalid X grab offset specified")
+ return
+ }
+
+ y_value, ok1 := ini_value_or_common(ini, anim, "graby")
+ if !ok1 {
+ fmt.println("ERROR: No Y grab offset specified")
+ return
+ }
+ a.grab.y, ok1 = strconv.parse_int(y_value)
+ if !ok1 {
+ fmt.println("ERROR: Invalid Y grab offset specified")
+ return
+ }
+ }
+
+ fmt.println(anim)
+ ch.animations[anim] = a
+ }
+
+ ok = true
+ return
+}
main :: proc() {
+ ch, ok := Character_load()
+ if !ok {
+ panic("Invalid character")
+ }
+
+ fmt.println(ch)
+
desktop_width := win.GetSystemMetrics(win.SM_CXSCREEN)
desktop_height := win.GetSystemMetrics(win.SM_CYSCREEN)