Skip to content

Commit

Permalink
Add options for Loader (#62)
Browse files Browse the repository at this point in the history
This commit adds tiled.WithFileSystem which allows users to pass a fs.FS
or embed.FS object like this

    //go:embed data
    var data embed.FS
    ...
    m, err := tiled.LoadFile(path, tiled.WithFileSystem(data))

Rename LoadFromFile and LoadFromReader
  • Loading branch information
eliasdaler authored Jan 14, 2022
1 parent 8f6d20a commit abe4da2
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 40 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const mapPath = "maps/map.tmx" // Path to your Tiled Map.

func main() {
// Parse .tmx file.
gameMap, err := tiled.LoadFromFile(mapPath)
gameMap, err := tiled.LoadFile(mapPath)
if err != nil {
fmt.Printf("error parsing map: %s", err.Error()
os.Exit(2)
Expand Down
2 changes: 1 addition & 1 deletion example/tmx2img/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func main() {
img = "map.png"
}

m, err := tiled.LoadFromFile(filename)
m, err := tiled.LoadFile(filename)
if err != nil {
fmt.Println(err)
return
Expand Down
48 changes: 34 additions & 14 deletions tiled.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,38 +30,58 @@ import (
"path/filepath"
)

// LoadFromReader function loads tiled map in TMX format from io.Reader
// LoadReader function loads tiled map in TMX format from io.Reader
// baseDir is used for loading additional tile data, current directory is used if empty
func LoadFromReader(baseDir string, r io.Reader) (*Map, error) {
return (*Loader)(nil).LoadFromReader(baseDir, r)
func LoadReader(baseDir string, r io.Reader, options ...LoaderOption) (*Map, error) {
l := newLoader(options...)
return l.LoadReader(baseDir, r)
}

// LoadFromFile function loads tiled map in TMX format from file
func LoadFromFile(fileName string) (*Map, error) {
return (*Loader)(nil).LoadFromFile(fileName)
// LoadFile function loads tiled map in TMX format from file
func LoadFile(fileName string, options ...LoaderOption) (*Map, error) {
l := newLoader(options...)
return l.LoadFile(fileName)
}

// Loader provides configuration on how TMX maps and resources are loaded.
type Loader struct {
// loader provides configuration on how TMX maps and resources are loaded.
type loader struct {
// A FileSystem that is used for loading TMX files and any external
// resources it may reference.
//
// A nil FileSystem uses the local file system.
FileSystem fs.FS
}

// LoaderOption is used with LoadReader and LoadFile functions to pass additional options
type LoaderOption func(*loader)

func newLoader(options ...LoaderOption) *loader {
l := &loader{}
for _, opt := range options {
opt(l)
}
return l
}

// open opens the given file using the Loader's FileSystem, or uses os.Open
// if l or l.FileSystem is nil.
func (l *Loader) open(name string) (fs.File, error) {
func (l *loader) open(name string) (fs.File, error) {
if l == nil || l.FileSystem == nil {
return os.Open(name)
}
return l.FileSystem.Open(name)
}

// LoadFromReader function loads tiled map in TMX format from io.Reader
// WithFileSystem returns an option to load level from a passed filesystem
func WithFileSystem(fileSystem fs.FS) LoaderOption {
return func(l *loader) {
l.FileSystem = fileSystem
}
}

// LoadReader function loads tiled map in TMX format from io.Reader
// baseDir is used for loading additional tile data, current directory is used if empty
func (l *Loader) LoadFromReader(baseDir string, r io.Reader) (*Map, error) {
func (l *loader) LoadReader(baseDir string, r io.Reader) (*Map, error) {
d := xml.NewDecoder(r)

m := &Map{
Expand All @@ -75,14 +95,14 @@ func (l *Loader) LoadFromReader(baseDir string, r io.Reader) (*Map, error) {
return m, nil
}

// LoadFromFile function loads tiled map in TMX format from file
func (l *Loader) LoadFromFile(fileName string) (*Map, error) {
// LoadFile function loads tiled map in TMX format from file
func (l *loader) LoadFile(fileName string) (*Map, error) {
f, err := l.open(fileName)
if err != nil {
return nil, err
}
defer f.Close()

dir := filepath.Dir(fileName)
return l.LoadFromReader(dir, f)
return l.LoadReader(dir, f)
}
48 changes: 26 additions & 22 deletions tiled_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func GetAssetsDirectory() string {
return filepath.Join(filepath.Dir(filename), "assets")
}

func TestLoadFromReader(t *testing.T) {
func TestLoadReader(t *testing.T) {
r := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.1" orientation="orthogonal" renderorder="right-down" width="4" height="4" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="2">
<layer id="1" name="Tile Layer 1" width="4" height="4">
Expand All @@ -53,28 +53,28 @@ func TestLoadFromReader(t *testing.T) {
</data>
</layer>
</map>`)
m, err := LoadFromReader(GetAssetsDirectory(), r)
m, err := LoadReader(GetAssetsDirectory(), r)

assert.NoError(t, err)
assert.NotNil(t, m)
assert.Len(t, m.Layers, 1)
}

func TestLoadFromReaderError(t *testing.T) {
func TestLoadReaderError(t *testing.T) {
r := bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="1.2.1" orientation="orthogonal" renderorder="right-down" width="4" height="4" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="2">
<layer id="1" name="Tile Layer 1" width="4" height="4">
<data encoding="csv">
</layer>
</map>`)
m, err := LoadFromReader(GetAssetsDirectory(), r)
m, err := LoadReader(GetAssetsDirectory(), r)

assert.Error(t, err)
assert.Nil(t, m)
}

func TestLoadFromFile(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "test.tmx"))
func TestLoadFile(t *testing.T) {
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "test.tmx"))

assert.NoError(t, err)
assert.NotNil(t, m)
Expand All @@ -93,15 +93,15 @@ func TestLoadFromFile(t *testing.T) {
assert.Equal(t, true, m.ObjectGroups[0].Objects[0].Visible)
}

func TestLoadFromFileError(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "invalid.tmx"))
func TestLoadFileError(t *testing.T) {
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "invalid.tmx"))

assert.Error(t, err)
assert.Nil(t, m)
}

func TestExternalTilesetImageLoaded(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "test2.tmx"))
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "test2.tmx"))

assert.NoError(t, err)
assert.NotNil(t, m)
Expand All @@ -123,7 +123,7 @@ func TestExternalTilesetImageLoaded(t *testing.T) {
}

func TestImageLayer(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "imagelayer.tmx"))
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "imagelayer.tmx"))

assert.NoError(t, err)
assert.NotNil(t, m)
Expand All @@ -145,7 +145,7 @@ func TestImageLayer(t *testing.T) {
}

func TestGroup(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "groups.tmx"))
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "groups.tmx"))

