godotengine / godotengine/godot

`EditorExportPlugin`: `skip()` can cause issues when customizing a `CompressedTexture2D`

Open
#94,045 2 comments 0 reactions 0 assignees View on GitHub
bug topic:export
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

Commit 932c191 onwards

### System information

Godot v4.3.beta (b97110cd3) - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 980 Ti (NVIDIA; 31.0.15.3699) - Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz (8 Threads)

### Issue description

I made changes to `EditorExportPlugin` in PR #93878 that allowed all resources to be skipped through the `_export_file` function. I have found no issues with most imported files, such as `.wav` audio files, but have found an issue that I believe is specific to `Texture2D`'s interaction between `_customize_resource` and `skip()`.

**Works:** Skipping an `AudioStreamWAV` and customizing a different `AudioStreamWAV` to be replaced by the skipped `AudioStreamWAV`.

**Does not work:** Skipping a `CompressedTexture2D` and customizing a different `CompressedTexture2D` to be replaced by the skipped `CompressedTexture2D`.

~~This is important functionality for porting because it allows the developer to, for example, replace existing PC-specific textures (such as an Xbox controller diagram) with mobile-specific textures (such as a touch-screen controls diagram). This functionality is needed to fully implement https://github.com/godotengine/godot-proposals/issues/10051 as an add-on for all resource types, including textures.~~ (**Update:** there is a workaround, see my [next comment](https://github.com/godotengine/godot/issues/94045#issuecomment-2214680116).)

### Explanation

When a resource is customized in `EditorExportPlugin` , a new `.res` file is added to the `exported` folder. For something like `AudioStreamWAV`, this will contain all of the resource data, so it doesn't matter if the source resource data is skipped because a full copy is made into the newly customized resource.

...But for a `CompressedTexture2D` resource, the full resource data is not copied. Instead, the new `.res` file will simply point to a `.ctex` file inside of the `imported` folder. So if this source texture is skipped, it will no be copied to the `imported` folder and this customized resource will now be invalid.

### Development Status

I'm looking into a fix for this, but I would appreciate any thoughts that others might have on how to correctly solve this.

I don't see this as a regression in any way. It's just a very specific interaction that was not fully addressed when texture skipping was introduced in PR #93878.

### Steps to reproduce

Create an `EditorExportPlugin` with something like this:
``` GDScript
func _begin_customize_resources(platform: EditorExportPlatform, features: PackedStringArray) -> bool:
return true

func _customize_resource(resource: Resource, path: String) -> Resource:
if path == "res://default.svg":
return load("res://mobile.svg")
return null

func _export_file(path: String, type: String, features: PackedStringArray) -> void:
if path == "res://mobile.svg":
skip()
```
...And then export a project that uses `res://default.svg`.

Additionally, order doesn't matter: Renaming `res://mobile.svg` to `res://amobile.svg` does not change the behaivour.

### Minimal reproduction project (MRP)

[Testxport-customize-skip.zip](https://github.com/user-attachments/files/16120201/Testxport-customize-skip.zip)

Contributor guide

Open the contributing guide

Research direction

Start with the EditorExportPlugin entry points _export_file(), _customize_resource(), and skip(), then reproduce the behavior with the linked minimal reproduction project. Trace how customized CompressedTexture2D resources reference imported .ctex data, and verify that replacing a texture while skipping its source still produces a valid export without breaking the existing AudioStreamWAV behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
game-dev, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.