You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3045482 on 2016/07/11 by Zabir.Hoque DX12 Quries need to individually track their syncpoints. Only when resolving a query on the same frame should be stall. Change 3045929 on 2016/07/12 by Simon.Tovey Removing some deprecated node types from Niagara Change 3045951 on 2016/07/12 by Ben.Woodhouse D3D11 Log detailed live device info on shutdown if the debug layer is enabled (including resource types) Change3046019on 2016/07/12 by Chris.Bunner Fixed typo in material input name. #jira UE-5575 Change 3046053 on 2016/07/12 by Rolando.Caloca DR - Fix GL4 shutdown #jira UE-32799 Change 3046055 on 2016/07/12 by Rolando.Caloca DR - vk - Fix NumInstances=0 Change 3046063 on 2016/07/12 by Rolando.Caloca DR - vk - Added flat to uint layouts per glslang - Fix bad extension on dumped shaders Change 3046067 on 2016/07/12 by Rolando.Caloca DR - vk - Fix check when not using color RT - Added queue submit & present counters Change3046088on 2016/07/12 by Ben.Woodhouse Live GPU stats A non-hierarchical realtime high level GPU profiler with support for cumulative stat recording. Stats are added with SCOPED_GPU_STAT macros, e.g. SCOPED_GPU_STAT(RHICmdList, Stat_GPU_Distortion) The bulk of the files in this change are simply instrumentation for the renderer. The core changes are in SceneUtils.cpp/h and D3D11Query.cpp (this is the XB1/DX11X implementation of timestamp RHI queries, which was missing) Note: this is currently disabled by default. Enable with the cvar r.gpustatsenabled Tested on PC, XB1, PS4 Change 3046128 on 2016/07/12 by Olaf.Piesche Max draw distance and fade range for lights, requested by JonL Change 3046183 on 2016/07/12 by Ben.Woodhouse PR #2532: Fix SSAO being applied in unlit viewmode (Contributed by nick-penwarden) Change 3046223 on 2016/07/12 by Luke.Thatcher Fix Scene Cube Captures. SceneCaptureSource flag on the ViewFamily was not set for cube components. #jira UE-32345 Change 3046228 on 2016/07/12 by Marc.Olano Add Voronoi noise to Noise material node. Four versions with differing speed/quality levels accessed through the Quality value in the material node. Tooltips give estimates of the cost of each. Also includes spiffy new Rand3DPCG16 and Rand3DPCG32 int3 to int3 hash functions, and a 20% improvement on the computed gradient noise. Change 3046269 on 2016/07/12 by Rolando.Caloca DR - Skip flush on RHIDiscardRenderTargets and only use it on platforms that need it (ie OpenGL) Change 3046294 on 2016/07/12 by Rolando.Caloca DR - Fix static analyisis warning C6326: Potential comparison of a constant with another constant. Change 3046295 on 2016/07/12 by Rolando.Caloca DR - Fix the previous fix Change 3046731 on 2016/07/12 by Marc.Olano Fix typo in shader random number constant: repeated extra digit made it too big. Change 3046796 on 2016/07/12 by Uriel.Doyon The texture streaming manager now keeps a set of all valid textures. This is used to prevent from indirecting deleted memory upon SetTexturesRemovedTimestamp. #jira UE-33048 Change 3046800 on 2016/07/12 by Rolando.Caloca DR - vk - Added create image & renderpass dump Change 3046845 on 2016/07/12 by John.Billon Forgot to apply MaxGPUSkinBones Cvar access changes in a few locations. Change 3047023 on 2016/07/12 by Olaf.Piesche Niagara: -a bit of cleanup -now store and double buffer attributes individually, eliminating unnecessary copy of unused attributes -removed FNiagaraConstantMap, replaced with an instance of FNiagaraConstants -some code simplification -removed some deprecated structs and code used only by old content Change 3047052 on 2016/07/12 by Zabir.Hoque Unshelved from pending changelist '3044062': PR #2588: Adding blend mode BLEND_AlphaComposite (4.12) (Contributed by moritz-wundke) Change 3047727 on 2016/07/13 by Luke.Thatcher Fix Scene Capture Components only updating every other frame. #jira UE-32581 Change 3047919 on 2016/07/13 by Olaf.Piesche CMask decode, use in deferred decals, for PS4 Change 3047921 on 2016/07/13 by Uriel.Doyon "Build Texture Streaming" will now remove duplicate error msg when computing texcoord scales. Also, several texture messages are packed on the same line if they relate to the same material. Change 3047952 on 2016/07/13 by Rolando.Caloca DR - vk - Initial prep pass for separating combined images & samplers Change 3048648 on 2016/07/13 by Marcus.Wassmer Fix rare GPU hang when asynctexture reallocs would overlap with EndFrame Change 3049058 on 2016/07/13 by Rolando.Caloca DR - vk - timestamps Change 3049725 on 2016/07/14 by Marcus.Wassmer Fix autosdk bug where not having a platform directory sync'd at all would break manual SDK detection Change 3049742 on 2016/07/14 by Rolando.Caloca DR - Fix warning Change 3049902 on 2016/07/14 by Rolando.Caloca DR - Fix typo Change 3050345 on 2016/07/14 by Olaf.Piesche UE-23925 Clamping noise tessellation for beams at a high but sensible value; also making sure during beam index buffer building that we never get over 2^16 indices; this is a bit hokey, but there are so many variables that can influence triangle/index count, that this is the only way to be sure (short of nuking the entire site from orbit). Change 3050409 on 2016/07/14 by Olaf.Piesche Replicating 3049049; missing break and check for active particles when resolving a source point to avoid a potential crash Change 3050809 on 2016/07/14 by Rolando.Caloca DR - vk - Remove redundant validation layers Change 3051319 on 2016/07/15 by Ben.Woodhouse Fix for world space camera position not being exposed in decal pixel shaders; also fixes decal lighting missing spec and reflection The fix was to calculate ResolvedView at the top of the shader. Previously this was not initialized #jira UE-31976 Change 3051692 on 2016/07/15 by Rolando.Caloca DR - vk - Enable RHI thread by default Change 3052103 on 2016/07/15 by Uriel.Doyon Disabled depth offset in depth only pixel shaders when using debug view shaders (to prevent Z fighting). #jira UE-32765 Change 3052140 on 2016/07/15 by Rolando.Caloca DR - vk - Fix shader snafu Change 3052495 on 2016/07/15 by Rolando.Caloca DR - Fix for Win32 compile #jira UE-33349 Change 3052536 on 2016/07/15 by Uriel.Doyon Fixed texture streaming overbudget warning when using per texture bias. [CL 3054554 by Gil Gribb in Main branch]
810 lines
23 KiB
C++
810 lines
23 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
MaterialGraphNode.cpp
|
|
=============================================================================*/
|
|
|
|
#include "UnrealEd.h"
|
|
|
|
#include "Materials/MaterialExpressionComponentMask.h"
|
|
#include "Materials/MaterialExpressionConstant.h"
|
|
#include "Materials/MaterialExpressionConstant2Vector.h"
|
|
#include "Materials/MaterialExpressionConstant3Vector.h"
|
|
#include "Materials/MaterialExpressionConstant4Vector.h"
|
|
#include "Materials/MaterialExpressionFontSample.h"
|
|
#include "Materials/MaterialExpressionFontSampleParameter.h"
|
|
#include "Materials/MaterialExpressionFunctionInput.h"
|
|
#include "Materials/MaterialExpressionFunctionOutput.h"
|
|
#include "Materials/MaterialExpressionMaterialFunctionCall.h"
|
|
#include "Materials/MaterialExpressionParameter.h"
|
|
#include "Materials/MaterialExpressionScalarParameter.h"
|
|
#include "Materials/MaterialExpressionStaticBool.h"
|
|
#include "Materials/MaterialExpressionStaticBoolParameter.h"
|
|
#include "Materials/MaterialExpressionTangentOutput.h"
|
|
#include "Materials/MaterialExpressionTextureBase.h"
|
|
#include "Materials/MaterialExpressionTextureCoordinate.h"
|
|
#include "Materials/MaterialExpressionTextureSample.h"
|
|
#include "Materials/MaterialExpressionTextureSampleParameter.h"
|
|
#include "Materials/MaterialExpressionTextureObject.h"
|
|
#include "Materials/MaterialExpressionTextureProperty.h"
|
|
#include "Materials/MaterialExpressionVectorParameter.h"
|
|
#include "Materials/MaterialExpressionViewProperty.h"
|
|
#include "Materials/MaterialFunction.h"
|
|
|
|
#include "MaterialEditorUtilities.h"
|
|
#include "MaterialEditorActions.h"
|
|
#include "GraphEditorActions.h"
|
|
#include "GraphEditorSettings.h"
|
|
#include "EditorClassUtils.h"
|
|
#include "GenericCommands.h"
|
|
#include "ScopedTransaction.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "MaterialGraphNode"
|
|
|
|
/////////////////////////////////////////////////////
|
|
// UMaterialGraphNode
|
|
|
|
UMaterialGraphNode::UMaterialGraphNode(const FObjectInitializer& ObjectInitializer)
|
|
: Super(ObjectInitializer)
|
|
, bPreviewNeedsUpdate(false)
|
|
, bIsErrorExpression(false)
|
|
, bIsPreviewExpression(false)
|
|
{
|
|
}
|
|
|
|
void UMaterialGraphNode::PostCopyNode()
|
|
{
|
|
// Make sure the MaterialExpression goes back to being owned by the Material after copying.
|
|
ResetMaterialExpressionOwner();
|
|
}
|
|
|
|
FMaterialRenderProxy* UMaterialGraphNode::GetExpressionPreview()
|
|
{
|
|
return FMaterialEditorUtilities::GetExpressionPreview(GetGraph(), MaterialExpression);
|
|
}
|
|
|
|
void UMaterialGraphNode::RecreateAndLinkNode()
|
|
{
|
|
// Throw away the original pins
|
|
for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
|
|
{
|
|
UEdGraphPin* Pin = Pins[PinIndex];
|
|
Pin->Modify();
|
|
Pin->BreakAllPinLinks();
|
|
|
|
UEdGraphNode::DestroyPin(Pin);
|
|
}
|
|
Pins.Empty();
|
|
|
|
AllocateDefaultPins();
|
|
|
|
CastChecked<UMaterialGraph>(GetGraph())->LinkGraphNodesFromMaterial();
|
|
}
|
|
|
|
void UMaterialGraphNode::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
Super::PostEditChangeProperty(PropertyChangedEvent);
|
|
|
|
if (PropertyChangedEvent.Property)
|
|
{
|
|
const FName PropertyName = PropertyChangedEvent.Property->GetFName();
|
|
if (PropertyName == FName(TEXT("NodeComment")))
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
MaterialExpression->Modify();
|
|
MaterialExpression->Desc = NodeComment;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::PostEditImport()
|
|
{
|
|
// Make sure this MaterialExpression is owned by the Material it's being pasted into.
|
|
ResetMaterialExpressionOwner();
|
|
}
|
|
|
|
void UMaterialGraphNode::PostDuplicate(bool bDuplicateForPIE)
|
|
{
|
|
Super::PostDuplicate(bDuplicateForPIE);
|
|
|
|
if (!bDuplicateForPIE)
|
|
{
|
|
CreateNewGuid();
|
|
}
|
|
}
|
|
|
|
bool UMaterialGraphNode::CanPasteHere(const UEdGraph* TargetGraph) const
|
|
{
|
|
if (Super::CanPasteHere(TargetGraph))
|
|
{
|
|
const UMaterialGraph* MaterialGraph = Cast<const UMaterialGraph>(TargetGraph);
|
|
if (MaterialGraph)
|
|
{
|
|
// Check whether we're trying to paste a material function into a function that depends on it
|
|
UMaterialExpressionMaterialFunctionCall* FunctionExpression = Cast<UMaterialExpressionMaterialFunctionCall>(MaterialExpression);
|
|
bool bIsValidFunctionExpression = true;
|
|
|
|
if (MaterialGraph->MaterialFunction
|
|
&& FunctionExpression
|
|
&& FunctionExpression->MaterialFunction
|
|
&& FunctionExpression->MaterialFunction->IsDependent(MaterialGraph->MaterialFunction))
|
|
{
|
|
bIsValidFunctionExpression = false;
|
|
}
|
|
|
|
if (bIsValidFunctionExpression && MaterialExpression && IsAllowedExpressionType(MaterialExpression->GetClass(), MaterialGraph->MaterialFunction != NULL))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
FText UMaterialGraphNode::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
TArray<FString> Captions;
|
|
MaterialExpression->GetCaption(Captions);
|
|
|
|
if (TitleType == ENodeTitleType::EditableTitle)
|
|
{
|
|
return FText::FromString(GetParameterName());
|
|
}
|
|
else if (TitleType == ENodeTitleType::ListView || TitleType == ENodeTitleType::MenuTitle)
|
|
{
|
|
return FText::FromString(MaterialExpression->GetClass()->GetDescription());
|
|
}
|
|
else
|
|
{
|
|
// More useful to display multi line parameter captions in reverse order
|
|
// TODO: May have to choose order based on expression type if others need correct order
|
|
int32 CaptionIndex = Captions.Num() -1;
|
|
|
|
FTextBuilder NodeTitle;
|
|
NodeTitle.AppendLine(Captions[CaptionIndex]);
|
|
|
|
for (; CaptionIndex > 0; )
|
|
{
|
|
CaptionIndex--;
|
|
NodeTitle.AppendLine(Captions[CaptionIndex]);
|
|
}
|
|
|
|
if ( MaterialExpression->bShaderInputData && (MaterialExpression->bHidePreviewWindow || MaterialExpression->bCollapsed))
|
|
{
|
|
if (MaterialExpression->IsA<UMaterialExpressionTextureProperty>())
|
|
{
|
|
NodeTitle.AppendLine(LOCTEXT("TextureProperty", "Texture Property"));
|
|
}
|
|
else if (MaterialExpression->IsA<UMaterialExpressionViewProperty>())
|
|
{
|
|
NodeTitle.AppendLine(LOCTEXT("ViewProperty", "View Property"));
|
|
}
|
|
else
|
|
{
|
|
NodeTitle.AppendLine(LOCTEXT("InputData", "Input Data"));
|
|
}
|
|
}
|
|
|
|
if (bIsPreviewExpression)
|
|
{
|
|
NodeTitle.AppendLine();
|
|
NodeTitle.AppendLine(LOCTEXT("PreviewExpression", "Previewing"));
|
|
}
|
|
|
|
return NodeTitle.ToText();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
FText UMaterialGraphNode::GetTooltipText() const
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
TArray<FString> ToolTips;
|
|
MaterialExpression->GetExpressionToolTip(ToolTips);
|
|
|
|
if (ToolTips.Num() > 0)
|
|
{
|
|
FString ToolTip = ToolTips[0];
|
|
|
|
for (int32 Index = 1; Index < ToolTips.Num(); ++Index)
|
|
{
|
|
ToolTip += TEXT("\n");
|
|
ToolTip += ToolTips[Index];
|
|
}
|
|
|
|
return FText::FromString(ToolTip);
|
|
}
|
|
}
|
|
return FText::GetEmpty();
|
|
}
|
|
|
|
void UMaterialGraphNode::PrepareForCopying()
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
// Temporarily take ownership of the MaterialExpression, so that it is not deleted when cutting
|
|
MaterialExpression->Rename(NULL, this, REN_DontCreateRedirectors);
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::GetContextMenuActions(const FGraphNodeContextMenuBuilder& Context) const
|
|
{
|
|
UMaterialGraph* MaterialGraph = CastChecked<UMaterialGraph>(GetGraph());
|
|
|
|
if (Context.Node)
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
if (MaterialExpression->IsA(UMaterialExpressionTextureBase::StaticClass()))
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().UseCurrentTexture);
|
|
|
|
// Add a 'Convert To Texture' option for convertible types
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenu0");
|
|
{
|
|
if ( MaterialExpression->IsA(UMaterialExpressionTextureSample::StaticClass()))
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().ConvertToTextureObjects);
|
|
}
|
|
else if ( MaterialExpression->IsA(UMaterialExpressionTextureObject::StaticClass()))
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().ConvertToTextureSamples);
|
|
}
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
}
|
|
|
|
// Add a 'Convert To Parameter' option for convertible types
|
|
if (MaterialExpression->IsA(UMaterialExpressionConstant::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionConstant2Vector::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionConstant3Vector::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionConstant4Vector::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionTextureSample::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionComponentMask::StaticClass()))
|
|
{
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenu1");
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().ConvertObjects);
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
}
|
|
|
|
// Add a 'Convert To Constant' option for convertible types
|
|
if (MaterialExpression->IsA(UMaterialExpressionScalarParameter::StaticClass())
|
|
|| MaterialExpression->IsA(UMaterialExpressionVectorParameter::StaticClass()))
|
|
{
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenu1");
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().ConvertToConstant);
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
}
|
|
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenu2");
|
|
{
|
|
// Don't show preview option for bools
|
|
if (!MaterialExpression->IsA(UMaterialExpressionStaticBool::StaticClass())
|
|
&& !MaterialExpression->IsA(UMaterialExpressionStaticBoolParameter::StaticClass()))
|
|
{
|
|
// Add a preview node option if only one node is selected
|
|
if (bIsPreviewExpression)
|
|
{
|
|
// If we are already previewing the selected node, the menu option should tell the user that this will stop previewing
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().StopPreviewNode);
|
|
}
|
|
else
|
|
{
|
|
// The menu option should tell the user this node will be previewed.
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().StartPreviewNode);
|
|
}
|
|
}
|
|
|
|
if (MaterialExpression->bRealtimePreview)
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().DisableRealtimePreviewNode);
|
|
}
|
|
else
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().EnableRealtimePreviewNode);
|
|
}
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
}
|
|
|
|
// Break all links
|
|
Context.MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().BreakNodeLinks);
|
|
|
|
// Separate the above frequently used options from the below less frequently used common options
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenu3");
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry( FGenericCommands::Get().Delete );
|
|
Context.MenuBuilder->AddMenuEntry( FGenericCommands::Get().Cut );
|
|
Context.MenuBuilder->AddMenuEntry( FGenericCommands::Get().Copy );
|
|
Context.MenuBuilder->AddMenuEntry( FGenericCommands::Get().Duplicate );
|
|
|
|
// Select upstream and downstream nodes
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().SelectDownstreamNodes);
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().SelectUpstreamNodes);
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenuDocumentation");
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FGraphEditorCommands::Get().GoToDocumentation);
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
|
|
// Handle the favorites options
|
|
if (MaterialExpression)
|
|
{
|
|
Context.MenuBuilder->BeginSection("MaterialEditorMenuFavorites");
|
|
{
|
|
if (FMaterialEditorUtilities::IsMaterialExpressionInFavorites(MaterialExpression))
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().RemoveFromFavorites);
|
|
}
|
|
else
|
|
{
|
|
Context.MenuBuilder->AddMenuEntry(FMaterialEditorCommands::Get().AddToFavorites);
|
|
}
|
|
}
|
|
Context.MenuBuilder->EndSection();
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::CreateInputPins()
|
|
{
|
|
const TArray<FExpressionInput*> ExpressionInputs = MaterialExpression->GetInputs();
|
|
|
|
for (int32 Index = 0; Index < ExpressionInputs.Num() ; ++Index)
|
|
{
|
|
FExpressionInput* Input = ExpressionInputs[Index];
|
|
FString InputName = MaterialExpression->GetInputName(Index);
|
|
|
|
// Shorten long expression input names.
|
|
if ( !FCString::Stricmp( *InputName, TEXT("Coordinates") ) )
|
|
{
|
|
InputName = TEXT("UVs");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("TextureObject") ) )
|
|
{
|
|
InputName = TEXT("Tex");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("Input") ) )
|
|
{
|
|
InputName = TEXT("");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("Exponent") ) )
|
|
{
|
|
InputName = TEXT("Exp");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("AGreaterThanB") ) )
|
|
{
|
|
InputName = TEXT("A > B");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("AEqualsB") ) )
|
|
{
|
|
InputName = TEXT("A == B");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("ALessThanB") ) )
|
|
{
|
|
InputName = TEXT("A < B");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("MipLevel") ) )
|
|
{
|
|
InputName = TEXT("Level");
|
|
}
|
|
else if ( !FCString::Stricmp( *InputName, TEXT("MipBias") ) )
|
|
{
|
|
InputName = TEXT("Bias");
|
|
}
|
|
|
|
const UMaterialGraphSchema* Schema = CastChecked<UMaterialGraphSchema>(GetSchema());
|
|
FString PinCategory = MaterialExpression->IsInputConnectionRequired(Index) ? Schema->PC_Required : Schema->PC_Optional;
|
|
FString PinSubCategory = TEXT("");
|
|
|
|
UEdGraphPin* NewPin = CreatePin(EGPD_Input, PinCategory, PinSubCategory, NULL, /*bIsArray=*/ false, /*bIsReference=*/ false, InputName);
|
|
if (NewPin->PinName.IsEmpty())
|
|
{
|
|
// Makes sure pin has a name for lookup purposes but user will never see it
|
|
NewPin->PinName = CreateUniquePinName(TEXT("Input"));
|
|
NewPin->PinFriendlyName = FText::FromString(TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::CreateOutputPins()
|
|
{
|
|
TArray<FExpressionOutput>& Outputs = MaterialExpression->GetOutputs();
|
|
|
|
for( int32 Index = 0 ; Index < Outputs.Num() ; ++Index )
|
|
{
|
|
const FExpressionOutput& ExpressionOutput = Outputs[Index];
|
|
FString PinCategory = TEXT("");
|
|
FString PinSubCategory = TEXT("");
|
|
FString OutputName = TEXT("");
|
|
|
|
const UMaterialGraphSchema* Schema = CastChecked<UMaterialGraphSchema>(GetSchema());
|
|
|
|
if( ExpressionOutput.Mask )
|
|
{
|
|
PinCategory = Schema->PC_Mask;
|
|
|
|
if ( ExpressionOutput.MaskR && !ExpressionOutput.MaskG && !ExpressionOutput.MaskB && !ExpressionOutput.MaskA)
|
|
{
|
|
PinSubCategory = Schema->PSC_Red;
|
|
}
|
|
else if (!ExpressionOutput.MaskR && ExpressionOutput.MaskG && !ExpressionOutput.MaskB && !ExpressionOutput.MaskA)
|
|
{
|
|
PinSubCategory = Schema->PSC_Green;
|
|
}
|
|
else if (!ExpressionOutput.MaskR && !ExpressionOutput.MaskG && ExpressionOutput.MaskB && !ExpressionOutput.MaskA)
|
|
{
|
|
PinSubCategory = Schema->PSC_Blue;
|
|
}
|
|
else if (!ExpressionOutput.MaskR && !ExpressionOutput.MaskG && !ExpressionOutput.MaskB && ExpressionOutput.MaskA)
|
|
{
|
|
PinSubCategory = Schema->PSC_Alpha;
|
|
}
|
|
}
|
|
|
|
if (MaterialExpression->bShowOutputNameOnPin)
|
|
{
|
|
OutputName = ExpressionOutput.OutputName;
|
|
}
|
|
|
|
UEdGraphPin* NewPin = CreatePin(EGPD_Output, PinCategory, PinSubCategory, NULL, /*bIsArray=*/ false, /*bIsReference=*/ false, OutputName);
|
|
if (NewPin->PinName.IsEmpty())
|
|
{
|
|
// Makes sure pin has a name for lookup purposes but user will never see it
|
|
NewPin->PinName = CreateUniquePinName(TEXT("Output"));
|
|
NewPin->PinFriendlyName = FText::FromString(TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
|
|
int32 UMaterialGraphNode::GetOutputIndex(const UEdGraphPin* OutputPin)
|
|
{
|
|
TArray<UEdGraphPin*> OutputPins;
|
|
GetOutputPins(OutputPins);
|
|
|
|
for (int32 Index = 0; Index < OutputPins.Num(); ++Index)
|
|
{
|
|
if (OutputPin == OutputPins[Index])
|
|
{
|
|
return Index;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
uint32 UMaterialGraphNode::GetOutputType(const UEdGraphPin* OutputPin)
|
|
{
|
|
return MaterialExpression->GetOutputType(GetOutputIndex(OutputPin));
|
|
}
|
|
|
|
int32 UMaterialGraphNode::GetInputIndex(const UEdGraphPin* InputPin) const
|
|
{
|
|
TArray<UEdGraphPin*> InputPins;
|
|
GetInputPins(InputPins);
|
|
|
|
for (int32 Index = 0; Index < InputPins.Num(); ++Index)
|
|
{
|
|
if (InputPin == InputPins[Index])
|
|
{
|
|
return Index;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
uint32 UMaterialGraphNode::GetInputType(const UEdGraphPin* InputPin) const
|
|
{
|
|
return MaterialExpression->GetInputType(GetInputIndex(InputPin));
|
|
}
|
|
|
|
void UMaterialGraphNode::ResetMaterialExpressionOwner()
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
// Ensures MaterialExpression is owned by the Material or Function
|
|
UMaterialGraph* MaterialGraph = CastChecked<UMaterialGraph>(GetGraph());
|
|
UObject* ExpressionOuter = MaterialGraph->Material;
|
|
if (MaterialGraph->MaterialFunction)
|
|
{
|
|
ExpressionOuter = MaterialGraph->MaterialFunction;
|
|
}
|
|
MaterialExpression->Rename(NULL, ExpressionOuter, REN_DontCreateRedirectors);
|
|
|
|
// Set up the back pointer for newly created material nodes
|
|
MaterialExpression->GraphNode = this;
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::PostPlacedNewNode()
|
|
{
|
|
if (MaterialExpression)
|
|
{
|
|
NodeComment = MaterialExpression->Desc;
|
|
bCommentBubbleVisible = MaterialExpression->bCommentBubbleVisible;
|
|
NodePosX = MaterialExpression->MaterialExpressionEditorX;
|
|
NodePosY = MaterialExpression->MaterialExpressionEditorY;
|
|
bCanRenameNode = MaterialExpression->CanRenameNode();
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::NodeConnectionListChanged()
|
|
{
|
|
Super::NodeConnectionListChanged();
|
|
|
|
const UEdGraphSchema* Schema = GetSchema();
|
|
if (Schema != nullptr)
|
|
{
|
|
Schema->ForceVisualizationCacheClear();
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::OnRenameNode(const FString& NewName)
|
|
{
|
|
MaterialExpression->Modify();
|
|
SetParameterName(NewName);
|
|
MaterialExpression->MarkPackageDirty();
|
|
MaterialDirtyDelegate.ExecuteIfBound();
|
|
}
|
|
|
|
void UMaterialGraphNode::OnUpdateCommentText( const FString& NewComment )
|
|
{
|
|
const FScopedTransaction Transaction( LOCTEXT( "CommentCommitted", "Comment Changed" ) );
|
|
// Update the Node comment
|
|
Modify();
|
|
NodeComment = NewComment;
|
|
// Update the Material Expresssion desc to match the comment
|
|
if( MaterialExpression )
|
|
{
|
|
MaterialExpression->Modify();
|
|
MaterialExpression->Desc = NewComment;
|
|
MaterialDirtyDelegate.ExecuteIfBound();
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::OnCommentBubbleToggled( bool bInCommentBubbleVisible )
|
|
{
|
|
if ( MaterialExpression )
|
|
{
|
|
MaterialExpression->Modify();
|
|
MaterialExpression->bCommentBubbleVisible = bInCommentBubbleVisible;
|
|
MaterialDirtyDelegate.ExecuteIfBound();
|
|
}
|
|
}
|
|
|
|
void UMaterialGraphNode::GetPinHoverText(const UEdGraphPin& Pin, FString& HoverTextOut) const
|
|
{
|
|
Super::GetPinHoverText(Pin, HoverTextOut);
|
|
|
|
if (HoverTextOut.IsEmpty())
|
|
{
|
|
TArray<FString> ToolTips;
|
|
|
|
int32 DirIndex = -1;
|
|
int32 PinIndex = INDEX_NONE;
|
|
for (int32 Index = 0; Index < Pins.Num(); ++Index)
|
|
{
|
|
if (Pin.Direction == Pins[Index]->Direction)
|
|
{
|
|
++DirIndex;
|
|
if (Pins[Index] == &Pin)
|
|
{
|
|
PinIndex = DirIndex;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Pin.Direction == EEdGraphPinDirection::EGPD_Input)
|
|
{
|
|
MaterialExpression->GetConnectorToolTip(PinIndex, INDEX_NONE, ToolTips);
|
|
}
|
|
else
|
|
{
|
|
MaterialExpression->GetConnectorToolTip(INDEX_NONE, PinIndex, ToolTips);
|
|
}
|
|
|
|
if (ToolTips.Num() > 0)
|
|
{
|
|
HoverTextOut = ToolTips[0];
|
|
|
|
for (int32 Index = 1; Index < ToolTips.Num(); ++Index)
|
|
{
|
|
HoverTextOut += TEXT("\n");
|
|
HoverTextOut += ToolTips[Index];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FString UMaterialGraphNode::GetParameterName() const
|
|
{
|
|
return MaterialExpression->GetEditableName();
|
|
}
|
|
|
|
void UMaterialGraphNode::SetParameterName(const FString& NewName)
|
|
{
|
|
MaterialExpression->SetEditableName(NewName);
|
|
|
|
//@TODO: Push into the SetEditableName interface
|
|
CastChecked<UMaterialGraph>(GetGraph())->Material->UpdateExpressionParameterName(MaterialExpression);
|
|
}
|
|
|
|
bool UMaterialGraphNode::UsesBoolColour(UMaterialExpression* Expression)
|
|
{
|
|
if (Expression->IsA<UMaterialExpressionStaticBool>())
|
|
{
|
|
return true;
|
|
}
|
|
// Explicitly check for bool param as switch params inherit from it
|
|
else if (Expression->GetClass() == UMaterialExpressionStaticBoolParameter::StaticClass())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UMaterialGraphNode::UsesFloatColour(UMaterialExpression* Expression)
|
|
{
|
|
if (Expression->IsA<UMaterialExpressionConstant>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionScalarParameter>())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UMaterialGraphNode::UsesVectorColour(UMaterialExpression* Expression)
|
|
{
|
|
if (Expression->IsA<UMaterialExpressionConstant2Vector>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionConstant3Vector>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionConstant4Vector>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionVectorParameter>())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UMaterialGraphNode::UsesObjectColour(UMaterialExpression* Expression)
|
|
{
|
|
if (Expression->IsA<UMaterialExpressionTextureBase>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionFontSample>())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool UMaterialGraphNode::UsesEventColour(UMaterialExpression* Expression)
|
|
{
|
|
if (Expression->bShaderInputData && !Expression->IsA<UMaterialExpressionStaticBool>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionFunctionInput>())
|
|
{
|
|
return true;
|
|
}
|
|
else if (Expression->IsA<UMaterialExpressionTextureCoordinate>())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FString UMaterialGraphNode::GetDocumentationExcerptName() const
|
|
{
|
|
// Default the node to searching for an excerpt named for the C++ node class name, including the U prefix.
|
|
// This is done so that the excerpt name in the doc file can be found by find-in-files when searching for the full class name.
|
|
UClass* MyClass = (MaterialExpression != NULL) ? MaterialExpression->GetClass() : this->GetClass();
|
|
return FString::Printf(TEXT("%s%s"), MyClass->GetPrefixCPP(), *MyClass->GetName());
|
|
}
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|