/** * Extract the material names from the Apex Render Mesh contained within an Apex Destructible Asset. * @param ImportData - SkeletalMesh import data into which we are extracting information * @param ApexDestructibleAsset - the Apex Destructible Asset */ static void ImportMaterialsForSkelMesh(FSkeletalMeshImportData &ImportData, const NxDestructibleAsset& ApexDestructibleAsset) { physx::PxU32 SubmeshCount = 0; // Get the submesh count from the Destructible Asset's Render Mesh const physx::NxRenderMeshAsset* ApexRenderMesh = ApexDestructibleAsset.getRenderMeshAsset(); if (ApexRenderMesh != NULL) { SubmeshCount = ApexRenderMesh->getSubmeshCount(); } if( SubmeshCount == 0 ) { // No material info, create a default material slot ++SubmeshCount; UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("No material associated with skeletal mesh - using default")); } else { UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("Using default materials for material slot")); } // Create material slots UMaterial* DefaultMaterial = UMaterial::GetDefaultMaterial(MD_Surface); if (DefaultMaterial) { for (uint32 MatIndex = 0; MatIndex < SubmeshCount; MatIndex++) { ImportData.Materials.Add( VMaterial() ); ImportData.Materials.Last().Material = DefaultMaterial; ImportData.Materials.Last().MaterialImportName = DefaultMaterial->GetName(); } } }
FLinearColor UMaterialGraphNode::GetNodeTitleColor() const { UMaterial* Material = CastChecked<UMaterialGraph>(GetGraph())->Material; // Generate title color FColor TitleColor = MaterialExpression->BorderColor; TitleColor.A = 255; if (bIsErrorExpression) { // Outline expressions that caused errors in red TitleColor = FColor( 255, 0, 0 ); } else if (bIsCurrentSearchResult) { TitleColor = FColor( 64, 64, 255 ); } else if (bIsPreviewExpression) { // If we are currently previewing a node, its border should be the preview color. TitleColor = FColor( 70, 100, 200 ); } else if (UMaterial::IsParameter(MaterialExpression)) { if (Material->HasDuplicateParameters(MaterialExpression)) { TitleColor = FColor( 0, 255, 255 ); } else { TitleColor = FColor( 0, 128, 128 ); } } else if (UMaterial::IsDynamicParameter(MaterialExpression)) { if (Material->HasDuplicateDynamicParameters(MaterialExpression)) { TitleColor = FColor( 0, 255, 255 ); } else { TitleColor = FColor( 0, 128, 128 ); } } return FLinearColor(TitleColor); }
void FMaterialTrackEditor::AddVectorParameter( FGuid ObjectBinding, UMovieSceneMaterialTrack* MaterialTrack, FName ParameterName ) { UMovieSceneSequence* MovieSceneSequence = GetMovieSceneSequence(); float KeyTime = GetTimeForKey( MovieSceneSequence ); UMaterial* Material = GetMaterialForTrack( ObjectBinding, MaterialTrack ); if ( Material != nullptr ) { const FScopedTransaction Transaction( LOCTEXT( "AddVectorParameter", "Add vector parameter" ) ); FLinearColor ParameterValue; Material->GetVectorParameterValue( ParameterName, ParameterValue ); MaterialTrack->Modify(); for ( UMovieSceneSection* Section : MaterialTrack->GetAllSections() ) { Section->Modify(); } MaterialTrack->AddVectorParameterKey( ParameterName, KeyTime, ParameterValue ); } NotifyMovieSceneDataChanged(); }
TSharedRef<SWidget> FMaterialTrackEditor::OnGetAddParameterMenuContent( FGuid ObjectBinding, UMovieSceneMaterialTrack* MaterialTrack ) { FMenuBuilder AddParameterMenuBuilder( true, nullptr ); UMaterial* Material = GetMaterialForTrack( ObjectBinding, MaterialTrack ); if ( Material != nullptr ) { TArray<FParameterNameAndAction> ParameterNamesAndActions; // Collect scalar parameters. TArray<FName> ScalarParameterNames; TArray<FGuid> ScalarParmeterGuids; Material->GetAllScalarParameterNames( ScalarParameterNames, ScalarParmeterGuids ); for ( const FName& ScalarParameterName : ScalarParameterNames ) { FUIAction AddParameterMenuAction( FExecuteAction::CreateSP( this, &FMaterialTrackEditor::AddScalarParameter, ObjectBinding, MaterialTrack, ScalarParameterName ) ); FParameterNameAndAction NameAndAction( ScalarParameterName, AddParameterMenuAction ); ParameterNamesAndActions.Add(NameAndAction); } // Collect vector parameters. TArray<FName> VectorParameterNames; TArray<FGuid> VectorParmeterGuids; Material->GetAllVectorParameterNames( VectorParameterNames, VectorParmeterGuids ); for ( const FName& VectorParameterName : VectorParameterNames ) { FUIAction AddParameterMenuAction( FExecuteAction::CreateSP( this, &FMaterialTrackEditor::AddVectorParameter, ObjectBinding, MaterialTrack, VectorParameterName ) ); FParameterNameAndAction NameAndAction( VectorParameterName, AddParameterMenuAction ); ParameterNamesAndActions.Add( NameAndAction ); } // Sort and generate menu. ParameterNamesAndActions.Sort(); for ( FParameterNameAndAction NameAndAction : ParameterNamesAndActions ) { AddParameterMenuBuilder.AddMenuEntry( FText::FromName( NameAndAction.ParameterName ), FText(), FSlateIcon(), NameAndAction.Action ); } } return AddParameterMenuBuilder.MakeWidget(); }
void FBufferVisualizationData::Initialize() { if (!bIsInitialized) { if (AllowDebugViewmodes()) { check(MaterialMap.Num() == 0); FConfigSection* MaterialSection = GConfig->GetSectionPrivate( TEXT("Engine.BufferVisualizationMaterials"), false, true, GEngineIni ); if (MaterialSection != NULL) { for (FConfigSection::TIterator It(*MaterialSection); It; ++It) { FString MaterialName; if( FParse::Value( *It.Value().GetValue(), TEXT("Material="), MaterialName, true ) ) { UMaterial* Material = LoadObject<UMaterial>(NULL, *MaterialName); if (Material) { Material->AddToRoot(); Record& Rec = MaterialMap.Add(It.Key(), Record()); Rec.Name = It.Key().GetPlainNameString(); Rec.Material = Material; FText DisplayName; FParse::Value( *It.Value().GetValue(), TEXT("Name="), DisplayName, TEXT("Engine.BufferVisualizationMaterials") ); Rec.DisplayName = DisplayName; } } } } ConfigureConsoleCommand(); } bIsInitialized = true; } }
void UnFbx::FFbxImporter::CreateUnrealMaterial(FbxSurfaceMaterial* FbxMaterial, TArray<UMaterialInterface*>& OutMaterials, TArray<FString>& UVSets) { FString MaterialFullName = ANSI_TO_TCHAR(MakeName(FbxMaterial->GetName())); // check for a 'skinXX' suffix in the material name int32 MaterialNameLen = FCString::Strlen(*MaterialFullName) + 1; char* MaterialNameANSI = new char[MaterialNameLen]; FCStringAnsi::Strcpy(MaterialNameANSI, MaterialNameLen, TCHAR_TO_ANSI(*MaterialFullName)); if (FCStringAnsi::Strlen(MaterialNameANSI) > 6) { const char* SkinXX = MaterialNameANSI + FCStringAnsi::Strlen(MaterialNameANSI) - 6; if (FCharAnsi::ToUpper(*SkinXX) == 'S' && FCharAnsi::ToUpper(*(SkinXX+1)) == 'K' && FCharAnsi::ToUpper(*(SkinXX+2)) == 'I' && FCharAnsi::ToUpper(*(SkinXX+3)) == 'N') { if (FCharAnsi::IsDigit(*(SkinXX+4)) && FCharAnsi::IsDigit(*(SkinXX+5))) { // remove the 'skinXX' suffix from the material name MaterialFullName = MaterialFullName.Left(MaterialNameLen - 7); } } } MaterialFullName = ObjectTools::SanitizeObjectName(MaterialFullName); // Make sure we have a parent if ( !ensure(Parent) ) { return; } // set where to place the materials FString NewPackageName = FPackageName::GetLongPackagePath(Parent->GetOutermost()->GetName()) + TEXT("/") + MaterialFullName; NewPackageName = PackageTools::SanitizePackageName(NewPackageName); UPackage* Package = CreatePackage(NULL, *NewPackageName); UMaterialInterface* UnrealMaterialInterface = FindObject<UMaterialInterface>(Package,*MaterialFullName); // does not override existing materials if (UnrealMaterialInterface != NULL) { OutMaterials.Add(UnrealMaterialInterface); return; } // create an unreal material asset UMaterialFactoryNew* MaterialFactory = new UMaterialFactoryNew(FPostConstructInitializeProperties()); UMaterial* UnrealMaterial = (UMaterial*)MaterialFactory->FactoryCreateNew( UMaterial::StaticClass(), Package, *MaterialFullName, RF_Standalone|RF_Public, NULL, GWarn ); // TODO : need this ? UnrealMaterial->bUsedWithStaticLighting = true; if ( UnrealMaterial != NULL ) { // Notify the asset registry FAssetRegistryModule::AssetCreated(UnrealMaterial); // Set the dirty flag so this package will get saved later Package->SetDirtyFlag(true); } // textures and properties CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sDiffuse, UnrealMaterial->DiffuseColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sEmissive, UnrealMaterial->EmissiveColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecular, UnrealMaterial->SpecularColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecularFactor, UnrealMaterial->SpecularColor, false, UVSets); // SpecularFactor modulates the SpecularColor value if there's one //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sShininess, UnrealMaterial->SpecularPower, false, UVSets); if (!CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sNormalMap, UnrealMaterial->Normal, true, UVSets)) { CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sBump, UnrealMaterial->Normal, true, UVSets); // no bump in unreal, use as normal map } //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparentColor, UnrealMaterial->Opacity, false, UVSets); //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparencyFactor, UnrealMaterial->OpacityMask, false, UVSets); FixupMaterial( *FbxMaterial, UnrealMaterial); // add random diffuse if none exists // compile shaders for PC (from UPrecompileShadersCommandlet::ProcessMaterial // and FMaterialEditor::UpdateOriginalMaterial) // make sure that any static meshes, etc using this material will stop using the FMaterialResource of the original // material, and will use the new FMaterialResource created when we make a new UMaterial in place FGlobalComponentReregisterContext RecreateComponents; // let the material update itself if necessary UnrealMaterial->PreEditChange(NULL); UnrealMaterial->PostEditChange(); OutMaterials.Add(UnrealMaterial); }
// *************************************************************************** void CDriverUser::deleteMaterial(UMaterial &umat) { delete umat.getObjectPtr(); umat.detach(); }
FLinearColor UMaterialGraphNode::GetNodeTitleColor() const { UMaterial* Material = CastChecked<UMaterialGraph>(GetGraph())->Material; if (bIsPreviewExpression) { // If we are currently previewing a node, its border should be the preview color. return FColor( 70, 100, 200 ); } const UGraphEditorSettings* Settings = GetDefault<UGraphEditorSettings>(); if (UsesBoolColour(MaterialExpression)) { return Settings->BooleanPinTypeColor; } else if (UsesFloatColour(MaterialExpression)) { return Settings->FloatPinTypeColor; } else if (UsesVectorColour(MaterialExpression)) { return Settings->VectorPinTypeColor; } else if (UsesObjectColour(MaterialExpression)) { return Settings->ObjectPinTypeColor; } else if (UsesEventColour(MaterialExpression)) { return Settings->EventNodeTitleColor; } else if (MaterialExpression->IsA(UMaterialExpressionMaterialFunctionCall::StaticClass())) { // Previously FColor(0, 116, 255); return Settings->FunctionCallNodeTitleColor; } else if (MaterialExpression->IsA(UMaterialExpressionFunctionOutput::StaticClass())) { // Previously FColor(255, 155, 0); return Settings->ResultNodeTitleColor; } else if (MaterialExpression->IsA(UMaterialExpressionCustomOutput::StaticClass())) { // Previously FColor(255, 155, 0); return Settings->ResultNodeTitleColor; } else if (UMaterial::IsParameter(MaterialExpression)) { if (Material->HasDuplicateParameters(MaterialExpression)) { return FColor( 0, 255, 255 ); } else { return FColor( 0, 128, 128 ); } } else if (UMaterial::IsDynamicParameter(MaterialExpression)) { if (Material->HasDuplicateDynamicParameters(MaterialExpression)) { return FColor( 0, 255, 255 ); } else { return FColor( 0, 128, 128 ); } } // Assume that most material expressions act like pure functions and don't affect anything else return Settings->PureFunctionCallNodeTitleColor; }
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); }
void UMaterialEditorInstanceConstant::RegenerateArrays() { VisibleExpressions.Empty(); ParameterGroups.Empty(); if(Parent) { // Only operate on base materials UMaterial* ParentMaterial = Parent->GetMaterial(); SourceInstance->UpdateParameterNames(); // Update any parameter names that may have changed. // Loop through all types of parameters for this material and add them to the parameter arrays. TArray<FName> ParameterNames; TArray<FGuid> Guids; ParentMaterial->GetAllVectorParameterNames(ParameterNames, Guids); // Vector Parameters. for(int32 ParameterIdx=0; ParameterIdx<ParameterNames.Num(); ParameterIdx++) { UDEditorVectorParameterValue & ParameterValue = *(NewObject<UDEditorVectorParameterValue>()); FName ParameterName = ParameterNames[ParameterIdx]; FLinearColor Value; ParameterValue.bOverride = false; ParameterValue.ParameterName = ParameterName; ParameterValue.ExpressionId = Guids[ParameterIdx]; if(SourceInstance->GetVectorParameterValue(ParameterName, Value)) { ParameterValue.ParameterValue = Value; } // @todo: This is kind of slow, maybe store these in a map for lookup? // See if this keyname exists in the source instance. for(int32 VectorParameterIdx=0; VectorParameterIdx<SourceInstance->VectorParameterValues.Num(); VectorParameterIdx++) { FVectorParameterValue& SourceParam = SourceInstance->VectorParameterValues[VectorParameterIdx]; if(ParameterName==SourceParam.ParameterName) { ParameterValue.bOverride = true; ParameterValue.ParameterValue = SourceParam.ParameterValue; } } AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } // Scalar Parameters. ParentMaterial->GetAllScalarParameterNames(ParameterNames, Guids); for (int32 ParameterIdx=0; ParameterIdx<ParameterNames.Num(); ParameterIdx++) { UDEditorScalarParameterValue& ParameterValue = *(NewObject<UDEditorScalarParameterValue>()); FName ParameterName = ParameterNames[ParameterIdx]; float Value; ParameterValue.bOverride = false; ParameterValue.ParameterName = ParameterName; ParameterValue.ExpressionId = Guids[ParameterIdx]; if (SourceInstance->GetScalarParameterValue(ParameterName, Value)) { ParentMaterial->GetScalarParameterSliderMinMax(ParameterName, ParameterValue.SliderMin, ParameterValue.SliderMax); ParameterValue.ParameterValue = Value; } // @todo: This is kind of slow, maybe store these in a map for lookup? // See if this keyname exists in the source instance. for(int32 ScalarParameterIdx=0; ScalarParameterIdx<SourceInstance->ScalarParameterValues.Num(); ScalarParameterIdx++) { FScalarParameterValue& SourceParam = SourceInstance->ScalarParameterValues[ScalarParameterIdx]; if(ParameterName==SourceParam.ParameterName) { ParameterValue.bOverride = true; ParameterValue.ParameterValue = SourceParam.ParameterValue; } } AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } // Texture Parameters. ParentMaterial->GetAllTextureParameterNames(ParameterNames, Guids); for(int32 ParameterIdx=0; ParameterIdx<ParameterNames.Num(); ParameterIdx++) { UDEditorTextureParameterValue& ParameterValue = *(NewObject<UDEditorTextureParameterValue>()); FName ParameterName = ParameterNames[ParameterIdx]; UTexture* Value; ParameterValue.bOverride = false; ParameterValue.ParameterName = ParameterName; ParameterValue.ExpressionId = Guids[ParameterIdx]; if(SourceInstance->GetTextureParameterValue(ParameterName, Value)) { ParameterValue.ParameterValue = Value; } // @todo: This is kind of slow, maybe store these in a map for lookup? // See if this keyname exists in the source instance. for(int32 TextureParameterIdx=0; TextureParameterIdx<SourceInstance->TextureParameterValues.Num(); TextureParameterIdx++) { FTextureParameterValue& SourceParam = SourceInstance->TextureParameterValues[TextureParameterIdx]; if(ParameterName==SourceParam.ParameterName) { ParameterValue.bOverride = true; ParameterValue.ParameterValue = SourceParam.ParameterValue; } } AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } // Font Parameters. ParentMaterial->GetAllFontParameterNames(ParameterNames, Guids); for(int32 ParameterIdx=0; ParameterIdx<ParameterNames.Num(); ParameterIdx++) { UDEditorFontParameterValue& ParameterValue = *(NewObject<UDEditorFontParameterValue>()); FName ParameterName = ParameterNames[ParameterIdx]; UFont* FontValue; int32 FontPage; ParameterValue.bOverride = false; ParameterValue.ParameterName = ParameterName; ParameterValue.ExpressionId = Guids[ParameterIdx]; if(SourceInstance->GetFontParameterValue(ParameterName, FontValue,FontPage)) { ParameterValue.ParameterValue.FontValue = FontValue; ParameterValue.ParameterValue.FontPage = FontPage; } // @todo: This is kind of slow, maybe store these in a map for lookup? // See if this keyname exists in the source instance. for(int32 FontParameterIdx=0; FontParameterIdx<SourceInstance->FontParameterValues.Num(); FontParameterIdx++) { FFontParameterValue& SourceParam = SourceInstance->FontParameterValues[FontParameterIdx]; if(ParameterName==SourceParam.ParameterName) { ParameterValue.bOverride = true; ParameterValue.ParameterValue.FontValue = SourceParam.FontValue; ParameterValue.ParameterValue.FontPage = SourceParam.FontPage; } } AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } // Get all static parameters from the source instance. This will handle inheriting parent values. FStaticParameterSet SourceStaticParameters; SourceInstance->GetStaticParameterValues(SourceStaticParameters); // Copy Static Switch Parameters for(int32 ParameterIdx=0; ParameterIdx<SourceStaticParameters.StaticSwitchParameters.Num(); ParameterIdx++) { FStaticSwitchParameter StaticSwitchParameterValue = FStaticSwitchParameter(SourceStaticParameters.StaticSwitchParameters[ParameterIdx]); UDEditorStaticSwitchParameterValue& ParameterValue = *(NewObject<UDEditorStaticSwitchParameterValue>()); ParameterValue.ParameterValue =StaticSwitchParameterValue.Value; ParameterValue.bOverride =StaticSwitchParameterValue.bOverride; ParameterValue.ParameterName =StaticSwitchParameterValue.ParameterName; ParameterValue.ExpressionId= StaticSwitchParameterValue.ExpressionGUID; AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } // Copy Static Component Mask Parameters for(int32 ParameterIdx=0; ParameterIdx<SourceStaticParameters.StaticComponentMaskParameters.Num(); ParameterIdx++) { FStaticComponentMaskParameter StaticComponentMaskParameterValue = FStaticComponentMaskParameter(SourceStaticParameters.StaticComponentMaskParameters[ParameterIdx]); UDEditorStaticComponentMaskParameterValue& ParameterValue = *(NewObject<UDEditorStaticComponentMaskParameterValue>()); ParameterValue.ParameterValue.R = StaticComponentMaskParameterValue.R; ParameterValue.ParameterValue.G = StaticComponentMaskParameterValue.G; ParameterValue.ParameterValue.B = StaticComponentMaskParameterValue.B; ParameterValue.ParameterValue.A = StaticComponentMaskParameterValue.A; ParameterValue.bOverride =StaticComponentMaskParameterValue.bOverride; ParameterValue.ParameterName =StaticComponentMaskParameterValue.ParameterName; ParameterValue.ExpressionId= StaticComponentMaskParameterValue.ExpressionGUID; AssignParameterToGroup(ParentMaterial, Cast<UDEditorParameterValue>(&ParameterValue)); } IMaterialEditorModule* MaterialEditorModule = &FModuleManager::LoadModuleChecked<IMaterialEditorModule>( "MaterialEditor" ); MaterialEditorModule->GetVisibleMaterialParameters(ParentMaterial, SourceInstance, VisibleExpressions); } // sort contents of groups for(int32 ParameterIdx=0; ParameterIdx<ParameterGroups.Num(); ParameterIdx++) { FEditorParameterGroup & ParamGroup = ParameterGroups[ParameterIdx]; struct FCompareUDEditorParameterValueByParameterName { FORCEINLINE bool operator()(const UDEditorParameterValue& A, const UDEditorParameterValue& B) const { FString AName = A.ParameterName.ToString().ToLower(); FString BName = B.ParameterName.ToString().ToLower(); return AName < BName; } }; ParamGroup.Parameters.Sort( FCompareUDEditorParameterValueByParameterName() ); } // sort groups itself pushing defaults to end struct FCompareFEditorParameterGroupByName { FORCEINLINE bool operator()(const FEditorParameterGroup& A, const FEditorParameterGroup& B) const { FString AName = A.GroupName.ToString().ToLower(); FString BName = B.GroupName.ToString().ToLower(); if (AName == TEXT("none")) { return false; } if (BName == TEXT("none")) { return false; } return AName < BName; } }; ParameterGroups.Sort( FCompareFEditorParameterGroupByName() ); TArray<struct FEditorParameterGroup> ParameterDefaultGroups; for(int32 ParameterIdx=0; ParameterIdx<ParameterGroups.Num(); ParameterIdx++) { FEditorParameterGroup & ParamGroup = ParameterGroups[ParameterIdx]; if (bUseOldStyleMICEditorGroups == false) { if (ParamGroup.GroupName == TEXT("None")) { ParameterDefaultGroups.Add(ParamGroup); ParameterGroups.RemoveAt(ParameterIdx); break; } } else { if (ParamGroup.GroupName == TEXT("Vector Parameter Values") || ParamGroup.GroupName == TEXT("Scalar Parameter Values") || ParamGroup.GroupName == TEXT("Texture Parameter Values") || ParamGroup.GroupName == TEXT("Static Switch Parameter Values") || ParamGroup.GroupName == TEXT("Static Component Mask Parameter Values") || ParamGroup.GroupName == TEXT("Font Parameter Values")) { ParameterDefaultGroups.Add(ParamGroup); ParameterGroups.RemoveAt(ParameterIdx); } } } if (ParameterDefaultGroups.Num() >0) { ParameterGroups.Append(ParameterDefaultGroups); } }
void FGridWidget::DrawNewGrid(const FSceneView* View, FPrimitiveDrawInterface* PDI) { bool bUseTextureSolution = CVarEditorNewLevelGrid.GetValueOnGameThread() > 1; UMaterial* GridMaterial = bUseTextureSolution ? LevelGridMaterial2 : LevelGridMaterial; UMaterialInstanceDynamic* MaterialInst = bUseTextureSolution ? LevelGridMaterialInst2 : LevelGridMaterialInst; if (GridMaterial->IsCompilingOrHadCompileError(View->GetFeatureLevel())) { // The material would appear to be black (because we don't use a MaterialDomain but a UsageFlag - we should change that). // Here we rather want to hide it. return; } if(!MaterialInst) { return; } bool bMSAA = IsEditorCompositingMSAAEnabled(View->GetFeatureLevel()); bool bIsPerspective = ( View->ViewMatrices.ProjMatrix.M[3][3] < 1.0f ); // in unreal units float SnapGridSize = GEditor->GetGridSize(); // not used yet const bool bSnapEnabled = GetDefault<ULevelEditorViewportSettings>()->GridEnabled; float SnapAlphaMultiplier = 1.0f; // to get a light grid in a black level but use a high opacity value to be able to see it in a bright level static float Darken = 0.11f; static FName GridColorName("GridColor"); static FName SnapColorName("SnapColor"); static FName ExponentName("Exponent"); static FName AlphaBiasName("AlphaBias"); if(bIsPerspective) { MaterialInst->SetVectorParameterValue(GridColorName, FLinearColor(0.6f * Darken, 0.6f * Darken, 0.6f * Darken, CVarEditor3DGridFade.GetValueOnGameThread())); MaterialInst->SetVectorParameterValue(SnapColorName, FLinearColor(0.5f, 0.0f, 0.0f, SnapAlphaMultiplier * CVarEditor3DSnapFade.GetValueOnGameThread())); } else { MaterialInst->SetVectorParameterValue(GridColorName, FLinearColor(0.6f * Darken, 0.6f * Darken, 0.6f * Darken, CVarEditor2DGridFade.GetValueOnGameThread())); MaterialInst->SetVectorParameterValue(SnapColorName, FLinearColor(0.5f, 0.0f, 0.0f, SnapAlphaMultiplier * CVarEditor2DSnapFade.GetValueOnGameThread())); } // true:1m, false:1dm ios smallest grid size bool bLarger1mGrid = true; const int Exponent = 10; // 2 is the default so we need to set it MaterialInst->SetScalarParameterValue(ExponentName, (float)Exponent); // without MSAA we need the grid to be more see through so lines behind it can be recognized MaterialInst->SetScalarParameterValue(AlphaBiasName, bMSAA ? 0.0f : 0.05f); // grid for size float GridSplit = 0.5f; // red dots to visualize the snap float SnapSplit = 0.075f; float WorldToUVScale = 0.001f; if(bLarger1mGrid) { WorldToUVScale *= 0.1f; GridSplit *= 0.1f; } // in 2D all grid lines are same size in world space (they are at different scale so we need to adjust here) FLinearColor GridSplitTriple(GridSplit * 0.01f, GridSplit * 0.1f, GridSplit); if(bIsPerspective) { // largest grid lines GridSplitTriple.R *= 8.0f; // medium grid lines GridSplitTriple.G *= 3.0f; // fine grid lines GridSplitTriple.B *= 1.0f; } if(!bIsPerspective) { // screenspace size looks better in 2d float ScaleX = View->ViewMatrices.ProjMatrix.M[0][0] * View->ViewRect.Width(); float ScaleY = View->ViewMatrices.ProjMatrix.M[1][1] * View->ViewRect.Height(); float Scale = FMath::Min(ScaleX, ScaleY); float GridScale = CVarEditor2DSnapScale.GetValueOnGameThread(); float GridMin = CVarEditor2DSnapMin.GetValueOnGameThread(); // we need to account for a larger grids setting SnapSplit = 1.25f * FMath::Min(GridScale / SnapGridSize / Scale, GridMin); // hack test GridSplitTriple.R = 0.25f * FMath::Min(GridScale / 100 / Scale * 0.01f, GridMin); GridSplitTriple.G = 0.25f * FMath::Min(GridScale / 100 / Scale * 0.1f, GridMin); GridSplitTriple.B = 0.25f * FMath::Min(GridScale / 100 / Scale, GridMin); } float SnapTile = (1.0f / WorldToUVScale) / FMath::Max(1.0f, SnapGridSize); MaterialInst->SetVectorParameterValue("GridSplit", GridSplitTriple); MaterialInst->SetScalarParameterValue("SnapSplit", SnapSplit); MaterialInst->SetScalarParameterValue("SnapTile", SnapTile); FMatrix ObjectToWorld = FMatrix::Identity; FVector CameraPos = View->ViewMatrices.ViewOrigin; FVector2D UVCameraPos = FVector2D(CameraPos.X, CameraPos.Y); ObjectToWorld.SetOrigin(FVector(CameraPos.X, CameraPos.Y, 0)); FLinearColor AxisColors[3]; GetAxisColors(AxisColors, true); FLinearColor UAxisColor = AxisColors[1]; FLinearColor VAxisColor = AxisColors[0]; if(!bIsPerspective) { float FarZ = 100000.0f; if(View->ViewMatrices.ViewMatrix.M[1][1] == -1.f ) // Top { ObjectToWorld.SetOrigin(FVector(CameraPos.X, CameraPos.Y, -FarZ)); } if(View->ViewMatrices.ViewMatrix.M[1][2] == -1.f ) // Front { UVCameraPos = FVector2D(CameraPos.Z, CameraPos.X); ObjectToWorld.SetAxis(0, FVector(0,0,1)); ObjectToWorld.SetAxis(1, FVector(1,0,0)); ObjectToWorld.SetAxis(2, FVector(0,1,0)); ObjectToWorld.SetOrigin(FVector(CameraPos.X, -FarZ, CameraPos.Z)); UAxisColor = AxisColors[0]; VAxisColor = AxisColors[2]; } else if(View->ViewMatrices.ViewMatrix.M[1][0] == 1.f ) // Side { UVCameraPos = FVector2D(CameraPos.Y, CameraPos.Z); ObjectToWorld.SetAxis(0, FVector(0,1,0)); ObjectToWorld.SetAxis(1, FVector(0,0,1)); ObjectToWorld.SetAxis(2, FVector(1,0,0)); ObjectToWorld.SetOrigin(FVector(FarZ, CameraPos.Y, CameraPos.Z)); UAxisColor = AxisColors[2]; VAxisColor = AxisColors[1]; } } MaterialInst->SetVectorParameterValue("UAxisColor", UAxisColor); MaterialInst->SetVectorParameterValue("VAxisColor", VAxisColor); // We don't want to affect the mouse interaction. PDI->SetHitProxy(0); // good enough to avoid the AMD artifacts, horizon still appears to be a line float Radii = 100000; if(bIsPerspective) { // the higher we get the larger we make the geometry to give the illusion of an infinite grid while maintains the precision nearby Radii *= FMath::Max( 1.0f, FMath::Abs(CameraPos.Z) / 1000.0f ); } else { float ScaleX = View->ViewMatrices.ProjMatrix.M[0][0]; float ScaleY = View->ViewMatrices.ProjMatrix.M[1][1]; float Scale = FMath::Min(ScaleX, ScaleY); Scale *= View->ViewRect.Width(); // We render a larger grid if we are zoomed out more (good precision at any scale) Radii *= 1.0f / Scale; } FVector2D UVMid = UVCameraPos * WorldToUVScale; float UVRadi = Radii * WorldToUVScale; FVector2D UVMin = UVMid + FVector2D(-UVRadi, -UVRadi); FVector2D UVMax = UVMid + FVector2D(UVRadi, UVRadi); // vertex pos is in -1..1 range DrawPlane10x10(PDI, ObjectToWorld, Radii, UVMin, UVMax, MaterialInst->GetRenderProxy(false), SDPG_World ); }
void FMaterialThumbnailScene::SetMaterialInterface(UMaterialInterface* InMaterial) { check(PreviewActor); check(PreviewActor->GetStaticMeshComponent()); bIsUIMaterial = false; if ( InMaterial ) { // Transform the preview mesh as necessary FTransform Transform = FTransform::Identity; const USceneThumbnailInfoWithPrimitive* ThumbnailInfo = Cast<USceneThumbnailInfoWithPrimitive>(InMaterial->ThumbnailInfo); if ( !ThumbnailInfo ) { ThumbnailInfo = USceneThumbnailInfoWithPrimitive::StaticClass()->GetDefaultObject<USceneThumbnailInfoWithPrimitive>(); } UMaterial* BaseMaterial = InMaterial->GetBaseMaterial(); // UI material thumbnails always get a 2D plane centered at the camera which is a better representation of the // what the material will look like on UI bIsUIMaterial = BaseMaterial && BaseMaterial->IsUIMaterial(); EThumbnailPrimType PrimitiveType = bIsUIMaterial ? TPT_Plane : ThumbnailInfo->PrimitiveType.GetValue(); switch( PrimitiveType ) { case TPT_None: { bool bFoundCustomMesh = false; if ( ThumbnailInfo->PreviewMesh.IsValid() ) { UStaticMesh* MeshToUse = Cast<UStaticMesh>(ThumbnailInfo->PreviewMesh.ResolveObject()); if ( MeshToUse ) { PreviewActor->GetStaticMeshComponent()->SetStaticMesh(MeshToUse); bFoundCustomMesh = true; } } if ( !bFoundCustomMesh ) { // Just use a plane if the mesh was not found Transform.SetRotation(FQuat(FRotator(0, -90, 0))); PreviewActor->GetStaticMeshComponent()->SetStaticMesh(GUnrealEd->GetThumbnailManager()->EditorPlane); } } break; case TPT_Cube: PreviewActor->GetStaticMeshComponent()->SetStaticMesh(GUnrealEd->GetThumbnailManager()->EditorCube); break; case TPT_Sphere: // The sphere is a little big, scale it down to 256x256x256 Transform.SetScale3D( FVector(0.8f) ); PreviewActor->GetStaticMeshComponent()->SetStaticMesh(GUnrealEd->GetThumbnailManager()->EditorSphere); break; case TPT_Cylinder: PreviewActor->GetStaticMeshComponent()->SetStaticMesh(GUnrealEd->GetThumbnailManager()->EditorCylinder); break; case TPT_Plane: // The plane needs to be rotated 90 degrees to face the camera Transform.SetRotation(FQuat(FRotator(0, -90, 0))); PreviewActor->GetStaticMeshComponent()->SetStaticMesh(GUnrealEd->GetThumbnailManager()->EditorPlane); break; default: check(0); } PreviewActor->GetStaticMeshComponent()->SetRelativeTransform(Transform); PreviewActor->GetStaticMeshComponent()->UpdateBounds(); // Center the mesh at the world origin then offset to put it on top of the plane const float BoundsZOffset = GetBoundsZOffset(PreviewActor->GetStaticMeshComponent()->Bounds); Transform.SetLocation(-PreviewActor->GetStaticMeshComponent()->Bounds.Origin + FVector(0, 0, BoundsZOffset)); PreviewActor->GetStaticMeshComponent()->SetRelativeTransform(Transform); } PreviewActor->GetStaticMeshComponent()->SetMaterial(0, InMaterial); PreviewActor->GetStaticMeshComponent()->RecreateRenderState_Concurrent(); }
//! @brief Create an Unreal Material for the given graph-instance UMaterial* CreateMaterial(graph_inst_t* GraphInstance, const FString & MaterialName, UObject* Outer) { // create an unreal material asset UMaterialFactoryNew* MaterialFactory = NewObject<UMaterialFactoryNew>(); UMaterial* UnrealMaterial = (UMaterial*)MaterialFactory->FactoryCreateNew( UMaterial::StaticClass(), Substance::Helpers::CreateObjectPackage(Outer, MaterialName), *MaterialName, RF_Standalone|RF_Public, NULL, GWarn ); // textures and properties for (auto ItOut = GraphInstance->Outputs.itfront(); ItOut; ++ItOut) { output_inst_t* OutputInst = &(*ItOut); output_desc_t* OutputDesc = OutputInst->GetOutputDesc(); CreateMaterialExpression( OutputInst, UnrealMaterial); } // special case: emissive only materials TArray<FName> ParamNames; TArray<FGuid> ParamIds; UnrealMaterial->GetAllTextureParameterNames(ParamNames, ParamIds); if (ParamNames.Num() == 1) { if (ParamNames[0].ToString() == TEXT("emissive")) { UnrealMaterial->SetShadingModel(MSM_Unlit); } } // special case: no roughness but glossiness if (!UnrealMaterial->Roughness.IsConnected()) { for (auto ItOut = GraphInstance->Outputs.itfront(); ItOut; ++ItOut) { output_inst_t* OutputInst = &(*ItOut); output_desc_t* OutputDesc = OutputInst->GetOutputDesc(); UTexture* Texture = *OutputInst->Texture; if (OutputDesc->Channel == CHAN_Glossiness && Texture) { // and link it to the material UMaterialExpressionOneMinus* OneMinus = NewObject<UMaterialExpressionOneMinus>(UnrealMaterial); UMaterialExpressionTextureSampleParameter2D* UnrealTextureExpression = CreateSampler(UnrealMaterial, Texture, OutputDesc); UnrealTextureExpression->MaterialExpressionEditorX -= 200; OneMinus->MaterialExpressionEditorX = -200; OneMinus->MaterialExpressionEditorY = UnrealTextureExpression->MaterialExpressionEditorY; UnrealTextureExpression->ConnectExpression(OneMinus->GetInput(0), 0); UnrealMaterial->Roughness.Expression = OneMinus; UnrealMaterial->Expressions.Add(UnrealTextureExpression); UnrealMaterial->Expressions.Add(OneMinus); } } } // let the material update itself if necessary UnrealMaterial->PreEditChange(NULL); UnrealMaterial->PostEditChange(); return UnrealMaterial; }
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 }