Fix thumbnail export: stale camera angle, redirector crash, opaque transparent background - #5
Open
GatheredSatyr53 wants to merge 1 commit into
Conversation
Three independent defects in the "Export to Texture" action, all in FThumbnailToTextureToolModule::ExecuteSaveThumbnailAsTexture. 1. Exported texture always used the default camera angle. With the default settings (neither UseTransparentBackground nor UseCustomBackgroundMaterial) the export never rendered anything - it read the thumbnail cached inside the asset's .uasset via ThumbnailTools::LoadThumbnailsFromPackage. That cached copy is only regenerated on save when it is missing, empty or dirty, and rotating a thumbnail in the Content Browser only mutates the asset's USceneThumbnailInfo; it calls MarkPackageDirty() on the info object, never marking the cached image itself dirty. The cache therefore keeps whatever angle was baked in at first save - normally the default one - while the Content Browser shows a live render and looks correct. Render the thumbnail on demand through ThumbnailTools::RenderThumbnail instead, which is the same path the Content Browser uses, so the user's orbit is honoured. 2. Editor crashed when the target name was occupied by a redirector. Deleting or moving a previously exported texture can leave an UObjectRedirector at that path. NewObject<UTexture2D>() with an explicit name then hit the fatal "Cannot replace existing object of a different class" in StaticAllocateObject and took the editor down. Check the path first: move a redirector aside into the transient package (it is only a forwarding stub, and saving the package drops it), and refuse to overwrite an unrelated asset of some other class - log an error and skip instead. 3. Transparent background came out opaque white. Transparency is chroma keyed against the background material's "Color" parameter, but the render target was cleared to a hardcoded FLinearColor::White. Any pixel the background geometry did not cover kept that white, never matched the key colour, and stayed opaque. Resolve the key colour once and use it for both the clear colour and the cutoff, so the two cannot drift apart. The return value of GetVectorParameterValue is now honoured as well - FLinearColor's default constructor leaves the channels uninitialised, so ignoring it risked keying against stack garbage. Also in passing: - Drop ObjectFullName/ObjectFullNames, dead once the cache read is gone. - Use continue rather than return when an asset name is unusable, so one bad entry no longer abandons the rest of the selection. - Collapse a row-by-row copy that used the same offset for source and destination, so it only ever copied each row onto itself, into the plain memcpy it always was. Verified with RunUAT BuildPlugin against UE 5.7: BUILD SUCCESSFUL. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three independent defects in the "Export to Texture" action, all in
FThumbnailToTextureToolModule::ExecuteSaveThumbnailAsTexture. They surfaced in one session while exporting static mesh thumbnails, but none of them are specific to static meshes.1. Exported texture always used the default camera angle
With the default settings (neither
UseTransparentBackgroundnorUseCustomBackgroundMaterial) the export never rendered anything. It read the thumbnail cached inside the asset's.uassetthroughThumbnailTools::LoadThumbnailsFromPackage.That cached copy is only regenerated on save when it is missing, empty or dirty (
UnrealEdSrv.cpp, theObjectsMissingThumbnailsbranch). Rotating a thumbnail in the Content Browser goes throughSAssetThumbnailEditModeTools::OnMouseMove, which mutates the asset'sUSceneThumbnailInfoand, on mouse up, callsMarkPackageDirty()on that info object - the cached image itself is never marked dirty. So the cache keeps whatever angle was baked in at first save, normally the default one.The Content Browser hides this, because static meshes are drawn there live via
UStaticMeshThumbnailRendererand the cache is ignored. The export took the cache, hence the mismatch.Now the thumbnail is rendered on demand with
ThumbnailTools::RenderThumbnail(..., AlwaysFlush, ...)- the same path the Content Browser uses - so the orbit the user set is honoured. Background appearance is unchanged, since this still goes through the engine's own renderer.2. Editor crashed when the target name was occupied by a redirector
Deleting or moving a previously exported texture can leave an
UObjectRedirectorat that path.NewObject<UTexture2D>()with an explicit name then hit a fatal error inStaticAllocateObjectand took the whole editor down:The path is now checked before allocating:
UTexture2Dstill gets replaced, as before.3. Transparent background came out opaque white
Transparency is chroma keyed against the background material's
Colorparameter, but the render target was cleared to a hardcodedFLinearColor::White.BackgroundMaterialNoShadowkeys on magenta(1, 0, 1, 1), so any pixel the background geometry did not cover kept the white clear colour, never matched the key, and stayed fully opaque.The key colour is now resolved once and used for both the clear colour and the alpha cutoff, so the two cannot drift apart. The return value of
GetVectorParameterValueis honoured as well:FLinearColor's default constructor leaves the channels uninitialised (FLinearColor() = default;), so ignoring it risked keying against stack garbage if the parameter were ever renamed.Also in passing
ObjectFullName/ObjectFullNames, dead once the cache read is gone.continuerather thanreturnwhen an asset name is unusable, so one bad entry no longer abandons the rest of the selection.memcpyit always was.Testing
Built with
RunUAT BuildPluginagainst UE 5.7: BUILD SUCCESSFUL, no new warnings. The only warning in the log is pre-existing (CustomThumbnailHelpers.cpp:524,UStaticMesh::ThumbnailInfodeprecated in 5.7 in favour ofGetThumbnailInfo()); left alone to keep this PR scoped.Note this branch is cut from
mainand does not include the missing-include fix in #4; the two are independent. A non-unity build such asBuildPluginneeds #4 as well, which was applied locally for the verification above.Co-authored with Claude Opus 5.
🤖 Generated with Claude Code