package assetviewer import rl "vendor:raylib" import "core:os" import "core:fmt" import "core:strings" import fp "core:path/filepath" Vec2 :: [2]f32 Rect :: rl.Rectangle Img :: rl.Image Tex :: rl.Texture SCREEN_WIDTH : i32 = 1000 SCREEN_HEIGHT : i32 = 800 BW := f32(SCREEN_WIDTH) BH := f32(SCREEN_HEIGHT) AppState :: struct { dt: f32, img_scale: f32, image_paths: [dynamic]string, textures: [dynamic]Tex, selection_single: int, selection_path: cstring, selection_tex: [dynamic]int, } check_dir :: proc(info: os.File_Info, in_err: os.Error, user_data: rawptr) -> (err: os.Error, skip_dir: bool) { state := transmute(^AppState) user_data if !info.is_dir { if fp.ext(info.name) == ".png" { append(&state.image_paths, info.fullpath) } } return nil, false } init_state :: proc() -> ^AppState { state := AppState { img_scale = 1 } arguments := os.args[1:] root_dir := len(arguments) == 0 ? os.get_current_directory() : arguments[0] fp.walk(root_dir, check_dir, &state) for path in state.image_paths { path := strings.clone_to_cstring(path) defer delete(path) img := rl.LoadImage(path) defer rl.UnloadImage(img) tex := rl.LoadTextureFromImage(img) append(&state.textures, tex) } set_sprite_info(&state) return new_clone(state) } set_sprite_info :: proc(s: ^AppState) { path := s.image_paths[s.selection_single] spath,_ := fp.rel(os.get_current_directory(), path) tex := s.textures[s.selection_single] info := fmt.aprintf("Width: %d | Height: %d | Path: %s", tex.width, tex.height, spath) defer delete(info) s.selection_path = strings.clone_to_cstring(info) } player_input :: proc(s: ^AppState) { if rl.IsKeyPressed(.EQUAL) { s.img_scale += 1 } if rl.IsKeyPressed(.MINUS) && s.img_scale > 1 { s.img_scale -= 1 } is_dir_pressed :: proc(keys: []rl.KeyboardKey) -> bool { for k in keys { pressed := rl.IsKeyPressed(k) || rl.IsKeyPressedRepeat(k) if pressed { return true } } return false } left := is_dir_pressed([]rl.KeyboardKey{.A, .H, .LEFT}) right := is_dir_pressed([]rl.KeyboardKey{.D, .L, .RIGHT}) up := is_dir_pressed([]rl.KeyboardKey{.W, .K, .UP}) down := is_dir_pressed([]rl.KeyboardKey{.S, .J, .DOWN}) if left && s.selection_single > 0 { s.selection_single -= 1 set_sprite_info(s) } if right && s.selection_single < len(s.textures) - 1 { s.selection_single += 1 set_sprite_info(s) } } draw :: proc(s: ^AppState) { row :i32 = 0 col :i32 = 0 padding :i32 = 0 scale := s.img_scale tallest_height :f32 = 0 for tex,i in s.textures { tw := f32(tex.width) * scale th := f32(tex.height) * scale if col + i32(tw) > SCREEN_WIDTH { row += i32(tallest_height) col = 0 } if th > tallest_height { tallest_height = th } pos := Vec2{f32(col), f32(row)} rl.DrawTextureEx(tex, pos, 0, scale, rl.WHITE); color := i == s.selection_single ? rl.GREEN : rl.BLACK rl.DrawRectangleLinesEx({pos.x, pos.y, tw, th}, 2, color); col += i32(tw) + padding } // Info box at the bottom tsize :f32 = 18 pos := Vec2{0, f32(SCREEN_HEIGHT) - tsize} info_rect := Rect{pos.x, pos.y, f32(SCREEN_WIDTH), tsize} rl.DrawRectangleRec(info_rect, rl.BLACK); rl.DrawText(s.selection_path, i32(pos.x), i32(pos.y), i32(tsize), rl.WHITE) } main :: proc() { rl.SetTraceLogLevel(.ERROR) rl.InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Asset Browser") monitor := rl.GetCurrentMonitor() SCREEN_WIDTH = rl.GetMonitorWidth(monitor) - 50 SCREEN_HEIGHT = rl.GetMonitorHeight(monitor) - 50 rl.SetWindowSize(rl.GetMonitorWidth(monitor), rl.GetMonitorHeight(monitor)) rl.SetTargetFPS(60) state := init_state() for !rl.WindowShouldClose() { state.dt = rl.GetFrameTime() player_input(state) // update(state) rl.BeginDrawing() rl.ClearBackground(rl.GRAY) draw(state) rl.EndDrawing() } for tex in state.textures { rl.UnloadTexture(tex) } rl.CloseWindow() }