Exemplo n.º 1
0
void ReattachMaterials(const TArray<FString>& Args)
{
	FMaterialUpdateContext MaterialUpdateContext;

	UE_LOG(LogConsoleResponse, Display, TEXT("Reattach.Materials:"));

	// Clear the parents out of combination material
	for( TObjectIterator<UMaterial> MaterialIt; MaterialIt; ++MaterialIt )
	{
		if(Args.Num() == 1)
		{
			UE_LOG(LogConsoleResponse, Display, TEXT("   %s"), *MaterialIt->GetName());

			if(MaterialIt->GetName() == Args[0])
			{
				MaterialUpdateContext.AddMaterial(*MaterialIt);
			}
		}
	}
	UE_LOG(LogConsoleResponse, Display, TEXT(""));
}
void UMaterialParameterCollection::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	// If the array counts have changed, an element has been added or removed, and we need to update the uniform buffer layout,
	// Which also requires recompiling any referencing materials
	if (ScalarParameters.Num() != PreviousScalarParameters.Num()
		|| VectorParameters.Num() != PreviousVectorParameters.Num())
	{
		// Limit the count of parameters to fit within uniform buffer limits
		const uint32 MaxScalarParameters = 1024;

		if (ScalarParameters.Num() > MaxScalarParameters)
		{
			ScalarParameters.RemoveAt(MaxScalarParameters, ScalarParameters.Num() - MaxScalarParameters);
		}

		const uint32 MaxVectorParameters = 1024;

		if (VectorParameters.Num() > MaxVectorParameters)
		{
			VectorParameters.RemoveAt(MaxVectorParameters, VectorParameters.Num() - MaxVectorParameters);
		}

		// Generate a new Id so that unloaded materials that reference this collection will update correctly on load
		StateId = FGuid::NewGuid();

		// Update the uniform buffer layout
		CreateBufferStruct();

		// Recreate each instance of this collection
		for (TObjectIterator<UWorld> It; It; ++It)
		{
			UWorld* CurrentWorld = *It;
			CurrentWorld->AddParameterCollectionInstance(this, false);
		}

		// Build set of changed parameter names
		TSet<FName> ParameterNames;
		for (const FCollectionVectorParameter& Param : PreviousVectorParameters)
		{
			ParameterNames.Add(Param.ParameterName);
		}

		for (const FCollectionScalarParameter& Param : PreviousScalarParameters)
		{
			ParameterNames.Add(Param.ParameterName);
		}

		for (const FCollectionVectorParameter& Param : VectorParameters)
		{
			ParameterNames.Remove(Param.ParameterName);
		}

		for (const FCollectionScalarParameter& Param : ScalarParameters)
		{
			ParameterNames.Remove(Param.ParameterName);
		}

		// Create a material update context so we can safely update materials using this parameter collection.
		{
			FMaterialUpdateContext UpdateContext;

			// Go through all materials in memory and recompile them if they use this material parameter collection
			for (TObjectIterator<UMaterial> It; It; ++It)
			{
				UMaterial* CurrentMaterial = *It;

				bool bRecompile = false;

				// Preview materials often use expressions for rendering that are not in their Expressions array, 
				// And therefore their MaterialParameterCollectionInfos are not up to date.
				if (CurrentMaterial->bIsPreviewMaterial)
				{
					bRecompile = true;
				}
				else
				{
					for (int32 FunctionIndex = 0; FunctionIndex < CurrentMaterial->MaterialParameterCollectionInfos.Num() && !bRecompile; FunctionIndex++)
					{
						if (CurrentMaterial->MaterialParameterCollectionInfos[FunctionIndex].ParameterCollection == this)
						{
							TArray<UMaterialExpressionCollectionParameter*> CollectionParameters;
							CurrentMaterial->GetAllExpressionsInMaterialAndFunctionsOfType(CollectionParameters);
							for (UMaterialExpressionCollectionParameter* CollectionParameter : CollectionParameters)
							{
								if (ParameterNames.Contains(CollectionParameter->ParameterName))
								{
									bRecompile = true;
									break;
								}
							}
						}
					}
				}

				if (bRecompile)
				{
					UpdateContext.AddMaterial(CurrentMaterial);

					// Propagate the change to this material
					CurrentMaterial->PreEditChange(NULL);
					CurrentMaterial->PostEditChange();
					CurrentMaterial->MarkPackageDirty();
				}
			}
		}
	}

	// Update each world's scene with the new instance, and update each instance's uniform buffer to reflect the changes made by the user
	for (TObjectIterator<UWorld> It; It; ++It)
	{
		UWorld* CurrentWorld = *It;
		CurrentWorld->UpdateParameterCollectionInstances(true);
	}

	PreviousScalarParameters.Empty();
	PreviousVectorParameters.Empty();

	Super::PostEditChangeProperty(PropertyChangedEvent);
}
Exemplo n.º 3
0
void UTexture::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	SetLightingGuid();

	// Determine whether any property that requires recompression of the texture, or notification to Materials has changed.
	bool RequiresNotifyMaterials = false;

	UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
	if( PropertyThatChanged )
	{
		FString PropertyName = *PropertyThatChanged->GetName();
		if (FCString::Stricmp(*PropertyName, TEXT("CompressionSettings")) == 0)
		{
			RequiresNotifyMaterials = true;
		}

		bool bPreventSRGB = (CompressionSettings == TC_Alpha || CompressionSettings == TC_Normalmap || CompressionSettings == TC_Masks || CompressionSettings == TC_HDR);		
		if(bPreventSRGB && SRGB == true)
		{
			SRGB = false;
		}
	}

	NumCinematicMipLevels = FMath::Max<int32>( NumCinematicMipLevels, 0 );

	if( (PropertyChangedEvent.ChangeType & EPropertyChangeType::Interactive) == 0 )
	{
		// Update the texture resource. This will recache derived data if necessary
		// which may involve recompressing the texture.
		UpdateResource();
	}

	// Notify any loaded material instances if changed our compression format
	if (RequiresNotifyMaterials)
	{
		TArray<UMaterialInterface*> MaterialsThatUseThisTexture;

		// Create a material update context to safely update materials.
		{
			FMaterialUpdateContext UpdateContext;

			// Notify any material that uses this texture
			TSet<UMaterial*> BaseMaterialsThatUseThisTexture;
			for (TObjectIterator<UMaterialInterface> It; It; ++It)
			{
				UMaterialInterface* MaterialInterface = *It;
				if (DoesMaterialUseTexture(MaterialInterface,this))
				{
					MaterialsThatUseThisTexture.Add(MaterialInterface);

					// This is a bit tricky. We want to make sure all materials using this texture are
					// updated. Materials are always updated. Material instances may also have to be
					// updated and if they have static permutations their children must be updated
					// whether they use the texture or not! The safe thing to do is to add the instance's
					// base material to the update context causing all materials in the tree to update.
					BaseMaterialsThatUseThisTexture.Add(MaterialInterface->GetMaterial());
				}
			}

			// Go ahead and update any base materials that need to be.
			for (TSet<UMaterial*>::TConstIterator It(BaseMaterialsThatUseThisTexture); It; ++It)
			{
				UpdateContext.AddMaterial(*It);
				(*It)->PostEditChange();
			}
		}

		// Now that all materials and instances have updated send necessary callbacks.
		for (int32 i = 0; i < MaterialsThatUseThisTexture.Num(); ++i)
		{
			FEditorSupportDelegates::MaterialTextureSettingsChanged.Broadcast(MaterialsThatUseThisTexture[i]);
		}
	}
		
#if WITH_EDITORONLY_DATA
	// any texture that is referencing this texture as AssociatedNormalMap needs to be informed
	{
		TArray<UTexture*> TexturesThatUseThisTexture;

		for (TObjectIterator<UTexture> It; It; ++It)
		{
			UTexture* Tex = *It;

			if(Tex != this && Tex->CompositeTexture == this && Tex->CompositeTextureMode != CTM_Disabled)
			{
				TexturesThatUseThisTexture.Add(Tex);
			}
		}
		for (int32 i = 0; i < TexturesThatUseThisTexture.Num(); ++i)
		{
			TexturesThatUseThisTexture[i]->PostEditChange();
		}
	}
#endif
}
Exemplo n.º 4
0
void UTexture::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);

	SetLightingGuid();

	// Determine whether any property that requires recompression of the texture, or notification to Materials has changed.
	bool RequiresNotifyMaterials = false;
	bool DeferCompressionWasEnabled = false;

	UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
	if( PropertyThatChanged )
	{
		static const FName CompressionSettingsName("CompressionSettings");
		static const FName LODGroupName("LODGroup");
		static const FName DeferCompressionName("DeferCompression");
#if WITH_EDITORONLY_DATA
		static const FName MaxTextureSizeName("MaxTextureSize");
#endif // #if WITH_EDITORONLY_DATA

		const FName PropertyName = PropertyThatChanged->GetFName();
		if (PropertyName == CompressionSettingsName || PropertyName == LODGroupName)
		{
			RequiresNotifyMaterials = true;
		}
		else if (PropertyName == DeferCompressionName)
		{
			DeferCompressionWasEnabled = DeferCompression;
		}
#if WITH_EDITORONLY_DATA
		else if (PropertyName == MaxTextureSizeName)
		{
			if (MaxTextureSize <= 0)
			{
				MaxTextureSize = 0;
			}
			else
			{
				MaxTextureSize = FMath::Min<int32>(FMath::RoundUpToPowerOfTwo(MaxTextureSize), GetMaximumDimension());
			}
		}
#endif // #if WITH_EDITORONLY_DATA

		bool bPreventSRGB = (CompressionSettings == TC_Alpha || CompressionSettings == TC_Normalmap || CompressionSettings == TC_Masks || CompressionSettings == TC_HDR || CompressionSettings == TC_HDR_Compressed);
		if(bPreventSRGB && SRGB == true)
		{
			SRGB = false;
		}
	}
	else
	{
		FMaterialUpdateContext UpdateContext;
		// Update any material that uses this texture
		TSet<UMaterial*> BaseMaterialsThatUseThisTexture;
		for (TObjectIterator<UMaterialInterface> It; It; ++It)
		{
			UMaterialInterface* MaterialInterface = *It;
			if (DoesMaterialUseTexture(MaterialInterface, this))
			{
				UMaterial *Material = MaterialInterface->GetMaterial();
				bool MaterialAlreadyCompute = false;
				BaseMaterialsThatUseThisTexture.Add(Material, &MaterialAlreadyCompute);
				if (!MaterialAlreadyCompute)
				{
					UpdateContext.AddMaterial(Material);
					if (Material->IsTextureForceRecompileCacheRessource(this))
					{
						Material->UpdateMaterialShaderCacheAndTextureReferences();
					}
				}
			}
		}
		//If the DDC key was different the material is already recompile here
		RequiresNotifyMaterials = false;
	}

	NumCinematicMipLevels = FMath::Max<int32>( NumCinematicMipLevels, 0 );

	// Don't update the texture resource if we've turned "DeferCompression" on, as this 
	// would cause it to immediately update as an uncompressed texture
	if( !DeferCompressionWasEnabled && (PropertyChangedEvent.ChangeType & EPropertyChangeType::Interactive) == 0 )
	{
		// Update the texture resource. This will recache derived data if necessary
		// which may involve recompressing the texture.
		UpdateResource();
	}

	// Notify any loaded material instances if changed our compression format
	if (RequiresNotifyMaterials)
	{
		TArray<UMaterialInterface*> MaterialsThatUseThisTexture;

		// Create a material update context to safely update materials.
		{
			FMaterialUpdateContext UpdateContext;

			// Notify any material that uses this texture
			TSet<UMaterial*> BaseMaterialsThatUseThisTexture;
			for (TObjectIterator<UMaterialInterface> It; It; ++It)
			{
				UMaterialInterface* MaterialInterface = *It;
				if (DoesMaterialUseTexture(MaterialInterface,this))
				{
					MaterialsThatUseThisTexture.Add(MaterialInterface);

					// This is a bit tricky. We want to make sure all materials using this texture are
					// updated. Materials are always updated. Material instances may also have to be
					// updated and if they have static permutations their children must be updated
					// whether they use the texture or not! The safe thing to do is to add the instance's
					// base material to the update context causing all materials in the tree to update.
					BaseMaterialsThatUseThisTexture.Add(MaterialInterface->GetMaterial());
				}
			}

			// Go ahead and update any base materials that need to be.
			for (TSet<UMaterial*>::TConstIterator It(BaseMaterialsThatUseThisTexture); It; ++It)
			{
				UpdateContext.AddMaterial(*It);
				(*It)->PostEditChange();
			}
		}

		// Now that all materials and instances have updated send necessary callbacks.
		for (int32 i = 0; i < MaterialsThatUseThisTexture.Num(); ++i)
		{
			FEditorSupportDelegates::MaterialTextureSettingsChanged.Broadcast(MaterialsThatUseThisTexture[i]);
		}
	}
		
#if WITH_EDITORONLY_DATA
	// any texture that is referencing this texture as AssociatedNormalMap needs to be informed
	{
		TArray<UTexture*> TexturesThatUseThisTexture;

		for (TObjectIterator<UTexture> It; It; ++It)
		{
			UTexture* Tex = *It;

			if(Tex != this && Tex->CompositeTexture == this && Tex->CompositeTextureMode != CTM_Disabled)
			{
				TexturesThatUseThisTexture.Add(Tex);
			}
		}
		for (int32 i = 0; i < TexturesThatUseThisTexture.Num(); ++i)
		{
			TexturesThatUseThisTexture[i]->PostEditChange();
		}
	}
#endif
}