This question was created in reference to: [What is the recommended approach for importing inter-dependent assets? (when extending the Interchange [Content removed]
Hi there,
This is a non-urgent question whose resolution will allow me to implement a non-urgent Quality of Life feature for our team.
I will use a similar example situation as in the referenced post:
Our file uses the .abba extension…
I have aUInterchangeAbbaTranslator that creates a UInterchangeAbbaAssetNode
I have a UInterchangeAbbaPipeline that creates a UInterchangeAbbaAssetFactoryNode and a UInterchangeAbbaActorBlueprintFactoryNode
I have a UInterchangeAbbaAssetFactory that creates a UAbbaAsset
I have a UInterchangeAbbaActorBlueprintFactory that creates a UAbbaActorBlueprint
Additionally, I have a UAssetDefinition_AbbaAsset that enables the Reimport Asset Context Action, and use an identical copy of UStaticMesh::AssetImportData as UAbbaAsset::AssetImportData along with the associated UInterchangeAbbaAssetFactory functions that manipulate it (GetSourceFilenames etc.) to facilitate the reimport action.
My Desired Functionality
When I right-click on a UAbbaAsset in the content browser, and click Reimport, I would like the associated UAbbaActorBlueprint to also be reimported.
My Question
How would you recommend implementing this?
What I’ve Tried Already
The key point in the code-path is UE::Interchange::FTaskImportObject_GameThread::Execute
Factory is, as desired, initialized to an instance of UInterchangeAbbaActorBlueprintFactory (The previous code-path goes through UInterchangeAbbaPipeline, which creates a UInterchangeAbbaActorBlueprintFactoryNode)
ObjectToReimport, contrary to my requirements, is initialized to the UAbbaAsset on which I right-clicked. This prevents the reimport of the associated UAbbaActorBlueprint, as the UInterchangeAbbaActorBlueprintFactory obviously cannot handle a reimport of that asset class.
I am reluctant to store a TObjectPtr<UAbbaActorBlueprint> in UAbbaAsset.
We are considering this exact same feature for a future release.
By looking at FFactoryCommon::GetObjectToReimport, you can see that if the call to Factory->GetObjectToReimport returns a pointer different than the asset specified for reimport, it immediately returns that pointer.
Consequently, if you override UInterchangeFactoryBase::GetObjectToReimport in UInterchangeAbbaAssetFactory to return the blueprint asset when ReimportObject is pointing to a Abba asset and the call to ShouldForceNodeReimport on the factory node is returning true. Obviously, you will have to call SetForceNodeReimport() on the factory node of the blueprint in UInterchangeAbbaPipeline if a reimport is in progress. See CacheContextParam for that information.
We have not implemented this yet but this is what we are planning to work from.
First of all, I made a mistake. You should not override the GetObjectToReimport of the UInterchangeAbbaAssetFactory but of the UInterchangeAbbaActorBlueprintFactory class. This is the one which should return the UAbbaActorBlueprint asset that you want to reimport as a dependent.
Here is what I suggest you do in the overridden GetObjectToReimport:
Check whether the object to reimport is a UAbbaAsset. Stating the obvious here.
Make sure that the given FactoryNode is enabled. It should. But, worth checking. You can break the const and enable it. At least until we implement the proper API to import assets which a reimported asset depends on.
Check whether the asset defined with the given PackageName and AssetName parameters exists and is a UAbbaActorBlueprint. It should. Then return that pointer instead of the given ReimportObject.
Based on the code, that should do the trick.
Let me know how it goes.
Regards,
Jean-Luc
P.S.: I am short on time and cannot test my suggestion. My apologies.
It does not change anything. When you reimport an asset, the file used for the reimport is translated and the translated content is processed by the pipeline. The same steps as an import. Then it is how the factories are invoked that differs between import and reimport. On reimport, only factory nodes related to the reimported object that are processed by their corresponding factory. This is why you need to override GetObjectToReimport on UInterchangeAbbaActorBlueprintFactory. It will tell the Interchange manager that for the UAbbaAsset being reimported it should also reimport the associated UAbbaActorBlueprint.
Since my last reply, I implemented the same logic for two objects which had similar relationship.
> if you override UInterchangeFactoryBase::GetObjectToReimport in UInterchangeAbbaAssetFactory to return the blueprint asset when ReimportObject is pointing to a Abba asset
I will assume that, by this statement, you mean that overriding this function is indeed the recommended way to implement my desired functionality.
My next question is how you recommend “finding” the associated UAbbaActorBlueprint in a robust way (I’m moreso looking for guidance on how to tangibly “link” these interdependent assets)
I’m reluctant to store a pointer in AbbaAsset to AbbaActorBlueprint
Searching by asset name is vulnerable as a user could rename the AbbaActorBlueprint
I could store a pointer in AbbaActorBlueprint to AbbaAsset.
Is this the best way? Or is there some more sophisticated way I’m unaware of?