Skip to content

Commit

Permalink
support for data chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
Noofbiz committed Oct 1, 2018
1 parent 2ebb127 commit c9ede7f
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 27 deletions.
75 changes: 48 additions & 27 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type Chunk struct {
Height int `xml:"height,attr"`
// Tiles are the tiles in the chunk
Tiles []TileData `xml:"tile"`
// Inner is the inner data
Inner string `xml:",innerxml"`
}

// TileData contains the gid that maps a tile to the sprite
Expand Down Expand Up @@ -78,8 +80,35 @@ func (da *Data) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if len(da.Tiles) > 0 {
return nil
}
if da.Encoding == "csv" {
b := strings.NewReader(strings.TrimSpace(da.Inner))
var err error
if len(da.Chunks) == 0 {
da.Tiles, err = decodeTileData(da.Inner, da.Encoding, da.Compression)
if err != nil {
return err
}
} else {
for i := range da.Chunks {
da.Chunks[i].Tiles, err = decodeTileData(da.Chunks[i].Inner, da.Encoding, da.Compression)
if err != nil {
return err
}
}
}
return nil
}

func decodeGID(u uint32) (uint32, uint32) {
h := u & HorizontalFlipFlag
v := u & VerticalFlipFlag
d := u & DiagonalFlipFlag
ret := u & ^(HorizontalFlipFlag | VerticalFlipFlag | DiagonalFlipFlag)
return ret, h | v | d
}

func decodeTileData(d, encoding, compression string) ([]TileData, error) {
tiles := make([]TileData, 0)
if encoding == "csv" {
b := strings.NewReader(strings.TrimSpace(d))
cr := csv.NewReader(b)
// We allow variable number of fields per record to allow line ending commas and then
// empty strings appearing as a field. Later, we filter empty strings. This trick is
Expand All @@ -88,7 +117,7 @@ func (da *Data) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
cr.FieldsPerRecord = -1
recs, _ := cr.ReadAll()
if len(recs) < 1 {
return errors.New("No csv records found")
return tiles, errors.New("No csv records found")
}
for _, rec := range recs {
for i, id := range rec {
Expand All @@ -98,48 +127,48 @@ func (da *Data) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
}
nextInt, err := strconv.ParseUint(id, 10, 32)
if err != nil {
return err
return tiles, err
}
g, f := decodeGID(uint32(nextInt))
da.Tiles = append(da.Tiles, TileData{
tiles = append(tiles, TileData{
RawGID: uint32(nextInt),
Flipping: f,
GID: g,
})
}
}
return nil
return tiles, nil
}
var breader io.Reader
if da.Encoding == "base64" {
buff, err := base64.StdEncoding.DecodeString(strings.TrimSpace(da.Inner))
if encoding == "base64" {
buff, err := base64.StdEncoding.DecodeString(strings.TrimSpace(d))
if err != nil {
return err
return tiles, err
}
breader = bytes.NewReader(buff)
} else {
return errors.New("Unknown Encoding")
return tiles, errors.New("Unknown Encoding")
}
// Setup decompression if needed
var zreader io.Reader
if da.Compression == "" {
if compression == "" {
zreader = breader
} else if da.Compression == "zlib" {
} else if compression == "zlib" {
z, err := zlib.NewReader(breader)
if err != nil {
return err
return tiles, err
}
defer z.Close()
zreader = z
} else if da.Compression == "gzip" {
} else if compression == "gzip" {
z, err := gzip.NewReader(breader)
if err != nil {
return err
return tiles, err
}
defer z.Close()
zreader = z
} else {
return errors.New("Unknown Compression")
return tiles, errors.New("Unknown Compression")
}
var nextInt uint32
for {
Expand All @@ -148,22 +177,14 @@ func (da *Data) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if err == io.EOF {
break
}
return err
return tiles, err
}
g, f := decodeGID(nextInt)
da.Tiles = append(da.Tiles, TileData{
tiles = append(tiles, TileData{
RawGID: nextInt,
GID: g,
Flipping: f,
})
}
return nil
}

func decodeGID(u uint32) (uint32, uint32) {
h := u & HorizontalFlipFlag
v := u & VerticalFlipFlag
d := u & DiagonalFlipFlag
ret := u & ^(HorizontalFlipFlag | VerticalFlipFlag | DiagonalFlipFlag)
return ret, h | v | d
return tiles, nil
}
36 changes: 36 additions & 0 deletions data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,39 @@ func TestDataFlipped(t *testing.T) {
}
}
}

func TestDataChunks(t *testing.T) {
TMXURL = "testData/chunkData.tmx"
f, err := os.Open(TMXURL)
if err != nil {
t.Errorf("Unable to open %v. Error was: %v", TMXURL, err)
return
}
defer f.Close()
m, err := Parse(f)
if err != nil {
t.Error("Unable to parse chunk data")
return
}
for i, e := range testDataExpected {
if m.Layers[0].Data[0].Chunks[0].Tiles[i].GID != e {
t.Errorf("Test data did not match expected data\nWanted: %v\nGot: %v", e, m.Layers[0].Data[0].Chunks[0].Tiles[i].GID)
return
}
}
}

func TestDataMalformedChunks(t *testing.T) {
TMXURL = "testData/malformedChunkData.tmx"
f, err := os.Open(TMXURL)
if err != nil {
t.Errorf("Unable to open %v. Error was: %v", TMXURL, err)
return
}
defer f.Close()
_, err = Parse(f)
if err == nil {
t.Error("Able to parse malformed chunk data")
return
}
}
13 changes: 13 additions & 0 deletions testData/chunkData.tmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" tiledversion="1.1.5" orientation="orthogonal" renderorder="right-down" width="3" height="3" tilewidth="16" tileheight="16" infinite="1" nextobjectid="1">
<tileset firstgid="1" name="roguelikeIndoor_transparent" tilewidth="16" tileheight="16" spacing="1" tilecount="468" columns="26">
<image source="roguelikeIndoor_transparent.png" width="457" height="305"/>
</tileset>
<layer name="Tile Layer 1" width="3" height="3">
<data encoding="base64" compression="zlib">
<chunk x="-32" y="-16" width="16" height="16">
eJx7zcDA8AaI3wLxdyBOYWRgkAJiZyB2AWJBIAYAfvME1w==
</chunk>
</data>
</layer>
</map>
13 changes: 13 additions & 0 deletions testData/malformedChunkData.tmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" tiledversion="1.1.5" orientation="orthogonal" renderorder="right-down" width="3" height="3" tilewidth="16" tileheight="16" infinite="1" nextobjectid="1">
<tileset firstgid="1" name="roguelikeIndoor_transparent" tilewidth="16" tileheight="16" spacing="1" tilecount="468" columns="26">
<image source="roguelikeIndoor_transparent.png" width="457" height="305"/>
</tileset>
<layer name="Tile Layer 1" width="3" height="3">
<data encoding="base64" compression="zlib">
<chunk x="-32" y="-16" width="16" height="16">
iJx7zcDA8AaI3wLxdyBOYWRgkAJiZyB2AWJBIAYAfvME1w==
</chunk>
</data>
</layer>
</map>

0 comments on commit c9ede7f

Please sign in to comment.