Files
UnrealEngineUWP/Engine/Source/Editor/BlueprintGraph/Private/BlueprintNodeTemplateCache.cpp

525 lines
19 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "BlueprintNodeTemplateCache.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "Engine/Blueprint.h"
#include "UObject/UObjectHash.h"
#include "UObject/MetaData.h"
#include "GameFramework/Actor.h"
#include "Animation/AnimBlueprint.h"
#include "Engine/BlueprintGeneratedClass.h"
#include "Animation/AnimBlueprintGeneratedClass.h"
#include "EdGraph/EdGraphSchema.h"
#include "EdGraph/EdGraph.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "Kismet2/BlueprintEditorUtils.h"
#include "Animation/AnimInstance.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "Kismet2/KismetEditorUtilities.h"
#include "BlueprintEditorSettings.h"
DEFINE_LOG_CATEGORY_STATIC(LogBlueprintNodeCache, Log, All);
/*******************************************************************************
* Static FBlueprintNodeTemplateCache Helpers
******************************************************************************/
namespace BlueprintNodeTemplateCacheImpl
{
/** */
static int32 ActiveMemFootprint = 0;
/** Used to track the average blueprint size (so that we can try to predict when a blueprint would fail to be cached) */
static int32 MadeBlueprintCount = 0;
static int32 AverageBlueprintSize = 0;
/** Metadata tag used to identify graphs created by this system. */
static const FName TemplateGraphMetaTag(TEXT("NodeTemplateCache_Graph"));
/**
* Checks to see if this node is compatible with the given graph (to know if
* a node template can be spawned within it).
*
* @param NodeObj The CDO of the node you want to spawn.
* @param Graph The graph you want to check compatibility for.
* @return True if the node and graph are compatible (for templating purposes).
*/
static bool IsCompatible(UEdGraphNode* NodeObj, UEdGraph* Graph);
/**
* Looks through a blueprint for compatible graphs (ones that the specified
* node can spawn into).
*
* @param BlueprintOuter The blueprint to search through.
* @param NodeObj The CDO of the node you want to spawn.
* @param IsCompatibleFunc An option callback function to further filter out incompatible nodes.
* @return The first compatible graph found (null if no graph was found).
*/
static UEdGraph* FindCompatibleGraph(UBlueprint* BlueprintOuter, UEdGraphNode* NodeObj, bool(*IsCompatibleFunc)(UEdGraph*) = nullptr);
/**
* Creates a transient, temporary blueprint. Intended to be used as a
* template-node's outer (grandparent).
*
* @param BlueprintClass The class of blueprint to make.
* @param ParentClass The class type of blueprint to make (actor, object, etc.).
* @param GeneratedClassType The type of class that the blueprint should generate.
* @return A newly spawned (transient) blueprint.
*/
static UBlueprint* MakeCompatibleBlueprint(TSubclassOf<UBlueprint> BlueprintClass, UClass* ParentClass, TSubclassOf<UBlueprintGeneratedClass> GeneratedClassType);
/**
* Creates a new transient graph, for template node use (meant to be used as
* a template node's outer).
*
* @param BlueprintOuter The blueprint to nest the new graph under.
* @param SchemaClass The schema to assign the new graph.
* @return A newly created graph.
*/
static UEdGraph* AddGraph(UBlueprint* BlueprintOuter, TSubclassOf<UEdGraphSchema> SchemaClass);
/**
* Adds metadata to the supplied graph, flagging it as a graph belonging to
* the BlueprintNodeTemplateCache (so we can easily identify it later on).
*
* @param NewGraph The graph to flag.
*/
static void MarkGraphForTemplateUse(UEdGraph* NewGraph);
/**
* Determines if the specified graph is one that was allocated by
* BlueprintNodeTemplateCache (to house template nodes).
*
* @param ParentGraph The graph you want checked.
* @return True if this graph belongs to a BlueprintNodeTemplateCache, false if not.
*/
static bool IsTemplateOuter(UEdGraph* ParentGraph);
/**
* Converts the cache memory cap into bytes (form user settings).
*
* @return The user defined cache cap (in bytes).
*/
static int32 GetCacheCapSize();
/**
* Totals the size of the specified object, along with any other objects
* that have it in their outer chain. Does not account for any allocated
* memory that belongs to the object(s).
*
* @param Object The object you want an estimated byte size for.
* @return An estimated size (in bytes)... currently does not account for any allocated memory that the object may be responsible for.
*/
static int32 ApproximateMemFootprint(UObject const* Object);
}
//------------------------------------------------------------------------------
static bool BlueprintNodeTemplateCacheImpl::IsCompatible(UEdGraphNode* NodeObj, UEdGraph* Graph)
{
Merging //UE4/Release-4.11 to //UE4/Main (up to CL#2835147) ========================== MAJOR FEATURES + CHANGES ========================== Change 2817214 on 2016/01/06 by mason.seay Adjusted Walkable Slope Override for mesh #jira UE-24473 Change 2817384 on 2016/01/06 by Michael.Schoell Crash fix when selecting a variable node for a variable that is not owned by a Blueprint. #jira UE-24958 - Crash when getting the sequence player in level blueprint Change 2817438 on 2016/01/06 by Max.Chen Sequencer: Add option to specify position of material name from the movie scene capture interface. For example, MovieCapture_{material}_{width}x{height}.{frame} will create files like this: MovieCapture_FinalImage_1920x1080.0010.exr #rb Andrew.Rodham #jira UE-24926 Change 2817459 on 2016/01/06 by Marc.Audy PR #1679: Move MinRespawnDelay to virtual method AController::GetMinRespawnDelay() (Contributed by bozaro) #jira UE-22309 Change 2817472 on 2016/01/06 by Ben.Marsh Always run UHT in unattended mode from UBT; we don't want it opening any dialogs. Match3 is currently missing a plugin, and it's causing builds to time out. Change 2817473 on 2016/01/06 by Marc.Audy PR #1644: Improve "SpawnActor failed because the spawned actor IsPendingKill" error message (Contributed by slonopotamus) #jira UE-21911 Change 2817533 on 2016/01/06 by Lauren.Ridge Fixing Match3 not compiling in Debug (removed two checks on TileLibrary) #jira UE-25004 Change 2817625 on 2016/01/06 by Taizyd.Korambayil #jira UE-19659 Reimported Template Animations with Proper Skeletons Change 2817647 on 2016/01/06 by Lukasz.Furman replaced ensure during initialization of blackboard based behavior tree task with log warning #ue4 #jira UE-24448 #rb Mieszko.Zielinski Change 2817648 on 2016/01/06 by Lukasz.Furman fixed broken rendering component of navmesh actor after delete-undo operation #ue4 #jira UE-24446 #rb Mieszko.Zielinski Change 2817688 on 2016/01/06 by Taizyd.Korambayil #jira UE-22347 Fixed Message Warnings on Startup Change 2817815 on 2016/01/06 by Jamie.Dale Multiple fixes when editing right-to-left text - Text is now shaped over the entire line to allow rich-text and selected text to be shaped correctly across block boundaries. - Text layout highlights are now able to correctly handle bi-directional and right-to-left text. - Text picking can now handle bi-directional and right-to-left text. - Text picking can now pick the individual characters that make up a ligature glyph. - The caret now draws on the logical (rather than visual) side of the glyph (to handle right-to-left text). - Glyph clusters (multiple glyphs produced from a single character) are now treated as a single logical glyph. - Optimized some of the FShapedGlyphSequence to allow an early out once they've found and processed the start and end glyphs. #jira UE-25013 Change 2817828 on 2016/01/06 by Nick.Darnell Editor - Fixing the OpenLauncher call to be take a structure to allow us to customize it more, and to properly handle the silent command the way we're planning to handle it in the launcher. #jira UE-24563 Change 2818052 on 2016/01/06 by Nick.Darnell Editor - Adding another application check for the launcher to catch the current app name on mac. #jira UE-24563 Change 2818149 on 2016/01/06 by Taizyd.Korambayil #jira UE-19097 Adjusted FirstPerson Pawn, so that Camera doesnt clip the Arm Mesh Change 2818360 on 2016/01/06 by Chris.Babcock Fix reading from ini sections not cached after build system changes for 4.11 #jira UE-25027 #ue4 #android Change 2818369 on 2016/01/06 by Ryan.Vance #jira UE-24976 Adding tessellation support to instanced stereo Change 2818999 on 2016/01/07 by Robert.Manuszewski UHT will no longer try to load game-only plugins. #jira UE-25032 - Changed module type RuntimeNoProgram to RuntimeAndProgram so that bu default Runtime plugin modules won't be loaded by programs - Added better error message when UHT's PreInit fails Change 2819064 on 2016/01/07 by Richard.Hinckley #jira UE-24694 Fixing array usage in 4.11 stream. Change 2819067 on 2016/01/07 by Ori.Cohen When editor tries to spawn a physics asset we automatically load the needed skeletal mesh #rb Matt.K #JIRA UE-24165
2016-01-22 08:13:18 -05:00
const UEdGraphSchema* Schema = Graph->GetSchema();
return ensureMsgf(Schema != nullptr, TEXT("PROTO_BP graph with invalid schema: %s "), *Graph->GetName()) &&
NodeObj->CanCreateUnderSpecifiedSchema(Schema);
}
//------------------------------------------------------------------------------
static UEdGraph* BlueprintNodeTemplateCacheImpl::FindCompatibleGraph(UBlueprint* BlueprintOuter, UEdGraphNode* NodeObj, bool(*IsCompatibleFunc)(UEdGraph*))
{
UEdGraph* FoundGraph = nullptr;
TArray<UObject*> BlueprintChildObjs;
GetObjectsWithOuter(BlueprintOuter, BlueprintChildObjs, /*bIncludeNestedObjects =*/false, /*ExclusionFlags =*/ RF_NoFlags, /** InternalExcludeFlags */ EInternalObjectFlags::Garbage);
for (UObject* Child : BlueprintChildObjs)
{
UEdGraph* ChildGraph = Cast<UEdGraph>(Child);
bool bIsCompatible = (ChildGraph != nullptr) && IsCompatible(NodeObj, ChildGraph);
if (bIsCompatible && (IsCompatibleFunc != nullptr))
{
bIsCompatible = IsCompatibleFunc(ChildGraph);
}
if (bIsCompatible)
{
FoundGraph = ChildGraph;
break;
}
}
return FoundGraph;
}
//------------------------------------------------------------------------------
static UBlueprint* BlueprintNodeTemplateCacheImpl::MakeCompatibleBlueprint(TSubclassOf<UBlueprint> BlueprintClass, UClass* ParentClass, TSubclassOf<UBlueprintGeneratedClass> GeneratedClassType)
{
EBlueprintType BlueprintType = BPTYPE_Normal;
// @TODO: BPTYPE_LevelScript requires a level outer, which we don't want to have here... can we get away without it?
// if (BlueprintClass->IsChildOf<ULevelScriptBlueprint>())
// {
// BlueprintType = BPTYPE_LevelScript;
// }
if (GeneratedClassType == nullptr)
{
GeneratedClassType = UBlueprintGeneratedClass::StaticClass();
}
UPackage* BlueprintOuter = GetTransientPackage();
FString const DesiredName = FString::Printf(TEXT("PROTO_BP_%s"), *BlueprintClass->GetName());
FName const BlueprintName = MakeUniqueObjectName(BlueprintOuter, BlueprintClass, FName(*DesiredName));
BlueprintClass = FBlueprintEditorUtils::FindFirstNativeClass(BlueprintClass);
UBlueprint* NewBlueprint = FKismetEditorUtilities::CreateBlueprint(ParentClass, BlueprintOuter, BlueprintName, BlueprintType, BlueprintClass, GeneratedClassType);
NewBlueprint->SetFlags(RF_Transient);
++MadeBlueprintCount;
float const AproxBlueprintSize = ApproximateMemFootprint(NewBlueprint);
// track the average blueprint size, so that we can attempt to predict
// whether a blueprint will fail to be cached (when the cache is near full)
AverageBlueprintSize = AverageBlueprintSize * ((float)(MadeBlueprintCount-1) / MadeBlueprintCount) +
(AproxBlueprintSize / MadeBlueprintCount) + 0.5f;
return NewBlueprint;
}
//------------------------------------------------------------------------------
static UEdGraph* BlueprintNodeTemplateCacheImpl::AddGraph(UBlueprint* BlueprintOuter, TSubclassOf<UEdGraphSchema> SchemaClass)
{
UClass* GraphClass = UEdGraph::StaticClass();
FName const GraphName = MakeUniqueObjectName(BlueprintOuter, GraphClass, FName(TEXT("TEMPLATE_NODE_OUTER")));
UEdGraph* NewGraph = NewObject<UEdGraph>(BlueprintOuter, GraphClass, GraphName, RF_Transient);
NewGraph->Schema = SchemaClass;
MarkGraphForTemplateUse(NewGraph);
return NewGraph;
}
//------------------------------------------------------------------------------
static void BlueprintNodeTemplateCacheImpl::MarkGraphForTemplateUse(UEdGraph* NewGraph)
{
UPackage* TemplatePackage = NewGraph->GetOutermost();
UMetaData* PackageMetadata = TemplatePackage->GetMetaData();
PackageMetadata->SetValue(NewGraph, TemplateGraphMetaTag, TEXT("true"));
}
//------------------------------------------------------------------------------
bool BlueprintNodeTemplateCacheImpl::IsTemplateOuter(UEdGraph* ParentGraph)
{
if (ParentGraph->HasAnyFlags(RF_Transactional))
{
UPackage* GraphPackage = ParentGraph->GetOutermost();
UMetaData* PackageMetadata = GraphPackage->GetMetaData();
return PackageMetadata->HasValue(ParentGraph, TemplateGraphMetaTag);
}
return false;
}
//------------------------------------------------------------------------------
static int32 BlueprintNodeTemplateCacheImpl::GetCacheCapSize()
{
UBlueprintEditorSettings const* BpSettings = GetDefault<UBlueprintEditorSettings>();
// have to convert from MB to bytes
return (BpSettings->NodeTemplateCacheCapMB * 1024.f * 1024.f) + 0.5f;
}
//------------------------------------------------------------------------------
static int32 BlueprintNodeTemplateCacheImpl::ApproximateMemFootprint(UObject const* Object)
{
TArray<UObject*> ChildObjs;
GetObjectsWithOuter(Object, ChildObjs, /*bIncludeNestedObjects =*/true);
int32 ApproimateDataSize = sizeof(*Object);
for (UObject* ChildObj : ChildObjs)
{
// @TODO: doesn't account for any internal allocated memory (for member TArrays, etc.)
ApproimateDataSize += sizeof(*ChildObj);
}
return ApproimateDataSize;
}
/*******************************************************************************
* FBlueprintNodeTemplateCache
******************************************************************************/
//------------------------------------------------------------------------------
FBlueprintNodeTemplateCache::FBlueprintNodeTemplateCache()
: ApproximateObjectMem(0)
{
using namespace BlueprintNodeTemplateCacheImpl; // for MakeCompatibleBlueprint()
UBlueprint* StandardBlueprint = MakeCompatibleBlueprint(UBlueprint::StaticClass(), AActor::StaticClass(), UBlueprintGeneratedClass::StaticClass());
CacheBlueprintOuter(StandardBlueprint);
UBlueprint* AnimBlueprint = MakeCompatibleBlueprint(UAnimBlueprint::StaticClass(), UAnimInstance::StaticClass(), UAnimBlueprintGeneratedClass::StaticClass());
CacheBlueprintOuter(AnimBlueprint);
}
//------------------------------------------------------------------------------
UEdGraphNode* FBlueprintNodeTemplateCache::GetNodeTemplate(UBlueprintNodeSpawner const* NodeSpawner, UEdGraph* TargetGraph)
{
using namespace BlueprintNodeTemplateCacheImpl;
bool bIsOverMemCap = false;
auto LogCacheFullMsg = [&bIsOverMemCap]()
{
if (!bIsOverMemCap)
{
static int32 LoggedCapSize = -1;
int32 const CurrentCacheSize = GetCacheCapSize();
// log only once for each cap size change
if (LoggedCapSize != CurrentCacheSize)
{
UE_LOG(LogBlueprintNodeCache, Display, TEXT("The blueprint template-node cache is full. As a result, you may experience interactions which are slower than normal. To avoid this, increase the cache's cap in the blueprint editor prefences."));
LoggedCapSize = CurrentCacheSize;
}
bIsOverMemCap = true;
}
};
UEdGraphNode* TemplateNode = nullptr;
if (UEdGraphNode** FoundNode = NodeTemplateCache.Find(NodeSpawner))
{
TemplateNode = *FoundNode;
}
else if (NodeSpawner->NodeClass != nullptr)
{
UEdGraphNode* NodeCDO = NodeSpawner->NodeClass->GetDefaultObject<UEdGraphNode>();
check(NodeCDO != nullptr);
UBlueprint* TargetBlueprint = nullptr;
TSubclassOf<UBlueprint> BlueprintClass;
bool const bHasTargetGraph = (TargetGraph != nullptr);
if (bHasTargetGraph)
{
// by the time we're asking for a prototype for this spawner, we should
// be sure that it is compatible with the TargetGraph
//check(IsCompatible(NodeCDO, TargetGraph));
TargetBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(TargetGraph);
check(TargetBlueprint != nullptr);
BlueprintClass = TargetBlueprint->GetClass();
// check used to help identify user interactable graphs (as opposed to
// intermediate/transient graphs).
auto IsCompatibleUserGraph = [](UEdGraph* Graph)->bool
{
return !Graph->HasAnyFlags(RF_Transient);
};
TargetGraph = FindCompatibleGraph(TargetBlueprint, NodeCDO, IsCompatibleUserGraph);
check(TargetGraph != nullptr);
}
UBlueprint* CompatibleBlueprint = nullptr;
UEdGraph* CompatibleOuter = nullptr;
// find a compatible outer (don't want to have to create a new one if we don't have to)
for (UBlueprint* Blueprint : TemplateOuters)
{
CompatibleOuter = FindCompatibleGraph(Blueprint, NodeCDO);
if (CompatibleOuter != nullptr)
{
MarkGraphForTemplateUse(CompatibleOuter);
}
if (CompatibleOuter != nullptr)
{
CompatibleBlueprint = Blueprint;
break;
}
else if ((BlueprintClass != nullptr) && Blueprint->GetClass()->IsChildOf(BlueprintClass))
{
CompatibleBlueprint = Blueprint;
}
}
// reset ActiveMemFootprint, so calls to CacheBlueprintOuter()/CacheTemplateNode()
// use the most up-to-date value (users could have since modified the
// nodes, so they could have grown in size... like with AllocateDefaultPins)
//
// @TODO: GetEstimateCacheSize() is (most likely) inaccurate, seeing as
// external systems mutate template-nodes (such as calling
// AllocateDefaultPins), and this returns a size estimate from
// when the node was first spawned (it is too slow to recalculate
// the size of the object hierarchy here)
ActiveMemFootprint = GetEstimateCacheSize();
int32 const CacheCapSize = GetCacheCapSize();
if (ActiveMemFootprint > CacheCapSize)
{
LogCacheFullMsg();
// @TODO: evict nodes until we're back under the cap (in case the cap
// was changed at runtime, or external user modified node sizes)
}
// if a TargetGraph was supplied, and we couldn't find a suitable outer
// for this template-node, then attempt to emulate that graph
if (bHasTargetGraph)
{
if (CompatibleBlueprint == nullptr)
{
// if the cache is near full, attempt to predict if this
// impending cache will fail (if so, we don't want to waste the
// cycles on allocating a temp blueprint)
if (!bIsOverMemCap && ((AverageBlueprintSize == 0) ||
(ActiveMemFootprint + AverageBlueprintSize <= CacheCapSize)))
{
TSubclassOf<UBlueprintGeneratedClass> GeneratedClassType = UBlueprintGeneratedClass::StaticClass();
if (TargetBlueprint->GeneratedClass != nullptr)
{
GeneratedClassType = TargetBlueprint->GeneratedClass->GetClass();
}
CompatibleBlueprint = MakeCompatibleBlueprint(BlueprintClass, TargetBlueprint->ParentClass, GeneratedClassType);
if (!CacheBlueprintOuter(CompatibleBlueprint))
{
LogCacheFullMsg();
}
// this graph may come default with a compatible graph
CompatibleOuter = FindCompatibleGraph(CompatibleBlueprint, NodeCDO);
if (CompatibleOuter != nullptr)
{
MarkGraphForTemplateUse(CompatibleOuter);
}
}
else
{
CompatibleBlueprint = TargetBlueprint;
CompatibleOuter = FindCompatibleGraph(TargetBlueprint, NodeCDO, &BlueprintNodeTemplateCacheImpl::IsTemplateOuter);
LogCacheFullMsg();
}
}
if (CompatibleOuter == nullptr)
{
CompatibleOuter = AddGraph(CompatibleBlueprint, TargetGraph->Schema);
Merging //UE4/Release-4.11 to //UE4/Main (up to CL#2835147) ========================== MAJOR FEATURES + CHANGES ========================== Change 2817214 on 2016/01/06 by mason.seay Adjusted Walkable Slope Override for mesh #jira UE-24473 Change 2817384 on 2016/01/06 by Michael.Schoell Crash fix when selecting a variable node for a variable that is not owned by a Blueprint. #jira UE-24958 - Crash when getting the sequence player in level blueprint Change 2817438 on 2016/01/06 by Max.Chen Sequencer: Add option to specify position of material name from the movie scene capture interface. For example, MovieCapture_{material}_{width}x{height}.{frame} will create files like this: MovieCapture_FinalImage_1920x1080.0010.exr #rb Andrew.Rodham #jira UE-24926 Change 2817459 on 2016/01/06 by Marc.Audy PR #1679: Move MinRespawnDelay to virtual method AController::GetMinRespawnDelay() (Contributed by bozaro) #jira UE-22309 Change 2817472 on 2016/01/06 by Ben.Marsh Always run UHT in unattended mode from UBT; we don't want it opening any dialogs. Match3 is currently missing a plugin, and it's causing builds to time out. Change 2817473 on 2016/01/06 by Marc.Audy PR #1644: Improve "SpawnActor failed because the spawned actor IsPendingKill" error message (Contributed by slonopotamus) #jira UE-21911 Change 2817533 on 2016/01/06 by Lauren.Ridge Fixing Match3 not compiling in Debug (removed two checks on TileLibrary) #jira UE-25004 Change 2817625 on 2016/01/06 by Taizyd.Korambayil #jira UE-19659 Reimported Template Animations with Proper Skeletons Change 2817647 on 2016/01/06 by Lukasz.Furman replaced ensure during initialization of blackboard based behavior tree task with log warning #ue4 #jira UE-24448 #rb Mieszko.Zielinski Change 2817648 on 2016/01/06 by Lukasz.Furman fixed broken rendering component of navmesh actor after delete-undo operation #ue4 #jira UE-24446 #rb Mieszko.Zielinski Change 2817688 on 2016/01/06 by Taizyd.Korambayil #jira UE-22347 Fixed Message Warnings on Startup Change 2817815 on 2016/01/06 by Jamie.Dale Multiple fixes when editing right-to-left text - Text is now shaped over the entire line to allow rich-text and selected text to be shaped correctly across block boundaries. - Text layout highlights are now able to correctly handle bi-directional and right-to-left text. - Text picking can now handle bi-directional and right-to-left text. - Text picking can now pick the individual characters that make up a ligature glyph. - The caret now draws on the logical (rather than visual) side of the glyph (to handle right-to-left text). - Glyph clusters (multiple glyphs produced from a single character) are now treated as a single logical glyph. - Optimized some of the FShapedGlyphSequence to allow an early out once they've found and processed the start and end glyphs. #jira UE-25013 Change 2817828 on 2016/01/06 by Nick.Darnell Editor - Fixing the OpenLauncher call to be take a structure to allow us to customize it more, and to properly handle the silent command the way we're planning to handle it in the launcher. #jira UE-24563 Change 2818052 on 2016/01/06 by Nick.Darnell Editor - Adding another application check for the launcher to catch the current app name on mac. #jira UE-24563 Change 2818149 on 2016/01/06 by Taizyd.Korambayil #jira UE-19097 Adjusted FirstPerson Pawn, so that Camera doesnt clip the Arm Mesh Change 2818360 on 2016/01/06 by Chris.Babcock Fix reading from ini sections not cached after build system changes for 4.11 #jira UE-25027 #ue4 #android Change 2818369 on 2016/01/06 by Ryan.Vance #jira UE-24976 Adding tessellation support to instanced stereo Change 2818999 on 2016/01/07 by Robert.Manuszewski UHT will no longer try to load game-only plugins. #jira UE-25032 - Changed module type RuntimeNoProgram to RuntimeAndProgram so that bu default Runtime plugin modules won't be loaded by programs - Added better error message when UHT's PreInit fails Change 2819064 on 2016/01/07 by Richard.Hinckley #jira UE-24694 Fixing array usage in 4.11 stream. Change 2819067 on 2016/01/07 by Ori.Cohen When editor tries to spawn a physics asset we automatically load the needed skeletal mesh #rb Matt.K #JIRA UE-24165
2016-01-22 08:13:18 -05:00
ensureMsgf( CompatibleOuter->Schema != nullptr, TEXT("Invalid schema for template graph (from '%s :: %s')."),
*TargetBlueprint->GetName(), *TargetGraph->GetName() );
if (CompatibleBlueprint != TargetBlueprint)
{
int32 const ApproxGraphSize = ApproximateMemFootprint(CompatibleOuter);
ActiveMemFootprint += ApproxGraphSize;
ApproximateObjectMem += ApproxGraphSize;
}
}
}
if (CompatibleOuter != nullptr)
{
TemplateNode = NodeSpawner->Invoke(CompatibleOuter, IBlueprintNodeBinder::FBindingSet(), FVector2D::ZeroVector);
if (!bIsOverMemCap && !CacheTemplateNode(NodeSpawner, TemplateNode))
{
LogCacheFullMsg();
}
}
}
return TemplateNode;
}
//------------------------------------------------------------------------------
UEdGraphNode* FBlueprintNodeTemplateCache::GetNodeTemplate(UBlueprintNodeSpawner const* NodeSpawner, ENoInit) const
{
UEdGraphNode* TemplateNode = nullptr;
if (UEdGraphNode* const* FoundNode = NodeTemplateCache.Find(NodeSpawner))
{
return *FoundNode;
}
return nullptr;
}
//------------------------------------------------------------------------------
void FBlueprintNodeTemplateCache::ClearCachedTemplate(UBlueprintNodeSpawner const* NodeSpawner)
{
NodeTemplateCache.Remove(NodeSpawner);
// GC should take care of the rest
}
//------------------------------------------------------------------------------
int32 FBlueprintNodeTemplateCache::GetEstimateCacheSize() const
{
int32 TotalEstimatedSize = ApproximateObjectMem;
TotalEstimatedSize += TemplateOuters.GetAllocatedSize();
TotalEstimatedSize += NodeTemplateCache.GetAllocatedSize();
TotalEstimatedSize += sizeof(*this);
return TotalEstimatedSize;
}
//------------------------------------------------------------------------------
int32 FBlueprintNodeTemplateCache::RecalculateCacheSize()
{
ApproximateObjectMem = 0;
for (UBlueprint* Blueprint : TemplateOuters)
{
// if we didn't run garbage collection at the top, then this could also
// account for nodes that were never stored (because the cache was too full)
ApproximateObjectMem += BlueprintNodeTemplateCacheImpl::ApproximateMemFootprint(Blueprint);
}
return ApproximateObjectMem;
}
//------------------------------------------------------------------------------
bool FBlueprintNodeTemplateCache::IsTemplateOuter(UEdGraph* ParentGraph)
{
return BlueprintNodeTemplateCacheImpl::IsTemplateOuter(ParentGraph);
}
//------------------------------------------------------------------------------
void FBlueprintNodeTemplateCache::AddReferencedObjects(FReferenceCollector& Collector)
{
for (auto& TemplateEntry : NodeTemplateCache)
{
Collector.AddReferencedObject(TemplateEntry.Value);
}
Collector.AddReferencedObjects(TemplateOuters);
}
FString FBlueprintNodeTemplateCache::GetReferencerName() const
{
return TEXT("FBlueprintNodeTemplateCache");
}
//------------------------------------------------------------------------------
bool FBlueprintNodeTemplateCache::CacheBlueprintOuter(UBlueprint* Blueprint)
{
using namespace BlueprintNodeTemplateCacheImpl;
int32 const ApproxBlueprintSize = ApproximateMemFootprint(Blueprint);
if (ActiveMemFootprint + ApproxBlueprintSize > GetCacheCapSize())
{
return false;
}
else
{
ApproximateObjectMem += ApproxBlueprintSize;
TemplateOuters.Add(Blueprint);
return true;
}
}
//------------------------------------------------------------------------------
bool FBlueprintNodeTemplateCache::CacheTemplateNode(UBlueprintNodeSpawner const* NodeSpawner, UEdGraphNode* NewNode)
{
using namespace BlueprintNodeTemplateCacheImpl;
if (NewNode == nullptr)
{
return true;
}
int32 const ApproxNodeSize = BlueprintNodeTemplateCacheImpl::ApproximateMemFootprint(NewNode);
if (ActiveMemFootprint + ApproxNodeSize > GetCacheCapSize())
{
return false;
}
else
{
ApproximateObjectMem += ApproxNodeSize;
NodeTemplateCache.Add(NodeSpawner, NewNode);
return true;
}
}