//------------------------------------------------------------------------------
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;
}
// Rename a class and it's CDO into the transient package, and clear RF_Public on both of them
void FKismetCompilerUtilities::ConsignToOblivion(UClass* OldClass, bool bForceNoResetLoaders)
{
	if (OldClass != NULL)
	{
		// Use the Kismet class reinstancer to ensure that the CDO and any existing instances of this class are cleaned up!
		FBlueprintCompileReinstancer CTOResinstancer(OldClass);

		UPackage* OwnerOutermost = OldClass->GetOutermost();
		if( OldClass->ClassDefaultObject )
		{
			// rename to a temp name, move into transient package
			OldClass->ClassDefaultObject->ClearFlags(RF_Public);
			OldClass->ClassDefaultObject->SetFlags(RF_Transient);
			OldClass->ClassDefaultObject->RemoveFromRoot(); // make sure no longer in root set
		}
		
		OldClass->SetMetaData(FBlueprintMetadata::MD_IsBlueprintBase, TEXT("false"));
		OldClass->ClearFlags(RF_Public);
		OldClass->SetFlags(RF_Transient);
		OldClass->ClassFlags |= CLASS_Deprecated|CLASS_NewerVersionExists;
		OldClass->RemoveFromRoot(); // make sure no longer in root set

		// Invalidate the export for all old properties, to make sure they don't get partially reloaded and corrupt the class
		for( TFieldIterator<UProperty> It(OldClass,EFieldIteratorFlags::ExcludeSuper); It; ++It )
		{
			UProperty* Current = *It;
			InvalidatePropertyExport(Current);
		}

		for( TFieldIterator<UFunction> ItFunc(OldClass,EFieldIteratorFlags::ExcludeSuper); ItFunc; ++ItFunc )
		{
			UFunction* CurrentFunc = *ItFunc;
			ULinkerLoad::InvalidateExport(CurrentFunc);

			for( TFieldIterator<UProperty> It(CurrentFunc,EFieldIteratorFlags::ExcludeSuper); It; ++It )
			{
				UProperty* Current = *It;
				InvalidatePropertyExport(Current);
			}
		}

		const FString BaseName = FString::Printf(TEXT("DEADCLASS_%s_C_%d"), *OldClass->ClassGeneratedBy->GetName(), ConsignToOblivionCounter++);
		OldClass->Rename(*BaseName, GetTransientPackage(), (REN_DontCreateRedirectors|REN_NonTransactional|(bForceNoResetLoaders ? REN_ForceNoResetLoaders : 0)));

		// Make sure MetaData doesn't have any entries to the class we just renamed out of package
		OwnerOutermost->GetMetaData()->RemoveMetaDataOutsidePackage();
	}
}
// Compiles a blueprint.
void FKismet2CompilerModule::CompileBlueprint(class UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions, FCompilerResultsLog& Results, FBlueprintCompileReinstancer* ParentReinstancer, TArray<UObject*>* ObjLoaded)
{
	SCOPE_SECONDS_COUNTER(GBlueprintCompileTime);
	BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileTime);

	Results.SetSourceName(Blueprint->GetName());

	const bool bIsBrandNewBP = (Blueprint->SkeletonGeneratedClass == NULL) && (Blueprint->GeneratedClass == NULL) && (Blueprint->ParentClass != NULL) && !CompileOptions.bIsDuplicationInstigated;

	for ( IBlueprintCompiler* Compiler : Compilers )
	{
		Compiler->PreCompile(Blueprint);
	}

	if (CompileOptions.CompileType != EKismetCompileType::Cpp)
	{
		BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileSkeletonClass);

		FBlueprintCompileReinstancer SkeletonReinstancer(Blueprint->SkeletonGeneratedClass);

		FCompilerResultsLog SkeletonResults;
		SkeletonResults.bSilentMode = true;
		FKismetCompilerOptions SkeletonCompileOptions;
		SkeletonCompileOptions.CompileType = EKismetCompileType::SkeletonOnly;
		CompileBlueprintInner(Blueprint, SkeletonCompileOptions, SkeletonResults, ObjLoaded);
	}

	// If this was a full compile, take appropriate actions depending on the success of failure of the compile
	if( CompileOptions.IsGeneratedClassCompileType() )
	{
		BP_SCOPED_COMPILER_EVENT_STAT(EKismetCompilerStats_CompileGeneratedClass);

		// Perform the full compile
		CompileBlueprintInner(Blueprint, CompileOptions, Results, ObjLoaded);

		if (Results.NumErrors == 0)
		{
			// Blueprint is error free.  Go ahead and fix up debug info
			Blueprint->Status = (0 == Results.NumWarnings) ? BS_UpToDate : BS_UpToDateWithWarnings;
			
			Blueprint->BlueprintSystemVersion = UBlueprint::GetCurrentBlueprintSystemVersion();

			// Reapply breakpoints to the bytecode of the new class
			for (int32 Index = 0; Index < Blueprint->Breakpoints.Num(); ++Index)
			{
				UBreakpoint* Breakpoint = Blueprint->Breakpoints[Index];
				FKismetDebugUtilities::ReapplyBreakpoint(Breakpoint);
			}
		}
		else
		{
			// Should never get errors from a brand new blueprint!
			ensure(!bIsBrandNewBP || (Results.NumErrors == 0));

			// There were errors.  Compile the generated class to have function stubs
			Blueprint->Status = BS_Error;

			static const FBoolConfigValueHelper ReinstanceOnlyWhenNecessary(TEXT("Kismet"), TEXT("bReinstanceOnlyWhenNecessary"), GEngineIni);

			// Reinstance objects here, so we can preserve their memory layouts to reinstance them again
			if( ParentReinstancer != NULL )
			{
				ParentReinstancer->UpdateBytecodeReferences();

				if(!Blueprint->bIsRegeneratingOnLoad)
				{
					ParentReinstancer->ReinstanceObjects(!ReinstanceOnlyWhenNecessary);
				}
			}

			FBlueprintCompileReinstancer StubReinstancer(Blueprint->GeneratedClass);

			// Toss the half-baked class and generate a stubbed out skeleton class that can be used
			FCompilerResultsLog StubResults;
			StubResults.bSilentMode = true;
			FKismetCompilerOptions StubCompileOptions(CompileOptions);
			StubCompileOptions.CompileType = EKismetCompileType::StubAfterFailure;

			CompileBlueprintInner(Blueprint, StubCompileOptions, StubResults, ObjLoaded);

			StubReinstancer.UpdateBytecodeReferences();
			if( !Blueprint->bIsRegeneratingOnLoad )
			{
				StubReinstancer.ReinstanceObjects(!ReinstanceOnlyWhenNecessary);
			}
		}
	}

	for ( IBlueprintCompiler* Compiler : Compilers )
	{
		Compiler->PostCompile(Blueprint);
	}

	UPackage* Package = Blueprint->GetOutermost();
	if( Package )
	{
		UMetaData* MetaData =  Package->GetMetaData();
		MetaData->RemoveMetaDataOutsidePackage();
	}
}
//------------------------------------------------------------------------------
static void BlueprintNodeTemplateCacheImpl::MarkGraphForTemplateUse(UEdGraph* NewGraph)
{
	UPackage*  TemplatePackage = NewGraph->GetOutermost();
	UMetaData* PackageMetadata = TemplatePackage->GetMetaData();
	PackageMetadata->SetValue(NewGraph, TemplateGraphMetaTag, TEXT("true"));
}