121 lines
2.6 KiB
Go
121 lines
2.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/draw"
|
|
"image/png"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
type Tile struct {
|
|
Dirty bool
|
|
Image *image.RGBA
|
|
}
|
|
|
|
var tiles [][]Tile
|
|
|
|
type WrongSizeError struct {
|
|
ExpectedSize int
|
|
ActualSize image.Point
|
|
X int
|
|
Y int
|
|
}
|
|
|
|
func (err *WrongSizeError) Error() string {
|
|
return fmt.Sprintf("expected %dx%d tile, got %dx%d (coords: %d-%d)", err.ExpectedSize, err.ExpectedSize, err.ActualSize.X, err.ActualSize.Y, err.X, err.Y)
|
|
}
|
|
|
|
func Load(path string, canvasSize int, tileSize int) {
|
|
if err := os.Chdir(path); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
tiles = make([][]Tile, canvasSize)
|
|
for i := range tiles {
|
|
tiles[i] = make([]Tile, canvasSize)
|
|
}
|
|
|
|
for y := range tiles {
|
|
for x := range tiles[y] {
|
|
tiles[y][x].Image = image.NewRGBA(image.Rect(0, 0, tileSize, tileSize))
|
|
filename := fmt.Sprintf("%d-%d.png", x, y)
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
file, err = os.Create(filename)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
draw.Draw(tiles[y][x].Image, tiles[y][x].Image.Bounds(), &image.Uniform{C: image.White}, image.Point{}, draw.Src)
|
|
|
|
if err = png.Encode(file, tiles[y][x].Image); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
log.Printf("Created tile (%d-%d)\n", x, y)
|
|
|
|
} else {
|
|
img, _, err := image.Decode(file)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
draw.Draw(tiles[y][x].Image, img.Bounds(), img, img.Bounds().Min, draw.Src)
|
|
}
|
|
defer file.Close()
|
|
|
|
if tiles[y][x].Image.Bounds().Size().X != tileSize && tiles[y][x].Image.Bounds().Size().Y != tileSize {
|
|
panic(WrongSizeError{ExpectedSize: tileSize, ActualSize: tiles[y][x].Image.Bounds().Size(), X: x, Y: y})
|
|
}
|
|
|
|
tiles[y][x].Dirty = false
|
|
}
|
|
}
|
|
}
|
|
|
|
func Save() {
|
|
for y := range tiles {
|
|
for x := range tiles[y] {
|
|
if tiles[y][x].Dirty {
|
|
filename := fmt.Sprintf("%d-%d.png", x, y)
|
|
file, err := os.OpenFile(filename, os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
if err = png.Encode(file, tiles[y][x].Image); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
tiles[y][x].Dirty = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func GetTile(x int, y int) (*Tile, error) {
|
|
if x >= len(tiles) || y >= len(tiles) {
|
|
return nil, errors.New("tile coordinates out of range")
|
|
}
|
|
|
|
return &tiles[y][x], nil
|
|
}
|
|
|
|
func SetPixel(tx int, ty int, x int, y int, c color.Color) error {
|
|
if ty >= len(tiles) || tx >= len(tiles[y]) {
|
|
return errors.New("tile coordinates out of range")
|
|
}
|
|
if x >= tiles[y][x].Image.Bounds().Size().X || y >= tiles[y][x].Image.Bounds().Size().Y {
|
|
return errors.New("pixel coordinates out of range")
|
|
}
|
|
|
|
tiles[y][x].Image.Set(x, y, c)
|
|
tiles[y][x].Dirty = true
|
|
|
|
return nil
|
|
}
|