Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add template support #170

Merged
merged 21 commits into from
May 10, 2022
Merged

Add template support #170

merged 21 commits into from
May 10, 2022

Conversation

RossBrunton
Copy link
Contributor

@RossBrunton RossBrunton commented Feb 22, 2022

Whew, this was a bigger change than I thought it would be. I've made a few assumptions about the best way to design and implement things, so feel free to let me know if it should be restructured any.

Relates to #145

======

This patch adds support for templates. Templates are a property on Objects
that specify an external file to load object properties by default. In
this implementation, templates are not visible to the end user, their
behaviour happens "automatically".

As it parses, the Map will generate a list of templates, with each being
identified by their ID.

Templates introduce the concept of a tile that is bound to a tileset
that is not part of the main map's list of tilesets. For this reason,
the tileset_index() function now returns Option. Internally, an
enum is used to signify whether the tileset is map or template bound.

I had to change the signature of the Resource cache, because the
generator function now needs access to the cache.

@bjorn
Copy link
Member

bjorn commented Feb 23, 2022

This change really makes me wonder whether I made some horrible design decisions, and whether it couldn't all be a lot simpler when we could make a few changes to the data format. If you have any ideas about this, please let me know so we could potentially simplify this in future versions of Tiled.

Unfortunately, I won't have time to give this a thorough review until next week.

One thing sticks out to me, which is the choice to make the templates invisible to the user. That sounds very convenient, but eventually I still have the idea that rs-tiled could also be used to make modifications and write back files. Will it be possible to add this in the future without major changes in the API? Of course @aleokdev has been telling me not to worry about modification and writing for now (and maybe by then we should reconsider the entire format), but I just thought I'd mention it.

@aleokdev
Copy link
Contributor

@bjorn If you ever do consider a new format, please count me in in the new specs team. :)

@aleokdev aleokdev added breaking This change breaks backwards-compatibility feature labels Feb 23, 2022
Copy link
Contributor

@aleokdev aleokdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO ParseContext should not be defined in this PR, as it is largely unrelated to templates. Yes, it simplifies things, but it also made reviewing the PR much harder, and it has many issues unrelated to the addition of templates. I'd suggest reverting these changes; I'd be happy to review a parse context PR after this one has been merged so we can get the big picture.

@@ -15,13 +16,22 @@ mod util;
pub use finite::*;
pub use infinite::*;

/// The locatation of the tileset this tile is in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in location

/// valid index of the map tileset container, but **isn't guaranteed to actually contain
/// this tile**.
tileset_index: usize,
/// A valid TilesetLocation that contains this tile but **only if it is the tileset's range of tiles**.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// A valid TilesetLocation that contains this tile but **only if it is the tileset's range of tiles**.
/// A valid TilesetLocation that points to a tileset that **may or may not contain** this tile.

src/objects.rs Outdated
let s: String = template;
let template_path = PathBuf::from(s);

