Skip to content

Add <preupdate /> tag.#2072

Open
player-03 wants to merge 1 commit into
openfl:developfrom
player-03:preupdate
Open

Add <preupdate /> tag.#2072
player-03 wants to merge 1 commit into
openfl:developfrom
player-03:preupdate

Conversation

@player-03

@player-03 player-03 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

This allows users to pre-process (or even programmatically generate) their assets before Lime copies them. I've included a <postupdate /> tag for consistency (and so people don't ask why it's left out), but the main expected use case is pre-processing.

This is a more specific alternative to #1993, which offered full control at the expense of more potential to shoot yourself in the foot. This version should behave more like people expect.

@moxie-coder moxie-coder left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sounds very cool on paper honestly, I might be able to think of use cases for this possibly (macros maybe)

@ACrazyTown

Copy link
Copy Markdown
Contributor

I tried this out, and it works really well except for one minor nitpick: Like in the original issue (#1959), Lime will complain if the assets folder does not exist at build-time. Seems like this is checked before the preupdate script runs

@player-03

Copy link
Copy Markdown
Contributor Author

Ah, I see. It verifies the asset path when the <assets /> tag is first parsed. It has to do this because it has to be able to tell if the asset is a single file or a directory, since in the latter case it has to iterate through and enumerate the individual files.

The <execute /> tag would handle this, since it runs immediately and you can generate the asset before ProjectXMLParser reaches the <assets /> tag.

For <preupdate /> to work, we'd have to make some kind of change to how assets are handled.

  • Allow the user to specify if it's a file or directory, and defer directory traversal until the update step. But if anything examines the list of assets in the meantime, it would miss some.
  • Require missing assets to be files, not directories. At least then the correct number of assets can be found, even if the contents aren't there yet.
  • Run the <preupdate /> callbacks immediately whenever an asset isn't found. (With a variable to keep track of whether this was already done, so as not to do it twice.) But this means they'll get run every time the file is parsed, even in display mode.

...I guess if assets are getting parsed in display mode anyway, you might as well use <execute />, and not even bother with unless="display". It's going to check for the file every time, so you should also run your code every time.

@ACrazyTown

Copy link
Copy Markdown
Contributor

I feel like going with <execute /> would probably be the least hassle. Changing current behavior sounds like something for a major version

@dimensionscape

dimensionscape commented Jun 19, 2026

Copy link
Copy Markdown
Member

Sounds very cool on paper honestly, I might be able to think of use cases for this possibly (macros maybe)

XML lifecycle hooks could be useful, but I would just note that hxp is canonically more useful here.

@player-03

Copy link
Copy Markdown
Contributor Author

Yeah, that was my thought process for the <execute /> tag. HXP naturally solves this problem because it can execute arbitrary code, but not everyone wants to go to the trouble of switching an established project.

@ACrazyTown

ACrazyTown commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

HXP naturally solves this problem because it can execute arbitrary code, but not everyone wants to go to the trouble of switching an established project.

I agree. While HXP would definitely make sense here, most Lime/OpenFL projects ship with Project.xml by default. Needing to convert the entire project from XML to HXP for one feature definitely seems like a bit of an inconvenience (especially on larger projects), so it'd be nice if there was a way to accomplish something like this via XML too

@dimensionscape

Copy link
Copy Markdown
Member

Sure.

Anyway, I had a chance to take a deeper look at the PR. I don’t think this can close #1959 as written, though. The failing case in there is specifically a generated asset path that does not exist yet, and that still appears to fail before <preupdate /> can run.

parseAssetsElement() validates the asset path during Project.xml parsing:

if (!FileSystem.exists(path))
{
	Log.error("Could not find asset path \"" + path + "\"");
	return;
}

The new case only records the command with parseCommandElement(element, preUpdateCallbacks). Those callbacks are not executed until PlatformTarget.execute() reaches the update/build/test branch, after thre project file has already been parsed successfully.

So a project like:

<preupdate command="pre-process.sh" />
<assets path="game/assets-final" rename="assets" if="final" />

will still fail if game/assets-final does not already exist.

@dimensionscape

Copy link
Copy Markdown
Member

@ACrazyTown

HXP naturally solves this problem because it can execute arbitrary code, but not everyone wants to go to the trouble of switching an established project.

I agree. While HXP would definitely make sense here, most Lime/OpenFL projects ship with Project.xml by default. Needing to convert the entire project from XML to HXP for one feature definitely seems like a bit of an inconvenience (especially on larger projects), so it'd be nice if there was a way to accomplish something like this via XML too

I think there may be a small misconception here, which is why I brought up HXP to begin with. HXP was designed for this kind of escape hatch, and using it does not necessarily mean converting an entire project.xml to HXP.

You can use a very small project.hxp wrapper that runs code first, then merges the existing XML project.

Something like this:

import lime.tools.HXProject;
import lime.tools.ProjectXMLParser;
import sys.FileSystem;

class Project extends HXProject {
	public function new() {
		super();

		if (!FileSystem.exists("generated-assets")) {
			FileSystem.createDirectory("generated-assets");
		}

		merge(new ProjectXMLParser("Project.xml", defines));
	}
}

That lets HXP generate the missng asset directory before ProjectXMLParser validates the <assets /> path, while still keeping the rest of the project in XML.

I’m not against adding more XML hooks, but I wanted to clarify that using HXP here does not have to be a full project migration.

@moxie-coder

Copy link
Copy Markdown

honestly that's an very cool discovery, and kinda something I wish I knew beforehand since I thought it wasn't possible to use HXP and XML together lol

@player-03

Copy link
Copy Markdown
Contributor Author

parseAssetsElement() validates the asset path during Project.xml parsing

Yeah, that's I was saying. Except, more thorough.


You know, <preupdate /> still feels like it should have worked. Validating assets is the update step's job, why would there be unrelated code doing that job?

But no, I can kind of see why we want to traverse the directory immediately. There's a lot of attributes involved, and it's way easier to deal with them immediately than to store them. It would take an Array<{ path:String, ?embed:Bool, ?library:String, targetPath:String, ?glyphs:String, ?type:AssetType, ?include:String, ?exclude:String }>, just to be able to delay populating assets. And why would we even want to delay it; what if some code needs to access it?


There are certainly two sides to this, but I'm leaning towards "assets should only be processed in the update step, and no one should expect to access them until then." It'd also save a bunch of file access operations during display calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants