Split code, extend GUI mode, improve error handling
This commit is contained in:
parent
df0b580ce8
commit
a1f90962f6
|
@ -0,0 +1,60 @@
|
|||
package main
|
||||
|
||||
import rl "vendor:raylib"
|
||||
import "core:strings"
|
||||
|
||||
CART_WIDTH :: 160
|
||||
CART_HEIGHT :: 205
|
||||
|
||||
Cart :: struct {
|
||||
image : rl.Image,
|
||||
texture : rl.Texture,
|
||||
loaded : bool,
|
||||
}
|
||||
|
||||
CartLoadError :: enum {
|
||||
None,
|
||||
Wrong_Size,
|
||||
Allocation_Error,
|
||||
Wrong_Type
|
||||
}
|
||||
|
||||
loadCart :: proc(target: ^Cart, filename: cstring) -> CartLoadError {
|
||||
if !strings.has_suffix(string(filename), ".png") {
|
||||
return .Wrong_Type
|
||||
}
|
||||
unloadCart(target)
|
||||
target.image = rl.LoadImage(filename)
|
||||
if target.image.width != CART_WIDTH || target.image.height != CART_HEIGHT {
|
||||
return CartLoadError.Wrong_Size
|
||||
}
|
||||
target.texture = rl.LoadTextureFromImage(target.image)
|
||||
target.loaded = true
|
||||
return CartLoadError.None
|
||||
}
|
||||
|
||||
unloadCart :: proc(target: ^Cart) {
|
||||
if target.loaded {
|
||||
rl.UnloadTexture(target.texture)
|
||||
rl.MemFree(target.image.data)
|
||||
}
|
||||
target.loaded = false
|
||||
}
|
||||
|
||||
convertCart :: proc(cart: rl.Image, target: rl.Image) -> rl.Image {
|
||||
newCartImage := rl.ImageCopy(target)
|
||||
for x : i32 = 0; x < newCartImage.width; x += 1 {
|
||||
for y : i32 = 0; y < newCartImage.height; y += 1{
|
||||
targetCol := rl.GetImageColor(target, x, y)
|
||||
sourceCol := rl.GetImageColor(cart, x, y)
|
||||
newCol := rl.Color{
|
||||
targetCol.r & 0b11111100 | sourceCol.r & 0b00000011,
|
||||
targetCol.g & 0b11111100 | sourceCol.g & 0b00000011,
|
||||
targetCol.b & 0b11111100 | sourceCol.b & 0b00000011,
|
||||
targetCol.a & 0b11111100 | sourceCol.a & 0b00000011,
|
||||
}
|
||||
rl.ImageDrawPixel(&newCartImage, x, y, newCol)
|
||||
}
|
||||
}
|
||||
return newCartImage
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package main
|
||||
|
||||
import rl "vendor:raylib"
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
import "core:os"
|
||||
|
||||
|
||||
CmdMode :: proc(args: []string) {
|
||||
if len(args) < 2 || len(args) > 3 {
|
||||
fmt.eprintln(
|
||||
" PicoRepico cmdline usage:",
|
||||
"repico <input.p8.png> <shell.png> <output.p8.png>",
|
||||
"Use only 160x205 png images with PICO-8 palette",
|
||||
sep = "\n",
|
||||
)
|
||||
return
|
||||
}
|
||||
outToStd := false
|
||||
if len(args) == 2 {
|
||||
outToStd = true
|
||||
}
|
||||
|
||||
argnames := []string {
|
||||
"Input file",
|
||||
"Shell file",
|
||||
}
|
||||
images := [2]rl.Image{}
|
||||
for i := 0; i < 2; i+=1 {
|
||||
if !strings.has_suffix(args[i], ".png") {
|
||||
fmt.eprintf("ERROR: %v is not a .png file\n", argnames[i])
|
||||
os.exit(auto_cast os.EINVAL)
|
||||
}
|
||||
|
||||
images[i] = rl.LoadImage(strings.unsafe_string_to_cstring(args[i]))
|
||||
if !rl.IsImageReady(images[i]) {
|
||||
fmt.eprintf("ERROR: can't load %v\n", argnames[i])
|
||||
os.exit(auto_cast os.EIO)
|
||||
}
|
||||
|
||||
if images[i].width != CART_WIDTH || images[i].height != CART_HEIGHT {
|
||||
fmt.eprintf("ERROR: %v has wrong dimensions. 160x205 is expected\n", argnames[i])
|
||||
rl.UnloadImage(images[i])
|
||||
os.exit(auto_cast os.EINVAL)
|
||||
}
|
||||
}
|
||||
defer {
|
||||
for img in images {
|
||||
rl.UnloadImage(img)
|
||||
}
|
||||
}
|
||||
|
||||
newCart := convertCart(images[0], images[1])
|
||||
defer rl.UnloadImage(newCart)
|
||||
|
||||
if !outToStd {
|
||||
rl.ExportImage(newCart, strings.unsafe_string_to_cstring(args[2]))
|
||||
} else {
|
||||
filesize : i32 = 0
|
||||
ptr := rl.ExportImageToMemory(newCart, ".png", &filesize)
|
||||
defer rl.MemFree(ptr)
|
||||
os.write_ptr(os.stdout, ptr, auto_cast filesize)
|
||||
}
|
||||
fmt.eprintln("done!")
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
|
||||
import rl "vendor:raylib"
|
||||
import "core:fmt"
|
||||
import "core:strings"
|
||||
import "core:slice"
|
||||
import "core:os"
|
||||
|
||||
|
||||
W :: 400
|
||||
H :: 300
|
||||
|
||||
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
|
||||
|
||||
|
||||
State :: enum {
|
||||
CartsInput,
|
||||
Export,
|
||||
GotError,
|
||||
Exported
|
||||
}
|
||||
|
||||
GraphicsMode :: proc() {
|
||||
cart := Cart{}
|
||||
target := Cart{}
|
||||
|
||||
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({rl.ConfigFlag.WINDOW_RESIZABLE})
|
||||
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
|
||||
|
||||
#partial 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buttonCartRect := rl.Rectangle{
|
||||
x = hw - CART_WIDTH - 20,
|
||||
y = 8,
|
||||
width = CART_WIDTH,
|
||||
height = CART_HEIGHT,
|
||||
}
|
||||
buttonTargetRect := rl.Rectangle{
|
||||
x = hw + 20,
|
||||
y = 8,
|
||||
width = CART_WIDTH,
|
||||
height = 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}, "")
|
||||
rl.GuiButton(buttonCartRect, "Place here cart")
|
||||
rl.GuiButton(buttonTargetRect, "Place here target")
|
||||
|
||||
if cart.loaded {
|
||||
rl.DrawTexture(cart.texture, auto_cast buttonCartRect.x, auto_cast buttonCartRect.y, rl.WHITE)
|
||||
}
|
||||
if target.loaded {
|
||||
rl.DrawTexture(target.texture, auto_cast buttonTargetRect.x, auto_cast buttonTargetRect.y, rl.WHITE)
|
||||
}
|
||||
if !(cart.loaded && target.loaded) { rl.GuiDisable() }
|
||||
if rl.GuiButton(convertButtonRect, "CONVERT!") {
|
||||
state = .Export
|
||||
}
|
||||
rl.GuiEnable()
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
unloadCart(&cart)
|
||||
unloadCart(&target)
|
||||
}
|
||||
|
196
main.odin
196
main.odin
|
@ -1,30 +1,11 @@
|
|||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import rl "vendor:raylib"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
|
||||
|
||||
W :: 400
|
||||
H :: 300
|
||||
CW :: 160
|
||||
CH :: 205
|
||||
|
||||
width : int = W
|
||||
height : int = H
|
||||
zoom : int = 1
|
||||
|
||||
Cart :: struct {
|
||||
image : rl.Image,
|
||||
texture : rl.Texture,
|
||||
loaded : bool,
|
||||
}
|
||||
|
||||
WrongSizeErrorTimer : i32 = 0
|
||||
IsConverted : bool = false
|
||||
|
||||
main :: proc() {
|
||||
rl.SetTraceLogLevel(.FATAL)
|
||||
when ODIN_DEBUG {
|
||||
|
@ -53,180 +34,5 @@ main :: proc() {
|
|||
GraphicsMode()
|
||||
return
|
||||
}
|
||||
if len(args) != 3 {
|
||||
fmt.eprintln(
|
||||
" PicoRepico cmdline usage:",
|
||||
"repico <input.p8.png> <shell.png> <output.p8.png>",
|
||||
"Use only 160x205 png images with PICO-8 palette",
|
||||
sep = "\n",
|
||||
)
|
||||
return
|
||||
}
|
||||
CmdMode(args)
|
||||
}
|
||||
|
||||
CartLoadError :: enum {
|
||||
None,
|
||||
Wrong_Size,
|
||||
Allocation_Error,
|
||||
}
|
||||
|
||||
loadCart :: proc(target: ^Cart, filename: cstring) -> CartLoadError {
|
||||
unloadCart(target)
|
||||
target.image = rl.LoadImage(filename)
|
||||
if target.image.width != CW || target.image.height != CH {
|
||||
return CartLoadError.Wrong_Size
|
||||
}
|
||||
target.texture = rl.LoadTextureFromImage(target.image)
|
||||
target.loaded = true
|
||||
return CartLoadError.None
|
||||
}
|
||||
|
||||
unloadCart :: proc(target: ^Cart) {
|
||||
if target.loaded {
|
||||
rl.UnloadTexture(target.texture)
|
||||
rl.MemFree(target.image.data)
|
||||
}
|
||||
target.loaded = false
|
||||
}
|
||||
|
||||
convertCart :: proc(cart: rl.Image, target: rl.Image) -> rl.Image {
|
||||
newCartImage := rl.ImageCopy(target)
|
||||
for x : i32 = 0; x < newCartImage.width; x += 1 {
|
||||
for y : i32 = 0; y < newCartImage.height; y += 1{
|
||||
targetCol := rl.GetImageColor(target, x, y)
|
||||
sourceCol := rl.GetImageColor(cart, x, y)
|
||||
newCol := rl.Color{
|
||||
targetCol.r & 0b11111100 | sourceCol.r & 0b00000011,
|
||||
targetCol.g & 0b11111100 | sourceCol.g & 0b00000011,
|
||||
targetCol.b & 0b11111100 | sourceCol.b & 0b00000011,
|
||||
targetCol.a & 0b11111100 | sourceCol.a & 0b00000011,
|
||||
}
|
||||
rl.ImageDrawPixel(&newCartImage, x, y, newCol)
|
||||
}
|
||||
}
|
||||
return newCartImage
|
||||
}
|
||||
|
||||
|
||||
GraphicsMode :: proc() {
|
||||
cart := Cart{}
|
||||
target := Cart{}
|
||||
|
||||
rl.InitWindow(W, H, "PicoRepico")
|
||||
rl.SetTargetFPS(60)
|
||||
|
||||
hw : f32 = auto_cast width / 2
|
||||
hh : f32 = auto_cast height / 2
|
||||
buttonCartRect := rl.Rectangle{
|
||||
x = hw - CW - 20,
|
||||
y = 8,
|
||||
width = CW,
|
||||
height = CH,
|
||||
}
|
||||
buttonTargetRect := rl.Rectangle{
|
||||
x = hw + 20,
|
||||
y = 8,
|
||||
width = CW,
|
||||
height = CH,
|
||||
}
|
||||
convertButtonRect := rl.Rectangle{
|
||||
x = hw - 40,
|
||||
y = auto_cast height - 38,
|
||||
width = 80,
|
||||
height = 30,
|
||||
}
|
||||
|
||||
for !rl.WindowShouldClose() {
|
||||
if WrongSizeErrorTimer > 0 {
|
||||
WrongSizeErrorTimer -= 1
|
||||
}
|
||||
|
||||
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)
|
||||
if loadCart(&cart, f) == .Wrong_Size {
|
||||
WrongSizeErrorTimer = 180
|
||||
}
|
||||
}
|
||||
if mouse.x > hw {
|
||||
fmt.eprintln("Got target file: ", f)
|
||||
if loadCart(&target, f) == .Wrong_Size {
|
||||
WrongSizeErrorTimer = 180
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rl.BeginDrawing()
|
||||
rl.GuiDummyRec(rl.Rectangle{0, 0, auto_cast width, auto_cast height}, "")
|
||||
|
||||
rl.GuiButton(buttonCartRect, "Place here cart")
|
||||
rl.GuiButton(buttonTargetRect, "Place here target")
|
||||
|
||||
if WrongSizeErrorTimer > 0 {
|
||||
rl.GuiLabel(rl.Rectangle{8, auto_cast height - 38, 100, 30}, "WRONG IMAGE SIZE")
|
||||
}
|
||||
|
||||
if cart.loaded {
|
||||
rl.DrawTexture(cart.texture, auto_cast buttonCartRect.x, auto_cast buttonCartRect.y, rl.WHITE)
|
||||
}
|
||||
if target.loaded {
|
||||
rl.DrawTexture(target.texture, auto_cast buttonTargetRect.x, auto_cast buttonTargetRect.y, rl.WHITE)
|
||||
}
|
||||
|
||||
if rl.GuiButton(convertButtonRect, "CONVERT!") {
|
||||
newCart := convertCart(cart.image, target.image)
|
||||
rl.ExportImage(newCart, "output.p8.png")
|
||||
}
|
||||
rl.EndDrawing()
|
||||
}
|
||||
|
||||
unloadCart(&cart)
|
||||
unloadCart(&target)
|
||||
}
|
||||
|
||||
|
||||
CmdMode :: proc(args: []string) {
|
||||
argnames := []string {
|
||||
"input file",
|
||||
"shell file",
|
||||
}
|
||||
images := [2]rl.Image{}
|
||||
for i := 0; i < 2; i+=1 {
|
||||
if !strings.has_suffix(args[i], ".png") {
|
||||
fmt.eprintf("%v is not a .png file", argnames[i])
|
||||
return
|
||||
}
|
||||
|
||||
images[i] = rl.LoadImage(strings.unsafe_string_to_cstring(args[i]))
|
||||
if !rl.IsImageReady(images[i]) {
|
||||
fmt.eprintf("can't load %v", argnames[i])
|
||||
return
|
||||
}
|
||||
}
|
||||
defer {
|
||||
for img in images {
|
||||
rl.UnloadImage(img)
|
||||
}
|
||||
}
|
||||
|
||||
newCart := convertCart(images[0], images[1])
|
||||
defer rl.UnloadImage(newCart)
|
||||
|
||||
if args[2] != "--" {
|
||||
rl.ExportImage(newCart, strings.unsafe_string_to_cstring(args[2]))
|
||||
} else {
|
||||
filesize : i32 = 0
|
||||
ptr := rl.ExportImageToMemory(newCart, ".png", &filesize)
|
||||
defer rl.MemFree(ptr)
|
||||
os.write_ptr(os.stdout, ptr, auto_cast filesize)
|
||||
}
|
||||
fmt.eprintln("done!")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue