mirror of
https://github.com/Eragon-Brisingr/UShaderLab.git
synced 2026-09-15 14:54:36 +00:00
Init repo
This commit is contained in:
@@ -35,7 +35,7 @@ UPackage* FShaderLabMaterialRegistry::GetPackage()
|
||||
return Package;
|
||||
}
|
||||
|
||||
FString FShaderLabMaterialRegistry::MakeObjectName(const FString& ShaderName)
|
||||
FName FShaderLabMaterialRegistry::MakeObjectName(const FString& ShaderName)
|
||||
{
|
||||
FString Out;
|
||||
Out.Reserve(ShaderName.Len());
|
||||
@@ -47,12 +47,12 @@ FString FShaderLabMaterialRegistry::MakeObjectName(const FString& ShaderName)
|
||||
{
|
||||
Out = TEXT("Unnamed");
|
||||
}
|
||||
return Out;
|
||||
return FName(*Out);
|
||||
}
|
||||
|
||||
FString FShaderLabMaterialRegistry::MakeObjectPath(const FString& ShaderName)
|
||||
{
|
||||
return FString::Printf(TEXT("%s.%s"), GShaderLabPackageName, *MakeObjectName(ShaderName));
|
||||
return FString::Printf(TEXT("%s.%s"), GShaderLabPackageName, *MakeObjectName(ShaderName).ToString());
|
||||
}
|
||||
|
||||
UMaterial* FShaderLabMaterialRegistry::FindMaterial(const FString& ShaderName) const
|
||||
@@ -61,28 +61,29 @@ UMaterial* FShaderLabMaterialRegistry::FindMaterial(const FString& ShaderName) c
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return FindObject<UMaterial>(Package, *MakeObjectName(ShaderName));
|
||||
return FindObject<UMaterial>(Package, *MakeObjectName(ShaderName).ToString());
|
||||
}
|
||||
|
||||
UMaterial* FShaderLabMaterialRegistry::RegisterFromModel(const FShaderLabModel& Model)
|
||||
{
|
||||
UPackage* Pkg = GetPackage();
|
||||
const FString ObjName = MakeObjectName(Model.ShaderName);
|
||||
const FName ObjName = MakeObjectName(Model.ShaderName);
|
||||
|
||||
// Contract: a material's identity is its file name. Two different source files that sanitize to the
|
||||
// same object name are a hard error (would otherwise silently clobber each other / break MIC refs).
|
||||
// The key is an FName, so the collision check is case-insensitive — matching UObject name semantics.
|
||||
if (const FShaderLabModel* Existing = RegisteredModels.Find(ObjName))
|
||||
{
|
||||
if (!FPaths::IsSamePath(Existing->SourceFilePath, Model.SourceFilePath))
|
||||
{
|
||||
UE_LOG(LogShaderLabRegistry, Error,
|
||||
TEXT("ShaderLab: duplicate material name '%s' from '%s' and '%s' — rename one file."),
|
||||
*ObjName, *Existing->SourceFilePath, *Model.SourceFilePath);
|
||||
*ObjName.ToString(), *Existing->SourceFilePath, *Model.SourceFilePath);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
UMaterial* Material = FindObject<UMaterial>(Pkg, *ObjName);
|
||||
UMaterial* Material = FindObject<UMaterial>(Pkg, *ObjName.ToString());
|
||||
const bool bNewlyCreated = (Material == nullptr);
|
||||
if (bNewlyCreated)
|
||||
{
|
||||
@@ -90,16 +91,18 @@ UMaterial* FShaderLabMaterialRegistry::RegisterFromModel(const FShaderLabModel&
|
||||
// (RF_Standalone alone is not a GC root in a cooked runtime), which removes its entry from
|
||||
// the IoStore script-object table (RemoveUnreachableScriptObjects) and makes cooked Material
|
||||
// Instances that reference it resolve their Parent to null -> fall back to the default material.
|
||||
Material = NewObject<UMaterial>(Pkg, FName(*ObjName), RF_Public | RF_Standalone | RF_MarkAsRootSet);
|
||||
Material = NewObject<UMaterial>(Pkg, ObjName, RF_Public | RF_Standalone | RF_MarkAsRootSet);
|
||||
}
|
||||
|
||||
RegisteredModels.FindOrAdd(ObjName) = Model;
|
||||
|
||||
// Register with the loading system so imports to "/Script/UShaderLab.<ObjName>" from other
|
||||
// packages resolve to this in-memory object even if requested mid async-load.
|
||||
// packages resolve to this in-memory object — required for cooked builds, where the linker
|
||||
// resolves a Material Instance's parent import through this registration (without it the parent
|
||||
// resolves to null and the instance falls back to the default material).
|
||||
NotifyRegistrationEvent(
|
||||
FName(GShaderLabPackageName),
|
||||
FName(*ObjName),
|
||||
ObjName,
|
||||
ENotifyRegistrationType::NRT_NoExportObject,
|
||||
ENotifyRegistrationPhase::NRP_Finished,
|
||||
nullptr,
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
UPackage* GetPackage();
|
||||
|
||||
/** Deterministic, UObject-safe object name for a shader name like "ShaderLab/RustyMetal". */
|
||||
static FString MakeObjectName(const FString& ShaderName);
|
||||
static FName MakeObjectName(const FString& ShaderName);
|
||||
|
||||
/** Full object path, e.g. "/Script/UShaderLab.ShaderLab_RustyMetal". */
|
||||
static FString MakeObjectPath(const FString& ShaderName);
|
||||
@@ -48,10 +48,10 @@ public:
|
||||
FOnShaderLabBuildMaterial& OnBuildMaterial() { return BuildMaterialDelegate; }
|
||||
|
||||
/** Models registered so far, keyed by object name (used by the instance factory picker and the example/validation commandlets). */
|
||||
const TMap<FString, FShaderLabModel>& GetRegisteredModels() const { return RegisteredModels; }
|
||||
const TMap<FName, FShaderLabModel>& GetRegisteredModels() const { return RegisteredModels; }
|
||||
|
||||
private:
|
||||
UPackage* Package = nullptr;
|
||||
FOnShaderLabBuildMaterial BuildMaterialDelegate;
|
||||
TMap<FString, FShaderLabModel> RegisteredModels;
|
||||
TMap<FName, FShaderLabModel> RegisteredModels;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Engine/Engine.h"
|
||||
#include "IDirectoryWatcher.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "MaterialShared.h"
|
||||
#include "Materials/Material.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
@@ -31,7 +32,15 @@ namespace
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Recompile for rendering / editor preview (async).
|
||||
|
||||
// Recompile the base AND propagate to everything that depends on it. A bare PostEditChange
|
||||
// recompiles only the base shell; the instances carry their own static-permutation shader maps
|
||||
// (and the level components render those), so on a hot-reload they must be recompiled and
|
||||
// re-pushed too. FMaterialUpdateContext does exactly that on scope exit: recompile the listed
|
||||
// material, then recache every dependent instance and refresh the components/viewports using it.
|
||||
FMaterialUpdateContext UpdateContext;
|
||||
UpdateContext.AddMaterial(&Material);
|
||||
Material.PreEditChange(nullptr);
|
||||
Material.PostEditChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ namespace
|
||||
|
||||
// Collect the registered in-memory base materials (sorted by name for a stable layout).
|
||||
TArray<UMaterial*> Bases;
|
||||
TArray<FString> Names;
|
||||
TArray<FName> Names;
|
||||
Registry.GetRegisteredModels().GenerateKeyArray(Names);
|
||||
Names.Sort();
|
||||
for (const FString& Name : Names)
|
||||
Names.Sort([](const FName& A, const FName& B) { return A.Compare(B) < 0; });
|
||||
for (const FName& Name : Names)
|
||||
{
|
||||
if (UMaterial* Base = Registry.FindMaterial(Name))
|
||||
if (UMaterial* Base = Registry.FindMaterial(Name.ToString()))
|
||||
{
|
||||
Bases.Add(Base);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user