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

Using --pattern with negation on glb's doesn't seem to be possible #1492

Open
Kethatril opened this issue Aug 28, 2024 · 3 comments
Open

Using --pattern with negation on glb's doesn't seem to be possible #1492

Kethatril opened this issue Aug 28, 2024 · 3 comments
Labels

Comments

@Kethatril
Copy link

Describe the bug
I'm attempting to only process textures in a glb that don't match *comp2 however since there is no texture URI (as its a glb and the textures are embedded) I have to also make it always fail vs an empty string and I can't seem to figure out if that's possible with micromatch.

To Reproduce
Steps to reproduce the behavior:
1 Use --pattern with negation (e.g. !*comp2 or any other negative pattern) on a glb with no URI's for textures
2 Notice that every texture is processed including ones where the name ends in comp2

Expected behavior
--patterns that contain negation should work as expected on glb's that don't have URI's for textures

Additional context
Possibly empty URI's should not be matched against here:

} else if (patternRe && !(texture.getURI().match(patternRe) || texture.getName().match(patternRe))) {

Or at least not when every texture URI is an empty string.

@Kethatril Kethatril added the bug Something isn't working label Aug 28, 2024
@donmccurdy donmccurdy added this to the 🗄️ Backlog milestone Sep 3, 2024
@donmccurdy
Copy link
Owner

Interesting difference in how micromatch works when evaluating directly, or creating a regex...

const {isMatch, makeRe} = require("micromatch")

const pattern = '!foo';
const opts = { nocase: true, contains: true };

console.log({
	empty: isMatch('', pattern, opts),
	emptyRe: makeRe(pattern, opts).test(''),
});
// { empty: false, emptyRe: true }

It's possible that's a bug, though I'm not sure which result is expected.

For scripted use, I'd be open to adding callbacks for use like:

await document.transform(
  toktx({
    filter: (texture) => texture.getName().startsWith('foo')
  })
);

But that doesn't really help with CLI use. I'm not sure we can exclude empty URIs automatically without breaking other expectations.

@Kethatril
Copy link
Author

Yeah, looks like regex created by matchRe doesn't behave in the same way as isMatch. Seems to be intentional, or at least not something the author thinks is a problem. (Issue from picomatch, which is what micromatch uses for most matching micromatch/picomatch#117 )

For images that point to a bufferView a URI is invalid (according to the gltf spec), it's only an empty string here because the Texture class sets it to that by default. I'm not certain there are any reasons to check against it tbh, it's similar to checking a regex against undefined or null (as that is what an empty string represents in this context)

Currently it always succeeds for patterns with negation (and matches every embedded texture, no matter what the name is) and unless specifically matching an empty string (which means the pattern will always match no matter the name is for embedded textures) it will always fail.

Also because there are 3 cases where the uri can be empty (binary embedded image, data:uri image, or invalid image) I'm not sure matching against it can tell you much of use.

@donmccurdy
Copy link
Owner

Also because there are 3 cases where the uri can be empty (binary embedded image, data:uri image, or invalid image) I'm not sure matching against it can tell you much of use.

Agreed that matching a pattern with negation doesn't really work because of this. But for a positive match it will break expectations if we skip the empty URIs, and I'm not sure it would be wise for me to try to inspect the glob and guess which is which. 😕

Perhaps something like this:

  1. In @gltf-transform/functions's textureCompress() we'll add a 'filter' option, accepting a callback function (texture: Texture) => boolean
  2. In @gltf-transform/cli the --pattern flag can be replaced with two new flags, --include and --exclude, with the latter being explicit about the negation
  3. In @gltf-transform/cli we'll construct the 'filter' callback along these lines:
    (texture) => {
      const uri = texture.getURI();
      if (exclude && uri && exclude.match(uri)) return false;
      if (include && !include.match(uri)) return false;
      // ...
      return true;
    }

Maybe this should apply to more than just textureCompress(), @marwie @hybridherbst I think you'd requested something similar at one point – does this sound helpful? Perhaps this would replace --pattern and the regex options in a breaking change for v5 or at some later point, but for now it could exist alongside those options.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants