top-down-shooter/assetviewer/assetsviewer.odin

161 lines
4.3 KiB
Odin

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()
}