remove scratch arena from tiled library

This commit is contained in:
Rokas Puzonas 2026-09-21 20:11:19 +03:00
parent 96cfcd4626
commit b6d9f1664b
7 changed files with 98 additions and 32 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.12.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="64" tileheight="64" infinite="1" nextlayerid="8" nextobjectid="15">
<map version="1.10" tiledversion="1.12.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="64" tileheight="64" infinite="1" nextlayerid="8" nextobjectid="17">
<tileset firstgid="1" source="tileset.tsx"/>
<layer id="2" name="Ground" width="30" height="20">
<data encoding="csv">
@ -20,6 +20,24 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</chunk>
<chunk x="16" y="0" width="16" height="16">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,90,90,90,90,90,90,90,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</chunk>
</data>
</layer>
@ -42,6 +60,24 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</chunk>
<chunk x="16" y="0" width="16" height="16">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,98,98,98,98,98,98,98,0,0,0,0,0,
0,0,0,0,98,0,0,0,0,0,98,0,0,0,0,0,
0,0,0,0,98,0,7,0,26,0,98,0,0,0,0,0,
0,0,0,0,98,0,0,0,0,0,98,0,0,0,0,0,
0,0,0,0,98,0,7,0,26,0,98,0,0,0,0,0,
0,0,0,0,98,0,0,0,0,0,98,0,0,0,0,0,
0,0,0,0,98,98,98,98,98,98,98,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</chunk>
</data>
</layer>
@ -50,5 +86,16 @@
<point/>
</object>
</objectgroup>
<objectgroup id="7" name="Level bounds"/>
<objectgroup id="7" name="Level bounds">
<object id="15" x="345.333" y="218.667" width="633.333" height="566.667">
<properties>
<property name="level" type="int" value="1"/>
</properties>
</object>
<object id="16" x="1228" y="172" width="565.333" height="593.333">
<properties>
<property name="level" type="int" value="2"/>
</properties>
</object>
</objectgroup>
</map>

View File

