View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0004874 | NoesisGUI | Studio | public | 2026-03-09 13:18 | 2026-03-23 17:20 |
| Reporter | JinFox | Assigned To | sfernandez | ||
| Priority | normal | Severity | minor | ||
| Status | feedback | Resolution | open | ||
| Product Version | Studio_Beta | ||||
| Target Version | Studio_Beta | ||||
| Summary | 0004874: [Unreal] Material only appear in Studio when already manually used in XAML | ||||
| Description | Hello, I am creating this ticket to track the issue.
Thanks! | ||||
| Platform | Any | ||||
|
The following patch should fix the issue, could you try it? MaterialRegistration.patch (6,710 bytes)
Index: Private/NoesisRuntimeModule.cpp
===================================================================
--- Private/NoesisRuntimeModule.cpp (revision 16791)
+++ Private/NoesisRuntimeModule.cpp (working copy)
@@ -308,6 +308,16 @@
NoesisDestroyTypeClassForBlueprint(Blueprint);
}
+void OnAssetsAdded(TConstArrayView<FAssetData> Assets)
+{
+ NoesisRegisterMaterials(Assets);
+}
+
+void OnAssetsRemoved(TConstArrayView<FAssetData> Assets)
+{
+ NoesisUnregisterMaterials(Assets);
+}
+
void OnAssetRenamed(const FAssetData& AssetData, const FString& OldPath)
{
UObject* NewObject = AssetData.GetAsset();
@@ -973,6 +983,8 @@
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
+ AssetsAddedHandle = AssetRegistry.OnAssetsAdded().AddStatic(&OnAssetsAdded);
+ AssetsRemovedHandle = AssetRegistry.OnAssetsRemoved().AddStatic(&OnAssetsRemoved);
AssetRenamedHandle = AssetRegistry.OnAssetRenamed().AddStatic(&OnAssetRenamed);
}
#endif
@@ -1009,6 +1021,8 @@
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
+ AssetRegistry.OnAssetsAdded().Remove(AssetsAddedHandle);
+ AssetRegistry.OnAssetsRemoved().Remove(AssetsRemovedHandle);
AssetRegistry.OnAssetRenamed().Remove(AssetRenamedHandle);
FEnumEditorUtils::FEnumEditorManager::Get().RemoveListener(NotifyEnumChangedListener);
@@ -1115,6 +1129,8 @@
FDelegateHandle BlueprintPreCompileHandle;
NotifyEnumChanged* NotifyEnumChangedListener;
NotifyStructChanged* NotifyStructChangedListener;
+ FDelegateHandle AssetsAddedHandle;
+ FDelegateHandle AssetsRemovedHandle;
FDelegateHandle AssetRenamedHandle;
#endif
TSharedPtr<class IInputProcessor> InputPreProcessor;
Index: Private/NoesisTypeClass.cpp
===================================================================
--- Private/NoesisTypeClass.cpp (revision 16791)
+++ Private/NoesisTypeClass.cpp (working copy)
@@ -68,6 +68,7 @@
#include "NoesisSDK.h"
#ifdef WITH_EDITOR
+ #include "Interfaces/IPluginManager.h"
#include "NoesisSettings.h"
#endif
@@ -3804,6 +3805,109 @@
OnMaterialChanged(Material);
}
+static void GetProjectPaths(TArray<FString>& ProjectPaths)
+{
+ ProjectPaths.Add(TEXT("/Game"));
+
+ TArray<TSharedRef<IPlugin>> EnabledPlugins = IPluginManager::Get().GetEnabledPlugins();
+ for (const TSharedRef<IPlugin>& Plugin : EnabledPlugins)
+ {
+ if (Plugin->GetLoadedFrom() == EPluginLoadedFrom::Project)
+ {
+ ProjectPaths.Add(*Plugin->GetMountedAssetPath().LeftChop(1));
+ }
+ }
+}
+
+static bool IsProjectAsset(const FAssetData& AssetData, const TArray<FString>& ProjectPaths)
+{
+ bool Found = false;
+
+ FString Path = AssetData.PackagePath.ToString();
+ for (const FString& ProjectPath : ProjectPaths)
+ {
+ if (Path.StartsWith(ProjectPath))
+ {
+ Found = true;
+ break;
+ }
+ }
+
+ return Found;
+}
+
+void NoesisRegisterMaterials(TConstArrayView<FAssetData> Assets)
+{
+ Noesis::Studio::ClearTypeCache();
+
+ TArray<FString> ProjectPaths;
+ GetProjectPaths(ProjectPaths);
+
+ for (const FAssetData& AssetData : Assets)
+ {
+ if (AssetData.IsInstanceOf(UMaterialInterface::StaticClass()) &&
+ IsProjectAsset(AssetData, ProjectPaths))
+ {
+ if (UMaterialInterface* Material = Cast<UMaterialInterface>(AssetData.GetAsset()))
+ {
+ if (UMaterial* BaseMaterial = Material->GetBaseMaterial())
+ {
+ if (BaseMaterial->MaterialDomain == MD_UI ||
+ BaseMaterial->MaterialDomain == MD_PostProcess)
+ {
+ NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+ if (TypeClassPtr == nullptr)
+ {
+ Noesis::TypeClass* Type = NoesisCreateTypeClassForUMaterial(Material);
+ Noesis::Reflection::RegisterType(Type);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Noesis::Studio::PopulateTypeCache();
+}
+
+void NoesisUnregisterMaterials(TConstArrayView<FAssetData> Assets)
+{
+ Noesis::Studio::ClearTypeCache();
+
+ TArray<FString> ProjectPaths;
+ GetProjectPaths(ProjectPaths);
+
+ for (const FAssetData& AssetData : Assets)
+ {
+ if (AssetData.IsInstanceOf(UMaterialInterface::StaticClass()) &&
+ IsProjectAsset(AssetData, ProjectPaths))
+ {
+ if (UMaterialInterface* Material = Cast<UMaterialInterface>(AssetData.GetAsset()))
+ {
+ if (UMaterial* BaseMaterial = Material->GetBaseMaterial())
+ {
+ if (BaseMaterial->MaterialDomain == MD_UI ||
+ BaseMaterial->MaterialDomain == MD_PostProcess)
+ {
+ NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+ if (TypeClassPtr != nullptr)
+ {
+ NoesisTypeClass* TypeClass = *TypeClassPtr;
+ bool IsRegistered = IsTypeRegistered(TypeClass);
+ if (IsRegistered)
+ {
+ Noesis::Reflection::UnregisterNoDelete(TypeClass);
+ MaterialMap.Remove(Material);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Noesis::Studio::PopulateTypeCache();
+}
void NoesisAssetRenamed(UObject* Object, FString OldPath)
{
Noesis::Studio::ClearTypeCache();
@@ -3865,6 +3969,22 @@
}
}
}
+ else if (UMaterialInterface* Material = Cast<UMaterialInterface>(Object))
+ {
+ NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+ if (TypeClassPtr != nullptr)
+ {
+ NoesisTypeClass* TypeClass = *TypeClassPtr;
+ bool IsRegistered = IsTypeRegistered(TypeClass);
+ if (IsRegistered)
+ {
+ Noesis::Reflection::UnregisterNoDelete(TypeClass);
+ MaterialMap.Remove(Material);
+ }
+ Noesis::TypeClass* Type = NoesisCreateTypeClassForUMaterial(Material);
+ Noesis::Reflection::RegisterType(Type);
+ }
+ }
Noesis::Studio::PopulateTypeCache();
}
#endif
Index: Public/NoesisTypeClass.h
===================================================================
--- Public/NoesisTypeClass.h (revision 16791)
+++ Public/NoesisTypeClass.h (working copy)
@@ -135,6 +135,8 @@
NOESISRUNTIME_API void NoesisDestroyTypeClassForStruct(class UUserDefinedStruct*);
NOESISRUNTIME_API void NoesisDestroyTypeClassForEnum(class UEnum*);
NOESISRUNTIME_API void NoesisDestroyTypeClassForMaterial(class UMaterialInterface*);
+NOESISRUNTIME_API void NoesisRegisterMaterials(TConstArrayView<FAssetData> Assets);
+NOESISRUNTIME_API void NoesisUnregisterMaterials(TConstArrayView<FAssetData> Assets);
NOESISRUNTIME_API void NoesisAssetRenamed(UObject* Object, FString OldPath);
#endif
|
|
|
Hi Sergio, Sorry I wasn't able to come back to you sooner. I was only able to test quickly today and it seems that if I create a new Material (by duplicating an existing one, for example) it does load indefinitely. I wasn't able to look further today though so I will try again tomorrow hopefully. |
|
What do you mean? does Unreal get stuck/frozen or something similar? |
|
|
Hello Sergio, I just tested again applying the patch on beta 12 and the issue didn't occur (duplicating an existing material or deleting a material does feel a bit sluggish but it does work after a couple second of editor freeze). I just saw that however the following include was missing from the patch in NoesisTypeClass.cpp |
|
|
I commited the changes in r16873.
It could be related to Studio recalculating the internal cache of known objects (interactivity behaviors, triggers and actions, effects, brush shaders...). Are you using a debug version of our Noesis.dll? because it shouldn't take that much, unless you have tons of custom classes. |
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-03-09 13:18 | JinFox | New Issue | |
| 2026-03-09 17:04 | sfernandez | Assigned To | => sfernandez |
| 2026-03-09 17:04 | sfernandez | Status | new => assigned |
| 2026-03-09 17:04 | sfernandez | Target Version | => Studio_Beta |
| 2026-03-09 19:28 | sfernandez | Note Added: 0012011 | |
| 2026-03-09 19:28 | sfernandez | File Added: MaterialRegistration.patch | |
| 2026-03-09 19:28 | sfernandez | Status | assigned => feedback |
| 2026-03-18 16:43 | JinFox | Note Added: 0012060 | |
| 2026-03-18 16:43 | JinFox | Status | feedback => assigned |
| 2026-03-20 10:12 | sfernandez | Status | assigned => feedback |
| 2026-03-20 10:12 | sfernandez | Note Added: 0012074 | |
| 2026-03-20 10:12 | sfernandez | Note Edited: 0012074 | |
| 2026-03-20 10:12 | sfernandez | Note Edited: 0012074 | |
| 2026-03-23 15:19 | JinFox | Note Added: 0012089 | |
| 2026-03-23 15:19 | JinFox | Status | feedback => assigned |
| 2026-03-23 17:19 | sfernandez | Status | assigned => feedback |
| 2026-03-23 17:19 | sfernandez | Note Added: 0012090 | |
| 2026-03-23 17:20 | sfernandez | Note Edited: 0012090 | |
| 2026-03-23 17:20 | sfernandez | Note Edited: 0012090 |