assert.NoError(t, err)
assert.NotNil(t, m)
Expand Down Expand Up @@ -178,7 +178,7 @@ func TestGroup(t *testing.T) {
}

func TestFont(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "font.tmx"))
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "font.tmx"))

assert.NoError(t, err)
assert.NotNil(t, m)
Expand Down Expand Up @@ -219,12 +219,12 @@ func (t *testFileSystem) Open(filename string) (fs.File, error) {

func TestLoader(t *testing.T) {
fs := &testFileSystem{}
loader := &Loader{
loader := &loader{
FileSystem: fs,
}

mapFile := filepath.Join(GetAssetsDirectory(), "loader.tmx")
m, err := loader.LoadFromFile(mapFile)
m, err := loader.LoadFile(mapFile)

if assert.Error(t, err) {
assert.True(t, os.IsNotExist(err), "expecting no exist error")
Expand All @@ -238,27 +238,24 @@ func TestLoader(t *testing.T) {
var assetsFS embed.FS

func TestEmbeddedLoader(t *testing.T) {
loader := &Loader{
FileSystem: assetsFS,
}
tcs := []struct {
name string
load func() (*Map, error)
}{
{
name: "LoadFromReader",
name: "LoadReader",
load: func() (*Map, error) {
file, err := assetsFS.Open("assets/test2.tmx")
if err != nil {
return nil, err
}
return loader.LoadFromReader("assets", file)
return LoadReader("assets", file, WithFileSystem(assetsFS))
},
},
{
name: "LoadFromFile",
name: "LoadFile",
load: func() (*Map, error) {
return loader.LoadFromFile("assets/test2.tmx")
return LoadFile("assets/test2.tmx", WithFileSystem(assetsFS))
},
},
}
Expand All @@ -279,6 +276,13 @@ func TestEmbeddedLoader(t *testing.T) {
}
}

func TestLoadFileMissingFile(t *testing.T) {
_, err := LoadFile("missing-file.tmx")
if err == nil {
t.Fatal("expected LoadFile to return err, but no error was returned")
}
}

func TestParseHexColor(t *testing.T) {
type test struct {
name string
Expand Down Expand Up @@ -411,7 +415,7 @@ func TestFormatHexColor(t *testing.T) {
}

func TestVersions(t *testing.T) {
m, err := LoadFromFile(filepath.Join(GetAssetsDirectory(), "test2.tmx"))
m, err := LoadFile(filepath.Join(GetAssetsDirectory(), "test2.tmx"))

assert.Nil(t, err)

Expand Down
2 changes: 1 addition & 1 deletion tmx_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var (
// layers are rendered by Tiled
type Map struct {
// Loader for loading additional data
loader *Loader
loader *loader
// Base directory for loading additional data
baseDir string

Expand Down
2 changes: 1 addition & 1 deletion tmx_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func TestLoadTilesetReferencedOnlyByObjectGroup(t *testing.T) {
const mapPath = "assets/test_tileobject.tmx"

m, err := tiled.LoadFromFile(mapPath)
m, err := tiled.LoadFile(mapPath)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit abe4da2

Please sign in to comment.