@ -212,7 +212,6 @@ variant: Variant,
pub fn initFromXml(
arena: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Layer {
@ -279,33 +278,41 @@ pub fn initFromXml(
var objects: std.ArrayList(Object) = .empty;
var layers: std.ArrayList(Layer) = .empty;
if (variant == .object) {
try objects.ensureTotalCapacityPrecise(arena, doc.countChildren(element_id));
}
if (variant == .group) {
try layers.ensureTotalCapacityPrecise(arena, doc.countChildren(element_id));
}
var iter = doc.iterChildren(element_id);
while (iter.next()) |child_id| {
const child = doc.getTag(child_id) orelse continue;
const child_name = child.variant.tag.name;
if (std.mem.eql(u8, child_name, "properties")) {
properties = try Property.List.initFromXml(arena, scratch, doc, child_id);
properties = try Property.List.initFromXml(arena, doc, child_id);
} else if (variant == .image and std.mem.eql(u8, child_name, "image")) {
variant.image.image = try ImageVariant.Image.initFromXml(arena, doc, child_id);
} else if (variant == .object and std.mem.eql(u8, child_name, "object")) {
const object = try Object.initFromXml(arena, scratch, doc, child_id);
try objects.append(scratch.allocator(), object);
const object = try Object.initFromXml(arena, doc, child_id);
objects.appendAssumeCapacity(object);
} else if (variant == .group and Layer.Type.name_map.has(child_name)) {
const layer = try initFromXml(arena, scratch, doc, child_id);
try layers.append(scratch.allocator(), layer);
const layer = try initFromXml(arena, doc, child_id);
layers.appendAssumeCapacity(layer);
}
}
if (variant == .object) {
variant.object.items = try arena.dupe(Object, objects.items);
variant.object.items = objects.items;
}
if (variant == .group) {
variant.group.layers = try arena.dupe(Layer, layers.items);
variant.group.layers = layers.items;
}
return Layer{

View File

@ -116,7 +116,6 @@ shape: Shape,
pub fn initFromXml(
arena: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Object {
@ -213,10 +212,12 @@ pub fn initFromXml(
const points_str = child_attrs.get("points") orelse "";
var points: std.ArrayList(Position) = .empty;
try points.ensureTotalCapacityPrecise(arena, std.mem.countScalar(u8, points_str, ' ')+1);
var point_iter = std.mem.splitScalar(u8, points_str, ' ');
while (point_iter.next()) |point_str| {
const point = try Position.parseCommaDelimited(point_str);
try points.append(scratch.allocator(), point);
points.appendAssumeCapacity(point);
}
shape = .{

View File

@ -33,13 +33,13 @@ pub const List = struct {
pub fn initFromXml(
arena: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Property.List {
_ = try doc.getTagExpect(element_id, "properties");
var temp_properties: std.ArrayList(Property) = .empty;
var properties: std.ArrayList(Property) = .empty;
try properties.ensureTotalCapacityPrecise(arena, doc.countChildren(element_id));
var iter = doc.iterChildren(element_id);
while (iter.next()) |child_id| {
@ -48,14 +48,12 @@ pub const List = struct {
if (std.mem.eql(u8, child_name, "property")) {
const property = try Property.initFromXml(arena, doc, child_id);
try temp_properties.append(scratch.allocator(), property);
properties.appendAssumeCapacity(property);
}
}
const properties = try arena.dupe(Property, temp_properties.items);
return List{
.items = properties
.items = properties.items
};
}

View File

@ -109,7 +109,6 @@ layers: []Layer,
// https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#map
pub fn initFromXml(
gpa: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Tilemap {
@ -145,8 +144,27 @@ pub fn initFromXml(
// TODO: staggerindex
}
var layer_count: usize = 0;
var tileset_count: usize = 0;
{
var iter = doc.iterChildren(element_id);
while (iter.next()) |child_id| {
const child = doc.getTag(child_id) orelse continue;
const child_name = child.variant.tag.name;
if (std.mem.eql(u8, child_name, "tileset")) {
tileset_count += 1;
} else {
layer_count += 1;
}
}
}
var tileset_list: std.ArrayList(TilesetReference) = .empty;
try tileset_list.ensureTotalCapacityPrecise(arena, tileset_count);
var layer_list: std.ArrayList(Layer) = .empty;
try layer_list.ensureTotalCapacityPrecise(arena, layer_count);
var iter = doc.iterChildren(element_id);
while (iter.next()) |child_id| {
@ -154,11 +172,10 @@ pub fn initFromXml(
const child_name = child.variant.tag.name;
if (std.mem.eql(u8, child_name, "tileset")) {
try tileset_list.append(scratch.allocator(), try TilesetReference.initFromXml(arena, doc, child_id));
tileset_list.appendAssumeCapacity(try TilesetReference.initFromXml(arena, doc, child_id));
} else {
try layer_list.append(scratch.allocator(), try Layer.initFromXml(
layer_list.appendAssumeCapacity(try Layer.initFromXml(
arena,
scratch,
doc,
child_id
));

View File

@ -36,7 +36,6 @@ pub const Tile = struct {
pub fn initFromXml(
arena: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Tile {
@ -53,7 +52,7 @@ pub const Tile = struct {
const child_name = child.variant.tag.name;
if (std.mem.eql(u8, child_name, "properties")) {
properties = try Property.List.initFromXml(arena, scratch, doc, child_id);
properties = try Property.List.initFromXml(arena, doc, child_id);
}
}
@ -124,7 +123,6 @@ tiles: []Tile,
pub fn initFromXml(
gpa: std.mem.Allocator,
scratch: *std.heap.ArenaAllocator,
doc: xml.Document,
element_id: xml.Element.Id
) !Tileset {
@ -144,6 +142,7 @@ pub fn initFromXml(
var image: ?Image = null;
var tiles_list: std.ArrayList(Tile) = .empty;
try tiles_list.ensureTotalCapacityPrecise(arena, doc.countChildren(element_id));
var iter = doc.iterChildren(element_id);
while (iter.next()) |child_id| {
@ -153,8 +152,8 @@ pub fn initFromXml(
if (std.mem.eql(u8, child_name, "image")) {
image = try Image.intFromXml(arena, doc, child_id);
} else if (std.mem.eql(u8, child_name, "tile")) {
const tile = try Tile.initFromXml(arena, scratch, doc, child_id);
try tiles_list.append(scratch.allocator(), tile);
const tile = try Tile.initFromXml(arena, doc, child_id);
tiles_list.appendAssumeCapacity(tile);
}
}

View File

@ -270,14 +270,11 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 {
};
{
var scratch = std.heap.ArenaAllocator.init(plt.gpa);
defer scratch.deinit();
var xml_parser = try Tiled.xml.Parser.initCapacity(plt.gpa, .{});
defer xml_parser.deinit(plt.gpa);
const tilemap = try Tiled.Tilemap.initFromXml(
plt.gpa, &scratch,
plt.gpa,
try xml_parser.parse(plt.assets.readFile("tiled/map.tmx")),
.root
);
@ -287,7 +284,7 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 {
defer tilesets.deinit(plt.gpa);
try tilesets.add(plt.gpa, "tileset.tsx", try Tiled.Tileset.initFromXml(
plt.gpa, &scratch,
plt.gpa,
try xml_parser.parse(plt.assets.readFile("tiled/tileset.tsx")),
.root
));