From 2bee7edf6a41c0da4eddf6fa4b1f169d579ebd57 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 31 Aug 2024 20:01:46 +0700 Subject: [PATCH] Asset Viewer working well enough --- .gitignore | 1 + assetsviewer.odin | 121 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2780213 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/assetsviewer diff --git a/assetsviewer.odin b/assetsviewer.odin index cc28308..eea9839 100644 --- a/assetsviewer.odin +++ b/assetsviewer.odin @@ -3,8 +3,14 @@ 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) @@ -12,43 +18,142 @@ BH := f32(SCREEN_HEIGHT) AppState :: struct { dt: f32, - test: string, + 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 - fmt.println(state^); + 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 {dt = 5.0, test="Test String"} + 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) + img := rl.LoadImage(path) + tex := rl.LoadTextureFromImage(img) + append(&state.textures, tex) + rl.UnloadImage(img) + } + 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() - fp.walk("./Assets", check_dir, state) - for !rl.WindowShouldClose() { state.dt = rl.GetFrameTime() - // player_input(state) + player_input(state) // update(state) rl.BeginDrawing() - rl.ClearBackground(rl.WHITE) + rl.ClearBackground(rl.GRAY) - // draw2d(state) + draw(state) rl.EndDrawing() } + for tex in state.textures { + rl.UnloadTexture(tex) + } rl.CloseWindow() }