repico/guimode.odin

262 lines
6.7 KiB
Odin

package main
import rl "vendor:raylib"
import "core:fmt"
import "core:strings"
import "core:slice"
import "core:bytes"
import "core:os"
W :: 640
H :: 480
width : int = W
height : int = H
zoom : int = 1
WrongSizeErrorTimer : i32 = 0
IsConverted : bool = false
FILENAME_MAX :: 255
fileNameBuffer : [FILENAME_MAX]byte
fileNameString := cstring(&fileNameBuffer[0])
editMode := false
fileListScrolling : i32 = 0
fileListActive : i32 = -1
fileListFocus : i32 = -1
fileList : rl.FilePathList
State :: enum {
CartsInput,
Export,
GotError,
Exported,
FileSelect
}
GraphicsMode :: proc() {
files = slice.into_dynamic(filesBuf[:])
cart := Cart{}
target := Cart{}
fileListTarget : ^Cart
DefaultName :string : "output.p8.png"
for char, i in DefaultName {
fileNameBuffer[i] = auto_cast char
}
errorMessages := map[CartLoadError]cstring {
.None = "",
.Wrong_Size = "The image has wrong dimensions!\n160x205 PNG file expected",
.Wrong_Type = "The image is not a PNG file!\n160x205 PNG file expected",
.Allocation_Error = "Allocation error!",
}
defer delete(errorMessages)
currentError := CartLoadError.None
rl.SetConfigFlags({.WINDOW_RESIZABLE, .INTERLACED_HINT})
rl.InitWindow(W, H, "PicoRepico")
rl.SetTargetFPS(60)
//fontData := #load("font.ttf")
//font := rl.LoadFontFromMemory(".ttf", raw_data(fontData), auto_cast len(fontData), 8, nil, 0)
//font := rl.LoadFontEx("font.ttf", 32, nil, 0)
//rl.GuiSetFont(font)
//rl.GuiSetStyle(auto_cast rl.GuiControl.DEFAULT, auto_cast rl.GuiControlProperty.BORDER_COLOR_NORMAL, i32(rl.ColorToInt(rl.Color{211, 2, 255, 255})))
hw : f32 = auto_cast width / 2
hh : f32 = auto_cast height / 2
state := State.CartsInput
for !rl.WindowShouldClose() {
if WrongSizeErrorTimer > 0 {
WrongSizeErrorTimer -= 1
}
width = auto_cast rl.GetScreenWidth()
height = auto_cast rl.GetScreenHeight()
hw = auto_cast width / 2
hh = auto_cast height / 2
switch state {
case .CartsInput: {
mouse := rl.GetMousePosition()
if rl.IsFileDropped() {
droppedFiles := rl.LoadDroppedFiles()
defer rl.UnloadDroppedFiles(droppedFiles)
if droppedFiles.count == 1 {
f := droppedFiles.paths[0]
if mouse.x <= hw {
fmt.eprintln("Got cart file: ", f)
currentError = loadCart(&cart, f)
if currentError != .None {
state = .GotError
}
}
if mouse.x > hw {
fmt.eprintln("Got target file: ", f)
currentError = loadCart(&target, f)
if currentError != .None {
state = .GotError
}
}
}
}
zoom = 1
if width >= 640 && height > 450 {
zoom = 2
}
buttonCartRect := rl.Rectangle{
x = hw - CART_WIDTH * f32(zoom) - 5,
y = 8,
width = CART_WIDTH * f32(zoom),
height = CART_HEIGHT * f32(zoom),
}
buttonTargetRect := rl.Rectangle{
x = hw + 5,
y = 8,
width = CART_WIDTH * f32(zoom),
height = CART_HEIGHT * f32(zoom),
}
cartRect := rl.Rectangle{0, 0, CART_WIDTH, CART_HEIGHT}
convertButtonRect := rl.Rectangle{
x = hw - 40,
y = auto_cast height - 38,
width = 80,
height = 30,
}
rl.BeginDrawing()
rl.GuiDummyRec(rl.Rectangle{0, 0, auto_cast width, auto_cast height}, "")
if rl.GuiButton(buttonCartRect, "Drag original\ncart here") {
fileListTarget = &cart
cd(".")
state = .FileSelect
}
if cart.loaded {
rl.DrawTexturePro(cart.texture, cartRect, buttonCartRect, {0, 0}, 0, rl.WHITE)
}
if rl.GuiButton(buttonTargetRect, "Drag target\nshell here") {
fileListTarget = &target
cd(".")
state = .FileSelect
}
if target.loaded {
rl.DrawTexturePro(target.texture, cartRect, buttonTargetRect, {0, 0}, 0, rl.WHITE)
}
if !(cart.loaded && target.loaded) { rl.GuiDisable() }
if rl.GuiButton(convertButtonRect, "CONVERT!") {
state = .Export
}
rl.GuiEnable()
if rl.GuiLabelButton(rl.Rectangle{auto_cast width-60, auto_cast height-20, 60, 20}, "by Nefrace") {
rl.OpenURL("https://nefrace.itch.io")
}
}
case .Export: {
res := rl.GuiTextInputBox(rl.Rectangle{hw - 100, 60, 200, 100}, "Input filename for result", "", "ok;cancel", fileNameString, FILENAME_MAX, nil)
if res == 0 || res == 2 {
state = .CartsInput
slice.fill(fileNameBuffer[:], 0)
}
if res == 1 {
newCart := convertCart(cart.image, target.image)
rl.ExportImage(newCart, fileNameString)
state = .Exported
}
}
case .Exported: {
if rl.GuiMessageBox(rl.Rectangle{hw-110, 80, 220, 120}, "Success!", "Cart was exported successfully", "CLOSE") != -1 {
state = .CartsInput
}
}
case .GotError: {
if rl.GuiMessageBox(rl.Rectangle{hw-150, 30, 300, 200}, "ERROR", errorMessages[currentError], "CLOSE") != -1 {
state = .CartsInput
}
}
case .FileSelect: {
rl.GuiPanel(rl.Rectangle{4, 4, auto_cast width - 8, auto_cast height - 8}, "Select a file")
if rl.GuiButton(rl.Rectangle{auto_cast width - 26, 8, 16, 16}, "#128#") {
state = .CartsInput
}
if rl.GuiButton(rl.Rectangle{8, 30, 50, 22}, "Open") {
if fileListActive == -1 {break}
if rl.DirectoryExists(files[fileListActive]) {
cd(files[fileListActive])
break
}
if rl.GetFileExtension(files[fileListActive]) != ".png" {
fmt.println("not a png")
break
}
currentError = loadCart(fileListTarget, files[fileListActive])
if currentError != .None {
state = .GotError
}
state = .CartsInput
}
if rl.GuiButton(rl.Rectangle{60, 30, 50, 22}, "Up") {
cd("..")
}
rl.GuiSetStyle(auto_cast rl.GuiControl.LISTVIEW, auto_cast rl.GuiControlProperty.TEXT_ALIGNMENT, auto_cast rl.GuiTextAlignment.TEXT_ALIGN_LEFT)
res := rl.GuiListViewEx(rl.Rectangle{8, 54, auto_cast width - 16, auto_cast height - 62}, filesPtr, auto_cast filesCount, &fileListScrolling, &fileListActive, &fileListFocus)
}
}
rl.EndDrawing()
}
unloadCart(&cart)
unloadCart(&target)
}
filesBuf : [1024*8]cstring
files : [dynamic]cstring
filesPtr : [^]cstring
filesCount : i32 = 0
cd :: proc(dir: cstring) -> (result: bool) {
result = rl.ChangeDirectory(dir)
rl.UnloadDirectoryFiles(fileList)
clear(&files)
fileList = rl.LoadDirectoryFiles(".")
for fname in fileList.paths[:fileList.count] {
if rl.DirectoryExists(fname) || rl.GetFileExtension(fname) == ".png" {
append(&files, fname)
}
}
slice.sort_by(files[:], proc(i,j:cstring) -> bool {
a := string(i)
b := string(j)
adir := rl.DirectoryExists(i)
bdir := rl.DirectoryExists(j)
if (adir && bdir) || (!adir && !bdir) {
return strings.compare(a, b) == -1
}
return adir && !bdir
})
filesPtr = raw_data(files)
filesCount = auto_cast len(files)
// slice.sort_by_cmp(fileList.paths[:fileList.count], strings.compare())
fileListScrolling = 0
fileListActive = -1
fileListFocus = -1
return
}