diff --git a/application/toast.go b/application/toast.go new file mode 100644 index 0000000..799ff73 --- /dev/null +++ b/application/toast.go @@ -0,0 +1,49 @@ +package application + +import ( + "fmt" + "time" + + raylib "github.com/gen2brain/raylib-go/raylib" +) + +var ( + toasts = []Toast{} + toastHeight = float32(0) + toastMaxAge = 5 * time.Second +) + +type Toast struct { + Text string + Age time.Time +} + +func AddToast(text string) { + toast := Toast{Text: text, Age: time.Now()} + toasts = append(toasts, toast) +} + +func UpdateToasts() { + if len(toasts) != 0 { + toastHeight = raylib.Lerp(toastHeight, float32(20*len(toasts))+10, 0.1) + } else { + toastHeight = raylib.Lerp(toastHeight, 0, 0.1) + } + + for i := 0; i < len(toasts); i++ { + if time.Since(toasts[i].Age) > toastMaxAge { + toasts = append(toasts[:i], toasts[i+1:]...) + i-- + } + } +} + +func DrawToasts() { + raylib.BeginScissorMode(0, 0, WindowWidth, int32(toastHeight)) + raylib.DrawRectangle(0, 0, WindowWidth, WindowHeight, raylib.Fade(raylib.Black, 0.5)) + for i := 0; i < len(toasts); i++ { + text := fmt.Sprintf("%s (%s)", toasts[i].Text, time.Since(toasts[i].Age).Round(time.Second)) + raylib.DrawText(text, 10, int32(20*i)+10, 10, raylib.White) + } + raylib.EndScissorMode() +} diff --git a/main.go b/main.go index 1d066ca..7674561 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ func main() { raylib.InitWindow(application.WindowWidth, application.WindowHeight, application.WindowTitle) raylib.InitAudioDevice() - //raylib.SetTargetFPS(application.WindowFPS) + raylib.SetTargetFPS(application.WindowFPS) //raylib.SetExitKey(0) // disable exit key // MAIN LOOP diff --git a/scenes/drawing.go b/scenes/drawing.go index 2c70eef..522c35b 100644 --- a/scenes/drawing.go +++ b/scenes/drawing.go @@ -20,11 +20,15 @@ type stroke struct { func Drawing() { var ( - canvasSize = raylib.NewVector2(500, 430) - canvas = raylib.LoadRenderTexture(int32(canvasSize.X), int32(canvasSize.Y)) + camera = raylib.NewCamera2D(raylib.NewVector2(0, 0), raylib.NewVector2(0, 0), 0, 1) + //cameraMoveOffset = raylib.NewVector2(10, 10) - sidePanelWidth float32 = 300 - sidePanelRelativeX = application.WindowWidth - int32(sidePanelWidth) + canvasSize = raylib.NewVector2(500, 430) + canvas = raylib.LoadRenderTexture(int32(canvasSize.X), int32(canvasSize.Y)) + canvasRefresh = true + + sidePanelWidth = float32(300) + sidePanelRelativeX = application.WindowWidth - int32(sidePanelWidth) drawing = false //drawingMode = ModeDrawing @@ -33,10 +37,13 @@ func Drawing() { strokes = []stroke{currentStroke} undoneStrokes = []stroke{} - colourPickerVal = raylib.Orange - colourPickerHeight float32 = 200 + colourPickerVal = raylib.Orange + colourPickerHeight = float32(200) - brushSize float32 = 10 + brushSize = float32(10) + + fileName = "NewProject" + fileNameEditing = false ) refreshCanvas := func() { @@ -55,8 +62,42 @@ func Drawing() { raylib.EndTextureMode() } - // Create canvas - refreshCanvas() + undoStroke := func() { + fmt.Println("Undo") + + if len(undoneStrokes) > 0 { + strokes = append(strokes, undoneStrokes[len(undoneStrokes)-1]) + undoneStrokes = undoneStrokes[:len(undoneStrokes)-1] + } + + canvasRefresh = true + } + redoStroke := func() { + fmt.Println("Redo") + + // 1 because I dont know why + if len(strokes) > 1 { + undoneStrokes = append(undoneStrokes, strokes[len(strokes)-1]) + strokes = strokes[:len(strokes)-1] + } + + canvasRefresh = true + } + + saveImage := func() { + if fileName == "" { + application.AddToast("Please enter a file name") + } else { + image := raylib.LoadImageFromTexture(canvas.Texture) + + raylib.ImageRotate(image, 180) + raylib.ImageFlipHorizontal(image) + + raylib.ExportImage(*image, application.DirUserData+fileName+".png") + + application.AddToast("Drawing saved at " + application.DirUserData + fileName + ".png") + } + } for !application.ShouldQuit { // DEFAULT @@ -75,10 +116,24 @@ func Drawing() { // INPUT { - if raylib.IsMouseButtonPressed(raylib.MouseLeftButton) { - drawing = false + //if raylib.GetMouseWheelMove() != 0 { + // camera.Zoom += float32(raylib.GetMouseWheelMove()) * 0.05 + //} + //if raylib.IsMouseButtonPressed(raylib.MouseMiddleButton) { + // cameraMoveOffset = raylib.Vector2Subtract(camera.Target, raylib.GetMousePosition()) + //} + //if raylib.IsMouseButtonDown(raylib.MouseMiddleButton) { + // camera.Target = raylib.Vector2Subtract(raylib.GetMousePosition(), raylib.Vector2Scale(cameraMoveOffset, -1)) + //} - if raylib.CheckCollisionPointRec(raylib.GetMousePosition(), raylib.NewRectangle(10, 10, canvasSize.X, canvasSize.Y)) { + if raylib.IsKeyPressed(raylib.KeyF8) { + application.AddToast("This is a toast message!") + } + + if raylib.IsMouseButtonPressed(raylib.MouseLeftButton) { + if raylib.CheckCollisionPointRec(raylib.GetMousePosition(), raylib.NewRectangle(float32(application.WindowWidth-int32(sidePanelWidth)), 0, sidePanelWidth, float32(application.WindowHeight))) { + drawing = false + } else if raylib.CheckCollisionPointRec(raylib.GetMousePosition(), raylib.NewRectangle(10, 10, canvasSize.X, canvasSize.Y)) { drawing = true currentStroke = stroke{ Color: colourPickerVal, @@ -102,23 +157,15 @@ func Drawing() { currentStroke = stroke{} undoneStrokes = []stroke{} - refreshCanvas() + canvasRefresh = true } if raylib.IsKeyDown(raylib.KeyLeftControl) && raylib.IsKeyDown(raylib.KeyLeftShift) && raylib.IsKeyPressed(raylib.KeyZ) { - if len(undoneStrokes) > 1 { - strokes = append(strokes, undoneStrokes[len(undoneStrokes)-1]) - undoneStrokes = undoneStrokes[:len(undoneStrokes)-1] - } - - refreshCanvas() + undoStroke() } else if raylib.IsKeyDown(raylib.KeyLeftControl) && raylib.IsKeyPressed(raylib.KeyZ) { - if len(strokes) > 1 { - undoneStrokes = append(undoneStrokes, strokes[len(strokes)-1]) - strokes = strokes[:len(strokes)-1] - } - - refreshCanvas() + redoStroke() + } else if raylib.IsKeyDown(raylib.KeyLeftControl) && raylib.IsKeyPressed(raylib.KeyS) { + saveImage() } } @@ -129,6 +176,13 @@ func Drawing() { } else { gui.SetState(gui.STATE_NORMAL) } + + if canvasRefresh { + refreshCanvas() + canvasRefresh = false + } + + application.UpdateToasts() } // DRAW @@ -138,18 +192,27 @@ func Drawing() { gui.Grid(raylib.NewRectangle(0, 0, float32(application.WindowWidth), float32(application.WindowHeight)), "", 30, 1, &raylib.Vector2{}) // Canvas stuff - raylib.DrawRectangle(20, 20, int32(canvasSize.X), int32(canvasSize.Y), raylib.Fade(raylib.Black, 0.3)) - raylib.BeginScissorMode(10, 10, int32(canvasSize.X), int32(canvasSize.Y)) + raylib.BeginMode2D(camera) { + raylib.DrawRectangle(20, 20, int32(canvasSize.X), int32(canvasSize.Y), raylib.Fade(raylib.Black, 0.3)) raylib.DrawTexturePro(canvas.Texture, raylib.NewRectangle(0, 0, float32(canvas.Texture.Width), float32(-canvas.Texture.Height)), raylib.NewRectangle(10, 10, canvasSize.X, canvasSize.Y), raylib.Vector2{}, 0, raylib.White) + + if drawing { + raylib.DrawRectangleLines(10, 10, int32(canvasSize.X), int32(canvasSize.Y), raylib.DarkGray) + } else { + raylib.DrawRectangleLines(10, 10, int32(canvasSize.X), int32(canvasSize.Y), raylib.Gray) + } + + raylib.BeginScissorMode(10, 10, int32(canvasSize.X), int32(canvasSize.Y)) for i := 1; i < len(currentStroke.Points); i++ { raylib.DrawLineEx(currentStroke.Points[i-1], currentStroke.Points[i], currentStroke.Size, currentStroke.Color) raylib.DrawCircle(int32(currentStroke.Points[i].X), int32(currentStroke.Points[i].Y), currentStroke.Size/2, currentStroke.Color) } + raylib.EndScissorMode() + raylib.DrawCircleLines(int32(raylib.GetMousePosition().X), int32(raylib.GetMousePosition().Y), brushSize/2, raylib.Black) } - raylib.EndScissorMode() - raylib.DrawRectangleLines(10, 10, int32(canvasSize.X), int32(canvasSize.Y), raylib.Gray) + raylib.EndMode2D() // UI stuff raylib.BeginScissorMode(sidePanelRelativeX, 0, int32(sidePanelWidth), application.WindowHeight) @@ -160,10 +223,26 @@ func Drawing() { application.CurrentScene = application.SceneTitle } if gui.Button(raylib.NewRectangle(float32(sidePanelRelativeX+20+25), 10, 25, 25), gui.IconText(gui.ICON_FOLDER_SAVE, "")) { + saveImage() + } + + // Stupid arrows are inverted + if gui.Button(raylib.NewRectangle(float32(application.WindowWidth-70), 10, 25, 25), gui.IconText(gui.ICON_UNDO, "")) { + redoStroke() + } + if gui.Button(raylib.NewRectangle(float32(application.WindowWidth-35), 10, 25, 25), gui.IconText(gui.ICON_REDO, "")) { + undoStroke() } colourPickerVal = gui.ColorPicker(raylib.NewRectangle(float32(sidePanelRelativeX+10), 45, sidePanelWidth-40, colourPickerHeight), "Color", colourPickerVal) - brushSize = gui.Slider(raylib.NewRectangle(float32(sidePanelRelativeX+80), 65+colourPickerHeight, 200, 20), "Brush Size", "", brushSize, 1, 100) + + gui.Label(raylib.NewRectangle(float32(sidePanelRelativeX+10), 55+colourPickerHeight, 200, 20), "Brush Size") + brushSize = gui.Slider(raylib.NewRectangle(float32(sidePanelRelativeX+78), 55+colourPickerHeight, 215, 20), "", "", brushSize, 1, 100) + + gui.Label(raylib.NewRectangle(float32(sidePanelRelativeX+10), 85+colourPickerHeight, 200, 20), "File Name") + if gui.TextBox(raylib.NewRectangle(float32(sidePanelRelativeX+78), 85+colourPickerHeight, 215, 20), &fileName, 40, fileNameEditing) { + fileNameEditing = !fileNameEditing + } } raylib.EndScissorMode() raylib.DrawRectangleLines(sidePanelRelativeX, 0, int32(sidePanelWidth), application.WindowHeight, raylib.Gray) @@ -178,6 +257,9 @@ func Drawing() { text = fmt.Sprintf("Canvas Size: %dx%d", int32(canvasSize.X), int32(canvasSize.Y)) gui.StatusBar(raylib.NewRectangle(199, float32(application.WindowHeight-20), 200, 20), text) } + + // Draw toasts + application.DrawToasts() } raylib.EndDrawing() } diff --git a/scenes/playerData.go b/scenes/playerData.go index 5a40d6d..a2d6f85 100644 --- a/scenes/playerData.go +++ b/scenes/playerData.go @@ -2,25 +2,37 @@ package scenes import ( "ColouringApp/application" + "os" + raylib "github.com/gen2brain/raylib-go/raylib" ) func PlayerData() { // Load player data here for !application.ShouldQuit { - application.ShouldQuit = raylib.WindowShouldClose() - if application.CurrentScene != application.ScenePlayerData { - break + // DEFAULT + { + application.ShouldQuit = raylib.WindowShouldClose() + if application.CurrentScene != application.ScenePlayerData { + break + } } - raylib.BeginDrawing() - raylib.ClearBackground(raylib.Black) + // check if userData exists + if _, err := os.Stat(application.DirUserData); os.IsNotExist(err) { + err := os.Mkdir(application.DirUserData, 0755) + if err != nil { + panic(err) + } + } - raylib.DrawText("Loading...", 10, application.WindowHeight-30, 20, raylib.White) - - raylib.EndDrawing() - - //time.Sleep(1 * time.Second) + // DRAW + { + raylib.BeginDrawing() + raylib.ClearBackground(raylib.Black) + raylib.DrawText("Loading...", 10, application.WindowHeight-30, 20, raylib.White) + raylib.EndDrawing() + } application.CurrentScene = application.SceneTitle }