let template_path = parse_context.require_path("Template")?.join(template_path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let template_path = parse_context.require_path("Template")?.join(template_path);
let template_path = parse_context.require_path("Template")?.join(Path::new(s));

src/objects.rs Outdated
let mut template_id: Option<usize> = None;

// If the template attribute is there, we need to go fetch the template file
if let Some(template) = template {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try returning template_id from this scope instead of using a mutable variable for it.

src/objects.rs Outdated
@@ -95,11 +129,23 @@ impl ObjectData {
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change

src/template.rs Outdated
Comment on lines 27 to 28
pub(crate) fn new_external<CacheTy: ResourceCache>(
path: &Path,
parse_context: &mut ParseContext<CacheTy>,
) -> Result<usize, TiledError> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a new function, it isn't very intuitive to see that it returns an usize. It definitely should not insert itself into the context, but rather return the resulting template to be inserted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there's an issue here in that tiles contained in a Template need to be able to store a reference of some kind to the template (so they can identify their tileset). I could have the Tile contain an Arc to either the Tileset or the Template, but that would make the Tile not be Copy, and may have performance implications.

I decided to copy how it was done with Tilesets, where during parsing a list of tilesets is generated, and tiles store an index into the list. For templates though, the parsing of the template's tile is done during parsing of the template itself, so the template needs to know its own id to tell the tile.

I agree this is a bit of a mess though, and will gladly change it if there is a better way. And yeah, the function names are not idiomatic, sorry!

src/template.rs Outdated
Comment on lines 31 to 30
// First, check if this template already exists in our list of templates (it will be uniquely identified by its
// path).
Copy link
Contributor

@aleokdev aleokdev Feb 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be done here... This creates a very tight binding between Template and ParseContext. The constructor should instead return the template, which then can be inserted into the cache externally. This is also more flexible since it allows loading templates without adding them to the cache (If we want to expose templates at some point, for instance)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should return Result<Template, TiledError>.

src/template.rs Outdated
err,
})?;

let mut tileset_parser = EventReader::new(file);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tileset parser?

src/template.rs Outdated
Comment on lines 83 to 86
parse_context.templates.push(Template {
path: path.to_path_buf(),
tileset: None,
object: None,
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this shouldn't be here; These are changes you wouldn't expect from a function called parse_external_template.

src/tile.rs Outdated
@@ -47,15 +48,15 @@ impl Tile {
let mut animation = None;
parse_tag!(parser, "tile", {
"image" => |attrs| {
image = Some(Image::new(parser, attrs, path_relative_to.ok_or(TiledError::SourceRequired{object_to_parse:"Image".to_owned()})?)?);
image = Some(Image::new(parser, attrs, &parse_context.require_path("Image")?)?);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't related to the addition of templates.

@RossBrunton
Copy link
Contributor Author

IMO ParseContext should not be defined in this PR, as it is largely unrelated to templates. Yes, it simplifies things, but it also made reviewing the PR much harder, and it has many issues unrelated to the addition of templates. I'd suggest reverting these changes; I'd be happy to review a parse context PR after this one has been merged so we can get the big picture.

I didn't really want to add it here as well, but we need to pass a lot more information around, and to a lot of locations. Specifically to parse templates we need:

  • The cache (to load a tilesheet if it's been already been processed).
  • The base filename (for the base file that the tile URI is based on).

Templates can be specified any time we need to process an Object, which comes up in a lot of places (although I guess we could just not support templates in more obscure places, like tilesets).

Templates also introduce a new "context" which affects which tileset a tile is linked to (not the ones in the main map), which is another piece of information that needs to be propogated up and down the call stack.

I'm open to ideas on how we can improve it, but I can't see any solution that doesn't involve giving each function 2-3 more arguments. Using a struct to store this information just makes it more cleaner IMO. I can refactor things so that arguments are passed directly between functions if that is what you prefer.

@RossBrunton
Copy link
Contributor Author

This change really makes me wonder whether I made some horrible design decisions, and whether it couldn't all be a lot simpler when we could make a few changes to the data format. If you have any ideas about this, please let me know so we could potentially simplify this in future versions of Tiled.

Unfortunately, I won't have time to give this a thorough review until next week.

One thing sticks out to me, which is the choice to make the templates invisible to the user. That sounds very convenient, but eventually I still have the idea that rs-tiled could also be used to make modifications and write back files. Will it be possible to add this in the future without major changes in the API? Of course @aleokdev has been telling me not to worry about modification and writing for now (and maybe by then we should reconsider the entire format), but I just thought I'd mention it.

From my (limited) experience of working with Tiled files, I think the format is pretty solid. I've found templates a really useful addition for managing object properties. The complexity with this MR is more with managing file locations and in-process parsing, neither of which I think are indicative of problems in the file format.

With regards to the templates being resolved "automatically". It should be simple enough to change things so that objects store a template index number, and properties (x, y, width, etc.) on ObjectData being optional (which is more faithful to the original data in the file anyway). The getter methods would check for the data on the ObjectData, then the template, and finally a default value.

I think if the library is automatically decoding and calculating gids to tileset indexes, it makes sense for it to also automatically parse and understand templates as well.

@aleokdev
Copy link
Contributor

but I can't see any solution that doesn't involve giving each function 2-3 more arguments

It's okay, we'll deal with those later. What is important right now is the feature; refactors can come later down the line, which also allows us to think more about them as we have more information about the interface at our disposal.

@bjorn
Copy link
Member

bjorn commented Feb 24, 2022

From my (limited) experience of working with Tiled files, I think the format is pretty solid. I've found templates a really useful addition for managing object properties. The complexity with this MR is more with managing file locations and in-process parsing, neither of which I think are indicative of problems in the file format.

Alright, that's great to hear!

With regards to the templates being resolved "automatically". It should be simple enough to change things so that objects store a template index number, and properties (x, y, width, etc.) on ObjectData being optional (which is more faithful to the original data in the file anyway). The getter methods would check for the data on the ObjectData, then the template, and finally a default value.

Rather than making each value optional, in Tiled there is a class member with bitflags indicating which values have been "overridden". In addition to being less fragmented, this also allows copying down values from the template so access can be more direct. Of course that does mean that when editing the template, the changes need to be copied down to all instances. Anyway, we can worry about that later, when we get around to #171.

I think if the library is automatically decoding and calculating gids to tileset indexes, it makes sense for it to also automatically parse and understand templates as well.

Yes, that is definitely helpful.

@RossBrunton RossBrunton changed the title Added ParseContext and template support Added template support Feb 24, 2022
Copy link
Contributor

@aleokdev aleokdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This is definitely much better. However, there are still a couple of important issues that need to be tackled.

src/map.rs Outdated Show resolved Hide resolved
src/objects.rs Outdated
object_to_parse: "Template".to_string(),
})?
.parent()
.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return an error instead; I believe there was an InvalidPath error or similar in the interface.

src/tileset.rs Outdated
@@ -113,10 +136,23 @@ impl Tileset {
pub(crate) fn parse_xml_in_map(
parser: &mut impl Iterator<Item = XmlEventResult>,
attrs: Vec<OwnedAttribute>,
map_path: &Path,
map_path: &Path, // Template or Map file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uuuuuuhm...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops! What should I call it? The paths are tracked in multiple places and now it can be a map, template or (I think) a tilesheet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name root_path has appeared elsewhere, and I guess it would be appropriate here as well. However, I don't really agree with the term "root", and would also be fine with just path (and would assume this path does not include the file name, actually).

Copy link
Contributor

@aleokdev aleokdev Feb 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function should be renamed to something that doesn't specify maps (e.g. parse_xml_in_file) and the path parameter could just be file_path then.

@aleokdev
Copy link
Contributor

BTW, you don't need to force push on each commit; In fact, it's better for us that you keep the original commits so we can see more easily what's changed between each review. Don't worry, the commits will all be squeezed down to a single one when merging with master, so the PR history can be as messy as you want (Still, be a bit careful :) ) Thanks!

This patch adds support for templates. Templates are a property on Objects
that specify an external file to load object properties by default. In
this implementation, templates are not visible to the end user, their
behaviour happens "automatically".

As it parses, the Map will generate a list of templates, with each being
identified by their ID.

Templates introduce the concept of a tile that is bound to a tileset
that is not part of the main map's list of tilesets. For this reason,
the tileset_index() function now returns Option<usize>. Internally, an
enum is used to signify whether the tileset is map or template bound.

I had to change the signature of the Resource cache, because the
generator function now needs access to the cache.
@aleokdev
Copy link
Contributor

BTW, you don't need to force push on each commit; In fact, it's better for us that you keep the original commits so we can see more easily what's changed between each review. Don't worry, the commits will all be squeezed down to a single one when merging with master, so the PR history can be as messy as you want (Still, be a bit careful :) ) Thanks!

Please consider doing this, otherwise I need to review the entire PR instead of the changed parts.

@RossBrunton
Copy link
Contributor Author

Sorry about the force pushing, I didn't see your message before pushing that last one! I guess I'm used to gitlab where rewriting history is handled much more egonomically. You can click the secret hidden link on the word "force-pushed" to see the diff introduced by that commit, but it's nowhere near as good as gitlab's "change history thing".

Anyway, I rushed it a bit, so there may be small mistakes I need to clean up.

src/cache.rs Outdated Show resolved Hide resolved
src/template.rs Outdated
impl Template {
pub(crate) fn parse_and_append_template(
path: &Path,
templates: &mut Vec<Template>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the cache, not here.

src/template.rs Outdated
Comment on lines 31 to 30
// First, check if this template already exists in our list of templates (it will be uniquely identified by its
// path).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should return Result<Template, TiledError>.

src/template.rs Outdated
.find(|(_, template)| template.path == path)
{
return Ok(id);
}
Copy link
Contributor

@aleokdev aleokdev Mar 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be moved to the caller using get_template and then insert_template.

src/template.rs Outdated

fn parse_and_append_external_template(
parser: &mut impl Iterator<Item = XmlEventResult>,
_attrs: &Vec<OwnedAttribute>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the attributes aren't being used, they shouldn't be passed to the function.

src/template.rs Outdated
let res = Tileset::parse_xml_in_map(parser, attrs, template_path, templates, Some(template_id), cache)?;
match res.result_type {
EmbeddedParseResultType::ExternalReference { tileset_path } => {
let tileset = if let Some(ts) = cache.get_tileset(&tileset_path) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use Option::unwrap_or_else here... Or cache.get_or_try_insert_tileset.

@RossBrunton
Copy link
Contributor Author

So it seems there's a design issue here. Tiles must be able to identify which template they are "from" (so they can do the automatic gid resolving). I implemented this as an index into a vector that is collected as we parse, but that seems to be not the design you are looking for (which makes sense, I don't really like it either). Also complicating things is the fact that tiles inside templates can themselves include templates (Tiles can contain ObjectGroups).

Any suggestions on how I can refactor that so it's less messy?

@aleokdev aleokdev linked an issue Mar 3, 2022 that may be closed by this pull request
src/template.rs Outdated
pub(crate) struct Template {
pub path: PathBuf,
pub tileset: Option<Arc<Tileset>>,
pub object: Option<ObjectData>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The object attribute is mandatory, it just wasn't specified in the docs (oops): mapeditor/tiled@8f1162d

@aleokdev aleokdev added this to the 0.11.0 milestone Mar 4, 2022
@aleokdev aleokdev changed the title Added template support Add template support Mar 4, 2022
@aleokdev
Copy link
Contributor

aleokdev commented Mar 5, 2022

So it seems there's a design issue here. Tiles must be able to identify which template they are "from" (so they can do the automatic gid resolving). I implemented this as an index into a vector that is collected as we parse, but that seems to be not the design you are looking for (which makes sense, I don't really like it either). Also complicating things is the fact that tiles inside templates can themselves include templates (Tiles can contain ObjectGroups).

Any suggestions on how I can refactor that so it's less messy?

Yes; If you instead put templates in the cache, then the templates vector won't be needed and as such the template constructor won't need to insert itself anywhere (as the tiles it creates can do that themselves). This would imply making templates public, but I don't see how that is an issue, seeing how sharing templates between maps is a pretty common occurrence.

@RossBrunton
Copy link
Contributor Author

What would LayerTileData::tileset_index be in that case?

@aleokdev
Copy link
Contributor

aleokdev commented Mar 8, 2022

What would LayerTileData::tileset_index be in that case?

It can be the path of the template, as tiles in templates are uncommon enough to not have any impact on the memory and performance footprint.

@aleokdev
Copy link
Contributor

aleokdev commented Mar 8, 2022

That'd also remove the dependency of the map when accessing the tileset of a template's tile. However, maybe for consistency's sake a Vec of Arc to the map templates can be stored in the map, just like tilesets, and then we could have tiles store the template index in the map. Without looking at the code (I'm on phone rn) I believe that is what your current impl is doing

@aleokdev
Copy link
Contributor

aleokdev commented Mar 8, 2022

From the two options the second one sounds better, as you'd have access to the templates a map is referencing to and overall it'd be more consistent.

@bjorn
Copy link
Member

bjorn commented Apr 25, 2022

Disallowing tiles from having tile objects from within them would reduce complexity by a lot. Currently that's the blocker here.

In Tiled, the ObjectGroup of a Tile is not allowed to refer to tile objects, nor to templates of tile objects. So, these kind of circular references are impossible and don't need to be supported. Probably something that should also be mentioned in the Tiled manual.

@aleokdev
Copy link
Contributor

Neeeeat. Will finish the PR ASAP then.

@aleokdev aleokdev requested a review from bjorn April 25, 2022 17:26
@aleokdev
Copy link
Contributor

That should be it. Ready for final review.

@aleokdev
Copy link
Contributor

I'm more worried about the external interface and assumptions taken, the actual implementation can be upgraded later on without issues.

src/tileset.rs Outdated Show resolved Hide resolved
aleokdev
aleokdev previously approved these changes Apr 27, 2022
/// # fn main() -> Result<()> {
/// let mut loader = Loader::new();
/// let path = "assets/tilesheet.tsx";
///
/// assert!(loader.cache().get_tileset(path).is_none());
/// loader.load_tmx_map("assets/tiled_base64_external.tmx");
/// let tileset = Arc::new(loader.load_tsx_tileset(path)?);
/// loader.cache_mut().insert_tileset(path, tileset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these changes should be done in a different PR.

Copy link
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few minor suggestions and some questions.

CHANGELOG.md Outdated Show resolved Hide resolved
src/tileset.rs Outdated Show resolved Hide resolved
src/template.rs Outdated Show resolved Hide resolved
src/tile.rs Outdated Show resolved Hide resolved
@@ -22,6 +20,9 @@ impl GroupLayerData {
infinite: bool,
map_path: &Path,
tilesets: &[MapTilesetGid],
for_tileset: Option<Arc<Tileset>>,
reader: &mut impl ResourceReader,
cache: &mut impl ResourceCache,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that in many places we're passing around both a reader and a cache. Would it make sense to pass around a loader instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, Loader owns the reader/cache

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that pose a problem for passing loader: &mut Loader instead of the above two parameters?

src/map.rs Show resolved Hide resolved
aleokdev
aleokdev previously approved these changes Apr 29, 2022
Copy link
Contributor

@aleokdev aleokdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still has some internal quirks, but we'll deal with them later. Last review!

@aleokdev aleokdev requested a review from bjorn April 29, 2022 22:20
Copy link
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I found a few things could be improved about the actual inheritance from the template.

src/objects.rs Outdated Show resolved Hide resolved
src/objects.rs Outdated Show resolved Hide resolved
src/objects.rs Outdated Show resolved Hide resolved
bjorn
bjorn previously approved these changes May 2, 2022
src/objects.rs Show resolved Hide resolved
@aleokdev aleokdev merged commit ca9d34d into mapeditor:next May 10, 2022
@aleokdev
Copy link
Contributor

Thank you @RossBrunton and sorry for the wait!

@RossBrunton
Copy link
Contributor Author

No problem, thanks for taking over this and improving it.

@bjorn bjorn mentioned this pull request May 13, 2022
bjorn added a commit that referenced this pull request May 19, 2022
* Added template support

This patch adds support for templates. Templates are a property on Objects
that specify an external file to load object properties by default. In
this implementation, templates are not visible to the end user, their
behaviour happens "automatically".

As it parses, the Map will generate a list of templates, with each being
identified by their ID.

Templates introduce the concept of a tile that is bound to a tileset
that is not part of the main map's list of tilesets. For this reason,
the tileset_index() function now returns Option<usize>. Internally, an
enum is used to signify whether the tileset is map or template bound.

I had to change the signature of the Resource cache, because the
generator function now needs access to the cache.

* Handle error on template base_path.parent()

* LayerTileData object now can contain a templ. arc

Rather than an id into some list, this now contains an arc to the
tileset directly. Makes the code cleaner, and allows caching to behave
better, but can have performance implications.

* Removed some more template list Vecs

These should have been removed last commit, whoops!

* Responded to review comments

* Don't bind attributes property to a name

Squishes an "unused" warning.

* Cargo fmt and updated test

* Update changelog

* Clippy fixes

* Simplify LayerTileData and create ObjectTileData

* Fix clippy warnings

* Simplify implementation

* Apply suggestions from code review

* Remove outdated comment

* Address PR comments

* Trigger CI & handle review comment

Co-authored-by: alexdevteam <[email protected]>
Co-authored-by: Thorbjørn Lindeijer <[email protected]>
Co-authored-by: aleokdev <[email protected]>
@bjorn bjorn mentioned this pull request May 19, 2022
bjorn added a commit that referenced this pull request May 19, 2022
* Added template support

This patch adds support for templates. Templates are a property on Objects
that specify an external file to load object properties by default. In
this implementation, templates are not visible to the end user, their
behaviour happens "automatically".

As it parses, the Map will generate a list of templates, with each being
identified by their ID.

Templates introduce the concept of a tile that is bound to a tileset
that is not part of the main map's list of tilesets. For this reason,
the tileset_index() function now returns Option<usize>. Internally, an
enum is used to signify whether the tileset is map or template bound.

I had to change the signature of the Resource cache, because the
generator function now needs access to the cache.

* Handle error on template base_path.parent()

* LayerTileData object now can contain a templ. arc

Rather than an id into some list, this now contains an arc to the
tileset directly. Makes the code cleaner, and allows caching to behave
better, but can have performance implications.

* Removed some more template list Vecs

These should have been removed last commit, whoops!

* Responded to review comments

* Don't bind attributes property to a name

Squishes an "unused" warning.

* Cargo fmt and updated test

* Update changelog

* Clippy fixes

* Simplify LayerTileData and create ObjectTileData

* Fix clippy warnings

* Simplify implementation

* Apply suggestions from code review

* Remove outdated comment

* Address PR comments

* Trigger CI & handle review comment

Co-authored-by: alexdevteam <[email protected]>
Co-authored-by: Thorbjørn Lindeijer <[email protected]>
Co-authored-by: aleokdev <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change breaks backwards-compatibility feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for templates
3 participants