void UK2Node_FunctionEntry::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
	Super::ExpandNode(CompilerContext, SourceGraph);

	const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
	
	UEdGraphPin* OldStartExecPin = nullptr;

	if(Pins[0]->LinkedTo.Num())
	{
		OldStartExecPin = Pins[0]->LinkedTo[0];
	}
	
	UEdGraphPin* LastActiveOutputPin = Pins[0];

	// Only look for FunctionEntry nodes who were duplicated and have a source object
	if ( UK2Node_FunctionEntry* OriginalNode = Cast<UK2Node_FunctionEntry>(CompilerContext.MessageLog.FindSourceObject(this)) )
	{
		check(OriginalNode->GetOuter());

		// Find the associated UFunction
		UFunction* Function = FindField<UFunction>(CompilerContext.Blueprint->SkeletonGeneratedClass, *OriginalNode->GetOuter()->GetName());
		for (TFieldIterator<UProperty> It(Function); It; ++It)
		{
			if (const UProperty* Property = *It)
			{
				for (auto& LocalVar : LocalVariables)
				{
					if (LocalVar.VarName == Property->GetFName() && !LocalVar.DefaultValue.IsEmpty())
					{
						// Add a variable set node for the local variable and hook it up immediately following the entry node or the last added local variable
						UK2Node_VariableSet* VariableSetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableSet>(this, SourceGraph);
						VariableSetNode->SetFromProperty(Property, false);
						Schema->ConfigureVarNode(VariableSetNode, LocalVar.VarName, Function, CompilerContext.Blueprint);
						VariableSetNode->AllocateDefaultPins();
						CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableSetNode, this);

						if(UEdGraphPin* SetPin = VariableSetNode->FindPin(Property->GetName()))
						{
							if(LocalVar.VarType.bIsArray)
							{
								TSharedPtr<FStructOnScope> StructData = MakeShareable(new FStructOnScope(Function));
								FBlueprintEditorUtils::PropertyValueFromString(Property, LocalVar.DefaultValue, StructData->GetStructMemory());

								// Create a Make Array node to setup the array's defaults
								UK2Node_MakeArray* MakeArray = CompilerContext.SpawnIntermediateNode<UK2Node_MakeArray>(this, SourceGraph);
								MakeArray->AllocateDefaultPins();
								MakeArray->GetOutputPin()->MakeLinkTo(SetPin);
								MakeArray->PostReconstructNode();

								const UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property);
								check(ArrayProperty);

								FScriptArrayHelper_InContainer ArrayHelper(ArrayProperty, StructData->GetStructMemory());
								FScriptArrayHelper_InContainer DefaultArrayHelper(ArrayProperty, StructData->GetStructMemory());

								uint8* StructDefaults = NULL;
								UStructProperty* StructProperty = dynamic_cast<UStructProperty*>(ArrayProperty->Inner);
								if ( StructProperty != NULL )
								{
									checkSlow(StructProperty->Struct);
									StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize());
									StructProperty->InitializeValue(StructDefaults);
								}

								// Go through each element in the array to set the default value
								for( int32 ArrayIndex = 0 ; ArrayIndex < ArrayHelper.Num() ; ArrayIndex++ )
								{
									uint8* PropData = ArrayHelper.GetRawPtr(ArrayIndex);

									// Always use struct defaults if the inner is a struct, for symmetry with the import of array inner struct defaults
									uint8* PropDefault = ( StructProperty != NULL ) ? StructDefaults :
										( ( StructData->GetStructMemory() && DefaultArrayHelper.Num() > ArrayIndex ) ? DefaultArrayHelper.GetRawPtr(ArrayIndex) : NULL );

									// Retrieve the element's default value
									FString DefaultValue;
									FBlueprintEditorUtils::PropertyValueToString(ArrayProperty->Inner, PropData, DefaultValue);

									if(ArrayIndex > 0)
									{
										MakeArray->AddInputPin();
									}

									// Add one to the index for the pin to set the default on to skip the output pin
									Schema->TrySetDefaultValue(*MakeArray->Pins[ArrayIndex + 1], DefaultValue);
								}
							}
							else
							{
								// Set the default value
								Schema->TrySetDefaultValue(*SetPin, LocalVar.DefaultValue);
							}
						}

						LastActiveOutputPin->BreakAllPinLinks();
						LastActiveOutputPin->MakeLinkTo(VariableSetNode->Pins[0]);
						LastActiveOutputPin = VariableSetNode->Pins[1];
					}
				}
			}
		}

		// Finally, hook up the last node to the old node the function entry node was connected to
		if(OldStartExecPin)
		{
			LastActiveOutputPin->MakeLinkTo(OldStartExecPin);
		}
	}
}
示例#2
0
void UArrayProperty::SerializeItem( FArchive& Ar, void* Value, int32 MaxReadBytes, void const* Defaults ) const
{
	checkSlow(Inner);

	// Ensure that the Inner itself has been loaded before calling SerializeItem() on it
	Ar.Preload(Inner);

	FScriptArrayHelper ArrayHelper(this, Value);
	int32		n		= ArrayHelper.Num();
	Ar << n;
	if( Ar.IsLoading() )
	{
		ArrayHelper.EmptyAndAddValues(n);
	}
	ArrayHelper.CountBytes( Ar );

	const int32 ArrayMaxReadBytes = MaxReadBytes > 0 ? ( MaxReadBytes - sizeof( n ) ) : 0;
	for( int32 i=0; i<n; i++ )
	{
		const int32 ItemMaxReadBytes = ArrayMaxReadBytes > 0 ? ArrayMaxReadBytes / n: 0;
		Inner->SerializeItem( Ar, ArrayHelper.GetRawPtr(i), ItemMaxReadBytes );
	}
}
	void SetParameters(const FRenderingCompositePassContext& Context)
	{
		const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();

		FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
		DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
		PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());

		FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList);
		FIntPoint OutScaledSize;
		float OutScale;
		SceneContext.GetSeparateTranslucencyDimensions(OutScaledSize, OutScale);

		SetShaderValue(Context.RHICmdList, ShaderRHI, SeparateTranslucencyResMultParam, FVector4(OutScale, OutScale, OutScale, OutScale));

		{
			FVector4 DepthOfFieldParamValues[2];

			FRCPassPostProcessBokehDOF::ComputeDepthOfFieldParams(Context, DepthOfFieldParamValues);

			SetShaderValueArray(Context.RHICmdList, ShaderRHI, DepthOfFieldParams, DepthOfFieldParamValues, 2);
		}

		if (UseNearestDepthNeighborUpsample())
		{
			check(SceneContext.IsSeparateTranslucencyDepthValid());
			FTextureRHIParamRef LowResDepth = SceneContext.GetSeparateTranslucencyDepthSurface();
			SetTextureParameter(Context.RHICmdList, ShaderRHI, LowResDepthTexture, LowResDepth);

			const auto& BuiltinSamplersUBParameter = GetUniformBufferParameter<FBuiltinSamplersParameters>();
			SetUniformBufferParameter(Context.RHICmdList, ShaderRHI, BuiltinSamplersUBParameter, GBuiltinSamplersUniformBuffer.GetUniformBufferRHI());
		}
		else
		{
			checkSlow(!LowResDepthTexture.IsBound());
		}
	}
/**
 * Set current transform and the relative to ParentTransform.
 * Equates to This = This->GetRelativeTransform(Parent), but saves the intermediate FTransform storage and copy.
 */
void FTransform::SetToRelativeTransform(const FTransform& ParentTransform)
{
	// A * B(-1) = VQS(B)(-1) (VQS (A))
	// 
	// Scale = S(A)/S(B)
	// Rotation = Q(B)(-1) * Q(A)
	// Translation = 1/S(B) *[Q(B)(-1)*(T(A)-T(B))*Q(B)]
	// where A = this, B = Other
#if DEBUG_INVERSE_TRANSFORM
	FMatrix AM = ToMatrixWithScale();
	FMatrix BM = ParentTransform.ToMatrixWithScale();
#endif
	
	checkSlow(ParentTransform.IsRotationNormalized());

	// Scale = S(A)/S(B)	
	VectorRegister VSafeScale3D	= VectorSet_W0(GetSafeScaleReciprocal(ParentTransform.Scale3D));
	Scale3D = VectorMultiply(Scale3D, VSafeScale3D);
	
	//VQTranslation = (  ( T(A).X - T(B).X ),  ( T(A).Y - T(B).Y ), ( T(A).Z - T(B).Z), 0.f );
	VectorRegister VQTranslation = VectorSet_W0(VectorSubtract(Translation, ParentTransform.Translation));

	// Translation = 1/S(B) *[Q(B)(-1)*(T(A)-T(B))*Q(B)]
	VectorRegister VInverseParentRot = VectorQuaternionInverse(ParentTransform.Rotation);
	VectorRegister VQT = VectorQuaternionMultiply2(VInverseParentRot, VQTranslation);
	VectorRegister VR = VectorQuaternionMultiply2(VQT, ParentTransform.Rotation);
	Translation = VectorMultiply(VR, VSafeScale3D);

	// Rotation = Q(B)(-1) * Q(A)	
	Rotation = VectorQuaternionMultiply2(VInverseParentRot, Rotation );

	DiagnosticCheckNaN_All(); 

#if DEBUG_INVERSE_TRANSFORM
	DebugEqualMatrix(AM *  BM.InverseFast());
#endif
}
void FPoseLinkMappingRecord::PatchLinkIndex(uint8* DestinationPtr, int32 LinkID, int32 SourceLinkID) const
{
	checkSlow(IsValid());

	DestinationPtr = ChildProperty->ContainerPtrToValuePtr<uint8>(DestinationPtr);
	
	if (ChildPropertyIndex != INDEX_NONE)
	{
		UArrayProperty* ArrayProperty = CastChecked<UArrayProperty>(ChildProperty);

		FScriptArrayHelper ArrayHelper(ArrayProperty, DestinationPtr);
		check(ArrayHelper.IsValidIndex(ChildPropertyIndex));

		DestinationPtr = ArrayHelper.GetRawPtr(ChildPropertyIndex);
	}

	// Check to guard against accidental infinite loops
	check((LinkID == INDEX_NONE) || (LinkID != SourceLinkID));

	// Patch the pose link
	FPoseLinkBase& PoseLink = *((FPoseLinkBase*)DestinationPtr);
	PoseLink.LinkID = LinkID;
	PoseLink.SourceLinkID = SourceLinkID;
}
FTransaction::FObjectRecord::FPersistentObjectRef::FPersistentObjectRef(UObject* InObject)
	: ReferenceType(EReferenceType::Unknown)
	, Object(nullptr)
{
	check(InObject);
	UObject* Outermost = BuildSubobjectKey(InObject, SubObjectHierarchyID);

	if (SubObjectHierarchyID.Num()>0)
	{
		check(Outermost);
		//check(Outermost != GetTransientPackage());
		ReferenceType = EReferenceType::SubObject;
		Object = Outermost;
	}
	else
	{
		SubObjectHierarchyID.Empty();
		ReferenceType = EReferenceType::RootObject;
		Object = InObject;
	}

	// Make sure that when we look up the object we find the same thing:
	checkSlow(Get() == InObject);
}
FSlateShaderResourceProxy* FSlateD3DTextureManager::CreateColorTexture( const FName TextureName, FColor InColor )
{
	FNewTextureInfo Info;

	TArray<uint8> RawData;
	RawData.AddUninitialized(4);
	RawData[0] = InColor.R;
	RawData[1] = InColor.G;
	RawData[2] = InColor.B;
	RawData[3] = InColor.A;
	Info.bShouldAtlas = false;
	
	uint32 Width = 1;
	uint32 Height = 1;
	uint32 Stride = 4;
	Info.TextureData = MakeShareable( new FSlateTextureData( Width, Height, Stride, RawData ) );


	FSlateShaderResourceProxy* NewTexture = GenerateTextureResource( Info );
	checkSlow( !ResourceMap.Contains( TextureName ) );
	ResourceMap.Add( TextureName, NewTexture );

	return NewTexture;
}
示例#8
0
FShaderResource::FShaderResource(const FShaderCompilerOutput& Output, FShaderType* InSpecificType) 
	: SpecificType(InSpecificType)
	, NumInstructions(Output.NumInstructions)
	, NumTextureSamplers(Output.NumTextureSamplers)
	, NumRefs(0)
	, Canary(FShader::ShaderMagic_Initialized)
	
{
	Target = Output.Target;
	Code = Output.Code;
	check(Code.Num() > 0);

	OutputHash = Output.OutputHash;
	checkSlow(OutputHash != FSHAHash());

	{
		FScopeLock ShaderResourceIdMapLock(&ShaderResourceIdMapCritical);
		ShaderResourceIdMap.Add(GetId(), this);
	}
	
	INC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num());
	INC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes());
	INC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1);
}
示例#9
0
/**
 * Exports the property values for the specified object as text to the output device.
 *
 * @param	Context			Context from which the set of 'inner' objects is extracted.  If NULL, an object iterator will be used.
 * @param	Out				the output device to send the exported text to
 * @param	ObjectClass		the class of the object to dump properties for
 * @param	Object			the address of the object to dump properties for
 * @param	Indent			number of spaces to prepend to each line of output
 * @param	DiffClass		the class to use for comparing property values when delta export is desired.
 * @param	Diff			the address of the object to use for determining whether a property value should be exported.  If the value in Object matches the corresponding
 *							value in Diff, it is not exported.  Specify NULL to export all properties.
 * @param	Parent			the UObject corresponding to Object
 * @param	PortFlags		flags used for modifying the output and/or behavior of the export
 */
void ExportProperties
(
    const FExportObjectInnerContext* Context,
    FOutputDevice&	Out,
    UClass*			ObjectClass,
    uint8*			Object,
    int32				Indent,
    UClass*			DiffClass,
    uint8*			Diff,
    UObject*		Parent,
    uint32			PortFlags,
    UObject*		ExportRootScope
)
{
    FString ThisName = TEXT("(none)");
    check(ObjectClass != NULL);

    for( UProperty* Property = ObjectClass->PropertyLink; Property; Property = Property->PropertyLinkNext )
    {
        if (!Property->ShouldPort(PortFlags))
            continue;

        ThisName = Property->GetName();
        UArrayProperty* ArrayProperty = Cast<UArrayProperty>(Property);
        UObjectPropertyBase* ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(Property) : NULL;
        const uint32 ExportFlags = PortFlags | PPF_Delimited;

        if ( ArrayProperty != NULL )
        {
            // Export dynamic array.
            UProperty* InnerProp = ArrayProperty->Inner;
            ExportObjectProp = (Property->PropertyFlags & CPF_ExportObject) != 0 ? Cast<UObjectPropertyBase>(InnerProp) : NULL;
            // This is used as the default value in the case of an array property that has
            // fewer elements than the exported object.
            uint8* StructDefaults = NULL;
            UStructProperty* StructProperty = Cast<UStructProperty>(InnerProp);
            if ( StructProperty != NULL )
            {
                checkSlow(StructProperty->Struct);
                StructDefaults = (uint8*)FMemory::Malloc(StructProperty->Struct->GetStructureSize());
                StructProperty->InitializeValue(StructDefaults);
            }

            for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ )
            {
                void* Arr = Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex);
                FScriptArrayHelper ArrayHelper(ArrayProperty, Arr);

                void*	DiffArr = NULL;
                if( DiffClass )
                {
                    DiffArr = Property->ContainerPtrToValuePtrForDefaults<void>(DiffClass, Diff, PropertyArrayIndex);
                }
                // we won't use this if DiffArr is NULL, but we have to set it up to something
                FScriptArrayHelper DiffArrayHelper(ArrayProperty, DiffArr);

                bool bAnyElementDiffered = false;
                for( int32 DynamicArrayIndex=0; DynamicArrayIndex<ArrayHelper.Num(); DynamicArrayIndex++ )
                {
                    FString	Value;

                    // compare each element's value manually so that elements which match the NULL value for the array's inner property type
                    // but aren't in the diff array are still exported
                    uint8* SourceData = ArrayHelper.GetRawPtr(DynamicArrayIndex);
                    uint8* DiffData = DiffArr && DynamicArrayIndex < DiffArrayHelper.Num()
                                      ? DiffArrayHelper.GetRawPtr(DynamicArrayIndex)
                                      : StructDefaults;

                    bool bExportItem = DiffData == NULL || (DiffData != SourceData && !InnerProp->Identical(SourceData, DiffData, ExportFlags));
                    if ( bExportItem )
                    {
                        bAnyElementDiffered = true;
                        InnerProp->ExportTextItem(Value, SourceData, DiffData, Parent, ExportFlags, ExportRootScope);
                        if(ExportObjectProp)
                        {
                            UObject* Obj = ExportObjectProp->GetObjectPropertyValue(ArrayHelper.GetRawPtr(DynamicArrayIndex));
                            check(!Obj || Obj->IsValidLowLevel());
                            if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) )
                            {
                                // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions,
                                // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be
                                // used as the Outer to create the component

                                // Is this an array of components?
                                if ( InnerProp->HasAnyPropertyFlags(CPF_InstancedReference) )
                                {
                                    if ( Obj->GetOuter() == Parent )
                                    {
                                        // Don't export more than once.
                                        Obj->Mark(OBJECTMARK_TagImp);
                                        UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                    }
                                    else
                                    {
                                        // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object
                                        Obj->Mark(OBJECTMARK_TagExp);
                                    }
                                }
                                else
                                {
                                    // Don't export more than once.
                                    Obj->Mark(OBJECTMARK_TagImp);
                                    UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                }
                            }
                        }

                        Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex, *Value );
                    }
                    // if some other element has already been determined to differ from the defaults, then export this item with no data so that
                    // the different array's size is maintained on import (this item will get the default values for that index, if any)
                    // however, if no elements of the array have changed, we still don't want to export anything
                    // so that the array size will also be taken from the defaults, which won't be the case if any element is exported
                    else if (bAnyElementDiffered)
                    {
                        Out.Logf( TEXT("%s%s(%i)=()\r\n"), FCString::Spc(Indent), *Property->GetName(), DynamicArrayIndex );
                    }
                }
            }
            if (StructDefaults)
            {
                StructProperty->DestroyValue(StructDefaults);
                FMemory::Free(StructDefaults);
            }
        }
        else
        {
            for( int32 PropertyArrayIndex=0; PropertyArrayIndex<Property->ArrayDim; PropertyArrayIndex++ )
            {
                FString	Value;
                // Export single element.

                uint8* DiffData = (DiffClass && Property->IsInContainer(DiffClass->GetPropertiesSize())) ? Diff : NULL;
                if( Property->ExportText_InContainer( PropertyArrayIndex, Value, Object, DiffData, Parent, ExportFlags, ExportRootScope ) )
                {
                    if ( ExportObjectProp )
                    {
                        UObject* Obj = ExportObjectProp->GetObjectPropertyValue(Property->ContainerPtrToValuePtr<void>(Object, PropertyArrayIndex));
                        if( Obj && !Obj->HasAnyMarks(OBJECTMARK_TagImp) )
                        {
                            // only export the BEGIN OBJECT block for a component if Parent is the component's Outer....when importing subobject definitions,
                            // (i.e. BEGIN OBJECT), whichever BEGIN OBJECT block a component's BEGIN OBJECT block is located within is the object that will be
                            // used as the Outer to create the component
                            if ( Property->HasAnyPropertyFlags(CPF_InstancedReference) )
                            {
                                if ( Obj->GetOuter() == Parent )
                                {
                                    // Don't export more than once.
                                    Obj->Mark(OBJECTMARK_TagImp);
                                    UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                                }
                                else
                                {
                                    // set the OBJECTMARK_TagExp flag so that the calling code knows we wanted to export this object
                                    Obj->Mark(OBJECTMARK_TagExp);
                                }
                            }
                            else
                            {
                                // Don't export more than once.
                                Obj->Mark(OBJECTMARK_TagImp);
                                UExporter::ExportToOutputDevice( Context, Obj, NULL, Out, TEXT("T3D"), Indent, PortFlags );
                            }
                        }
                    }

                    if( Property->ArrayDim == 1 )
                    {
                        Out.Logf( TEXT("%s%s=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), *Value );
                    }
                    else
                    {
                        Out.Logf( TEXT("%s%s(%i)=%s\r\n"), FCString::Spc(Indent), *Property->GetName(), PropertyArrayIndex, *Value );
                    }
                }
            }
        }
    }

    // Allows to import/export C++ properties in case the automatic unreal script mesh wouldn't work.
    Parent->ExportCustomProperties(Out, Indent);
}
示例#10
0
/** Calculates the PDF for a sample generated by UniformSampleCone */
float UniformConePDF(float CosMaxConeTheta)
{
	checkSlow(CosMaxConeTheta >= 0.0f && CosMaxConeTheta <= 1.0f);
	return 1.0f / (2.0f * (float)PI * (1.0f - CosMaxConeTheta));
}
	/** 
	 * Process a string command to the logging suppression system 
	 * @param CmdString, string to process
	 * @param FromBoot, if true, this is a boot time command, and is handled differently
	 */
	void ProcessCmdString(const FString& CmdString, bool FromBoot = false)
	{
		// How to use the log command : `log <category> <verbosity>
		// e.g., Turn off all logging : `log global none
		// e.g., Set specific filter  : `log logshaders verbose
		// e.g., Combo command        : `log global none, log logshaders verbose

		static FName NAME_BootGlobal(TEXT("BootGlobal"));
		static FName NAME_Reset(TEXT("Reset"));
		FString Cmds = CmdString;
		Cmds = Cmds.Trim().TrimQuotes();
		Cmds.Trim();
		TArray<FString> SubCmds;
		Cmds.ParseIntoArray(SubCmds, TEXT(","), true);
		for (int32 Index = 0; Index < SubCmds.Num(); Index++)
		{
			static FString LogString(TEXT("Log "));
			FString Command = SubCmds[Index].Trim();
			if (Command.StartsWith(*LogString))
			{
				Command = Command.Right(Command.Len() - LogString.Len());
			}
			TArray<FString> CommandParts;
			Command.ParseIntoArrayWS(CommandParts);
			if (CommandParts.Num() < 1)
			{
				continue;
			}
			FName Category(*CommandParts[0]);
			if (Category == NAME_Global && FromBoot)
			{
				Category = NAME_BootGlobal; // the boot time global is a special one, since we want things like "log global none, log logshaders verbose"
			}
			TArray<FLogCategoryBase*> CategoryVerbosities;
			uint8 Value = 0;
			if (FromBoot)
			{
				// now maybe this was already set at boot, in which case we override what it had
				uint8* Boot = BootAssociations.Find(Category);
				if (Boot)
				{
					Value = *Boot;
				}
				else
				{
					// see if we had a boot global override
					Boot = BootAssociations.Find(NAME_BootGlobal);
					if (Boot)
					{
						Value = *Boot;
					}
				}
			}
			else
			{
				for (TMultiMap<FName, FLogCategoryBase*>::TKeyIterator It(ReverseAssociations, Category); It; ++It)
				{
					checkSlow(!(It.Value()->Verbosity & ELogVerbosity::BreakOnLog)); // this bit is factored out of this variable, always
					Value = It.Value()->Verbosity | (It.Value()->DebugBreakOnLog ? ELogVerbosity::BreakOnLog : 0);
					CategoryVerbosities.Add(It.Value());
				}					
			}
			if (CommandParts.Num() == 1)
			{
				// only possibility is the reset and toggle command which is meaningless at boot
				if (!FromBoot)
				{
					if (Category == NAME_Reset)
					{
						for (TMap<FLogCategoryBase*, FName>::TIterator It(Associations); It; ++It)
						{
							FLogCategoryBase* Verb = It.Key();
							Verb->ResetFromDefault();
							// store off the last non-zero one for toggle
							checkSlow(!(Verb->Verbosity & ELogVerbosity::BreakOnLog)); // this bit is factored out of this variable, always
							if (Verb->Verbosity)
							{
								// currently on, store this in the pending and clear it
								ToggleAssociations.Add(Category, Verb->Verbosity);
							}
						}
					}
					else
					{
						if (Value & ELogVerbosity::VerbosityMask)
						{
							// currently on, toggle it
							Value = Value & ~ELogVerbosity::VerbosityMask;
						}
						else
						{
							// try to get a non-zero value from the toggle backup
							uint8* Toggle = ToggleAssociations.Find(Category);
							if (Toggle && *Toggle)
							{
								Value |= *Toggle;
							}
							else
							{
								Value |= ELogVerbosity::All;
							}
						}
					}
				}
			}
			else
			{

				// now we have the current value, lets change it!
				for (int32 PartIndex = 1; PartIndex < CommandParts.Num(); PartIndex++)
				{
					FName CmdToken = FName(*CommandParts[PartIndex]);
					static FName NAME_Verbose(TEXT("Verbose"));
					static FName NAME_VeryVerbose(TEXT("VeryVerbose"));
					static FName NAME_All(TEXT("All"));
					static FName NAME_Default(TEXT("Default"));
					static FName NAME_On(TEXT("On"));
					static FName NAME_Off(TEXT("Off"));
					static FName NAME_Break(TEXT("Break"));
					static FName NAME_Fatal(TEXT("Fatal"));
					static FName NAME_Log(TEXT("Log"));
					static FName NAME_Display(TEXT("Display"));
					if (CmdToken == NAME_None)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Fatal;
					}
					else if (CmdToken == NAME_Fatal)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Fatal;
					}
					else if (CmdToken == NAME_Error)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Error;
					}
					else if (CmdToken == NAME_Warning)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Warning;
					}
					else if (CmdToken == NAME_Log)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Log;
					}
					else if (CmdToken == NAME_Display)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Display;
					}
					else if (CmdToken == NAME_Verbose)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Verbose;
					}
					else if (CmdToken == NAME_VeryVerbose || CmdToken == NAME_All)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::VeryVerbose;
					}
					else if (CmdToken == NAME_Default)
					{
						if (CategoryVerbosities.Num() && !FromBoot)
						{
							Value = CategoryVerbosities[0]->DefaultVerbosity;
						}
					}
					else if (CmdToken == NAME_Off)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
						Value |= ELogVerbosity::Fatal;
					}
					else if (CmdToken == NAME_On)
					{
						Value &= ~ELogVerbosity::VerbosityMask;
							// try to get a non-zero value from the toggle backup
							uint8* Toggle = ToggleAssociations.Find(Category);
							if (Toggle && *Toggle)
							{
								Value |= *Toggle;
							}
							else
							{
								Value |= ELogVerbosity::All;
							}
					}
					else if (CmdToken == NAME_Break)
					{
						Value ^= ELogVerbosity::BreakOnLog;
					}
				}
			}
			if (Category != NAME_Reset)
			{
				if (FromBoot)
				{
					if (Category == NAME_BootGlobal)
					{
						// changing the global at boot removes everything set up so far
						BootAssociations.Empty();
					}
					BootAssociations.Add(Category, Value);
				}
				else
				{
					for (int32 CategoryIndex = 0; CategoryIndex < CategoryVerbosities.Num(); CategoryIndex++)
					{
						FLogCategoryBase* Verb = CategoryVerbosities[CategoryIndex];
						Verb->SetVerbosity(ELogVerbosity::Type(Value));
					}
					if (Category == NAME_Global)
					{
						// if this was a global change, we need to change them all
						ApplyGlobalChanges();
					}
				}
				// store off the last non-zero one for toggle
				if (Value & ELogVerbosity::VerbosityMask)
				{
					// currently on, store this in the pending and clear it
					ToggleAssociations.Add(Category, Value & ELogVerbosity::VerbosityMask);
				}
			}
		}
	}
EConvertQueryResult ConvertQueryImpactHit(const UWorld* World, const PxLocationHit& PHit, FHitResult& OutResult, float CheckLength, const PxFilterData& QueryFilter, const FVector& StartLoc, const FVector& EndLoc, const PxGeometry* const Geom, const PxTransform& QueryTM, bool bReturnFaceIndex, bool bReturnPhysMat)
{
	SCOPE_CYCLE_COUNTER(STAT_ConvertQueryImpactHit);

#if WITH_EDITOR
	if(bReturnFaceIndex && World->IsGameWorld())
	{
		if(!ensure(UPhysicsSettings::Get()->bSuppressFaceRemapTable == false))
		{
			UE_LOG(LogPhysics, Error, TEXT("A scene query is relying on face indices, but bSuppressFaceRemapTable is true."));
			bReturnFaceIndex = false;
		}
	}
#endif

	checkSlow(PHit.flags & PxHitFlag::eDISTANCE);
	const bool bInitialOverlap = PHit.hadInitialOverlap();
	if (bInitialOverlap && Geom != nullptr)
	{
		ConvertOverlappedShapeToImpactHit(World, PHit, StartLoc, EndLoc, OutResult, *Geom, QueryTM, QueryFilter, bReturnPhysMat);
		return EConvertQueryResult::Valid;
	}

	// See if this is a 'blocking' hit
	const PxFilterData PShapeFilter = PHit.shape->getQueryFilterData();
	const PxQueryHitType::Enum HitType = FPxQueryFilterCallback::CalcQueryHitType(QueryFilter, PShapeFilter);
	OutResult.bBlockingHit = (HitType == PxQueryHitType::eBLOCK); 
	OutResult.bStartPenetrating = bInitialOverlap;

	// calculate the hit time
	const float HitTime = PHit.distance/CheckLength;
	OutResult.Time = HitTime;
	OutResult.Distance = PHit.distance;

	// figure out where the the "safe" location for this shape is by moving from the startLoc toward the ImpactPoint
	const FVector TraceStartToEnd = EndLoc - StartLoc;
	const FVector SafeLocationToFitShape = StartLoc + (HitTime * TraceStartToEnd);
	OutResult.Location = SafeLocationToFitShape;

	const bool bUsePxPoint = ((PHit.flags & PxHitFlag::ePOSITION) && !bInitialOverlap);
	if (bUsePxPoint && !PHit.position.isFinite())
	{
#if ENABLE_NAN_DIAGNOSTIC
		SetHitResultFromShapeAndFaceIndex(PHit.shape, PHit.actor, PHit.faceIndex, OutResult, bReturnPhysMat);
		UE_LOG(LogCore, Error, TEXT("ConvertQueryImpactHit() NaN details:\n>> Actor:%s (%s)\n>> Component:%s\n>> Item:%d\n>> BoneName:%s\n>> Time:%f\n>> Distance:%f\n>> Location:%s\n>> bIsBlocking:%d\n>> bStartPenetrating:%d"),
			*GetNameSafe(OutResult.GetActor()), OutResult.Actor.IsValid() ? *OutResult.GetActor()->GetPathName() : TEXT("no path"),
			*GetNameSafe(OutResult.GetComponent()), OutResult.Item, *OutResult.BoneName.ToString(),
			OutResult.Time, OutResult.Distance, *OutResult.Location.ToString(), OutResult.bBlockingHit ? 1 : 0, OutResult.bStartPenetrating ? 1 : 0);
#endif // ENABLE_NAN_DIAGNOSTIC

		OutResult.Reset();
		logOrEnsureNanError(TEXT("ConvertQueryImpactHit() received NaN/Inf for position: %.2f %.2f %.2f"), PHit.position.x, PHit.position.y, PHit.position.z);
		return EConvertQueryResult::Invalid;
	}

	OutResult.ImpactPoint = bUsePxPoint ? P2UVector(PHit.position) : StartLoc;
	
	// Caution: we may still have an initial overlap, but with null Geom. This is the case for RayCast results.
	const bool bUsePxNormal = ((PHit.flags & PxHitFlag::eNORMAL) && !bInitialOverlap);
	if (bUsePxNormal && !PHit.normal.isFinite())
	{
#if ENABLE_NAN_DIAGNOSTIC
		SetHitResultFromShapeAndFaceIndex(PHit.shape, PHit.actor, PHit.faceIndex, OutResult, bReturnPhysMat);
		UE_LOG(LogCore, Error, TEXT("ConvertQueryImpactHit() NaN details:\n>> Actor:%s (%s)\n>> Component:%s\n>> Item:%d\n>> BoneName:%s\n>> Time:%f\n>> Distance:%f\n>> Location:%s\n>> bIsBlocking:%d\n>> bStartPenetrating:%d"),
			*GetNameSafe(OutResult.GetActor()), OutResult.Actor.IsValid() ? *OutResult.GetActor()->GetPathName() : TEXT("no path"),
			*GetNameSafe(OutResult.GetComponent()), OutResult.Item, *OutResult.BoneName.ToString(),
			OutResult.Time, OutResult.Distance, *OutResult.Location.ToString(), OutResult.bBlockingHit ? 1 : 0, OutResult.bStartPenetrating ? 1 : 0);
#endif // ENABLE_NAN_DIAGNOSTIC

		OutResult.Reset();
		logOrEnsureNanError(TEXT("ConvertQueryImpactHit() received NaN/Inf for normal: %.2f %.2f %.2f"), PHit.normal.x, PHit.normal.y, PHit.normal.z);
		return EConvertQueryResult::Invalid;
	}

	FVector Normal = bUsePxNormal ? P2UVector(PHit.normal).GetSafeNormal() : -TraceStartToEnd.GetSafeNormal();
	OutResult.Normal = Normal;
	OutResult.ImpactNormal = Normal;

	OutResult.TraceStart = StartLoc;
	OutResult.TraceEnd = EndLoc;


#if ENABLE_CHECK_HIT_NORMAL
	CheckHitResultNormal(OutResult, TEXT("Invalid Normal from ConvertQueryImpactHit"), StartLoc, EndLoc, Geom);
#endif // ENABLE_CHECK_HIT_NORMAL

	if (bUsePxNormal && !Normal.IsNormalized())
	{
		// TraceStartToEnd should never be zero, because of the length restriction in the raycast and sweep tests.
		Normal = -TraceStartToEnd.GetSafeNormal();
		OutResult.Normal = Normal;
		OutResult.ImpactNormal = Normal;
	}

	const PxGeometryType::Enum SweptGeometryType = Geom ? Geom->getType() : PxGeometryType::eINVALID;
	OutResult.ImpactNormal = FindGeomOpposingNormal(SweptGeometryType, PHit, TraceStartToEnd, Normal);

	// Fill in Actor, Component, material, etc.
	SetHitResultFromShapeAndFaceIndex(PHit.shape, PHit.actor, PHit.faceIndex, OutResult, bReturnPhysMat);

	PxGeometryType::Enum PGeomType = PHit.shape->getGeometryType();

	if(PGeomType == PxGeometryType::eHEIGHTFIELD)
	{
		// Lookup physical material for heightfields
		if (bReturnPhysMat && PHit.faceIndex != InvalidQueryHit.faceIndex)
		{
			PxMaterial* HitMaterial = PHit.shape->getMaterialFromInternalFaceIndex(PHit.faceIndex);
			if (HitMaterial != NULL)
			{
				OutResult.PhysMaterial = FPhysxUserData::Get<UPhysicalMaterial>(HitMaterial->userData);
			}
		}
	}
	else if (bReturnFaceIndex && PGeomType == PxGeometryType::eTRIANGLEMESH)
	{
		PxTriangleMeshGeometry PTriMeshGeom;
		if(	PHit.shape->getTriangleMeshGeometry(PTriMeshGeom) && 
			PTriMeshGeom.triangleMesh != NULL &&
			PHit.faceIndex < PTriMeshGeom.triangleMesh->getNbTriangles() )
		{
			if (const PxU32* TriangleRemap = PTriMeshGeom.triangleMesh->getTrianglesRemap())
			{
				OutResult.FaceIndex	= TriangleRemap[PHit.faceIndex];
			}
		}
	}

	return EConvertQueryResult::Valid;
}
示例#13
0
void UUnrealEdEngine::SelectNone(bool bNoteSelectionChange, bool bDeselectBSPSurfs, bool WarnAboutManyActors)
{
	if( GEdSelectionLock )
	{
		return;
	}

	bool bShowProgress = false;

	// If there are a lot of actors to process, pop up a warning "are you sure?" box
	if( WarnAboutManyActors )
	{
		int32 NumSelectedActors = GEditor->GetSelectedActorCount();
		if( NumSelectedActors >= EditorActorSelectionDefs::MaxActorsToSelectBeforeWarning )
		{
			bShowProgress = true;

			const FText ConfirmText = FText::Format( NSLOCTEXT("UnrealEd", "Warning_ManyActorsForDeselect", "There are {0} selected actors. Are you sure you want to deselect them all?" ), FText::AsNumber(NumSelectedActors) );

			FSuppressableWarningDialog::FSetupInfo Info( ConfirmText, NSLOCTEXT( "UnrealEd", "Warning_ManyActors", "Warning: Many Actors" ), "Warning_ManyActors" );
			Info.ConfirmText = NSLOCTEXT("ModalDialogs", "ManyActorsForDeselectConfirm", "Continue Deselection");
			Info.CancelText = NSLOCTEXT("ModalDialogs", "ManyActorsForDeselectCancel", "Keep Current Selection");

			FSuppressableWarningDialog ManyActorsWarning( Info );
			if( ManyActorsWarning.ShowModal() == FSuppressableWarningDialog::Cancel )
			{
				return;
			}
		}
	}

	if( bShowProgress )
	{
		GWarn->BeginSlowTask( LOCTEXT("BeginDeselectingActorsTaskMessage", "Deselecting Actors"), true );
	}

	// Make a list of selected actors . . .
	TArray<AActor*> ActorsToDeselect;
	for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It )
	{
		AActor* Actor = static_cast<AActor*>( *It );
		checkSlow( Actor->IsA(AActor::StaticClass()) );

		ActorsToDeselect.Add( Actor );
	}

	USelection* SelectedActors = GetSelectedActors();
	SelectedActors->BeginBatchSelectOperation();
	SelectedActors->Modify();

	// . . . and deselect them.
	for ( int32 ActorIndex = 0 ; ActorIndex < ActorsToDeselect.Num() ; ++ActorIndex )
	{
		AActor* Actor = ActorsToDeselect[ ActorIndex ];
		SelectActor( Actor, false, false );
	}

	uint32 NumDeselectSurfaces = 0;
	UWorld* World = GWorld;
	if( bDeselectBSPSurfs && World )
	{
		// Unselect all surfaces in all levels.
		NumDeselectSurfaces += DeselectAllSurfacesForLevel( World->PersistentLevel );
		for( int32 LevelIndex = 0 ; LevelIndex < World->StreamingLevels.Num() ; ++LevelIndex )
		{
			ULevelStreaming* StreamingLevel = World->StreamingLevels[LevelIndex];
			if( StreamingLevel )
			{
				ULevel* Level = StreamingLevel->GetLoadedLevel();
				if ( Level != NULL )
				{
					NumDeselectSurfaces += DeselectAllSurfacesForLevel( Level );
				}
			}
		}
	}

	SelectedActors->EndBatchSelectOperation(bNoteSelectionChange);

	//prevents clicking on background multiple times spamming selection changes
	if (ActorsToDeselect.Num() || NumDeselectSurfaces)
	{
		GetSelectedActors()->DeselectAll();

		if( bNoteSelectionChange )
		{
			NoteSelectionChange();
		}

		//whenever selection changes, recompute whether the selection contains a locked actor
		bCheckForLockActors = true;

		//whenever selection changes, recompute whether the selection contains a world info actor
		bCheckForWorldSettingsActors = true;
	}

	if( bShowProgress )
	{
		GWarn->EndSlowTask();
	}
}
void ConvertQueryImpactHit(const UWorld* World, const PxLocationHit& PHit, FHitResult& OutResult, float CheckLength, const PxFilterData& QueryFilter, const FVector& StartLoc, const FVector& EndLoc, const PxGeometry* const Geom, const PxTransform& QueryTM, bool bReturnFaceIndex, bool bReturnPhysMat)
{
	SCOPE_CYCLE_COUNTER(STAT_ConvertQueryImpactHit);

	checkSlow(PHit.flags & PxHitFlag::eDISTANCE);
	const bool bInitialOverlap = PHit.hadInitialOverlap();
	if (bInitialOverlap && Geom != nullptr)
	{
		ConvertOverlappedShapeToImpactHit(World, PHit, StartLoc, EndLoc, OutResult, *Geom, QueryTM, QueryFilter, bReturnPhysMat);
		return;
	}

	// See if this is a 'blocking' hit
	const PxFilterData PShapeFilter = PHit.shape->getQueryFilterData();
	const PxSceneQueryHitType::Enum HitType = FPxQueryFilterCallback::CalcQueryHitType(QueryFilter, PShapeFilter);
	OutResult.bBlockingHit = (HitType == PxSceneQueryHitType::eBLOCK); 
	OutResult.bStartPenetrating = bInitialOverlap;

	// calculate the hit time
	const float HitTime = PHit.distance/CheckLength;
	OutResult.Time = HitTime;
	OutResult.Distance = PHit.distance;

	// figure out where the the "safe" location for this shape is by moving from the startLoc toward the ImpactPoint
	const FVector TraceStartToEnd = EndLoc - StartLoc;
	const FVector SafeLocationToFitShape = StartLoc + (HitTime * TraceStartToEnd);
	OutResult.Location = SafeLocationToFitShape;

	const bool bUsePxPoint = ((PHit.flags & PxHitFlag::ePOSITION) && !bInitialOverlap);
	OutResult.ImpactPoint = bUsePxPoint ? P2UVector(PHit.position) : StartLoc;
	
	// Caution: we may still have an initial overlap, but with null Geom. This is the case for RayCast results.
	const bool bUsePxNormal = ((PHit.flags & PxHitFlag::eNORMAL) && !bInitialOverlap);
	FVector Normal = bUsePxNormal ? P2UVector(PHit.normal).GetSafeNormal() : -TraceStartToEnd.GetSafeNormal();
	OutResult.Normal = Normal;
	OutResult.ImpactNormal = Normal;

	OutResult.TraceStart = StartLoc;
	OutResult.TraceEnd = EndLoc;


#if ENABLE_CHECK_HIT_NORMAL
	CheckHitResultNormal(OutResult, TEXT("Invalid Normal from ConvertQueryImpactHit"), StartLoc, EndLoc, Geom);
#endif // ENABLE_CHECK_HIT_NORMAL

	if (bUsePxNormal && !Normal.IsNormalized())
	{
		// TraceStartToEnd should never be zero, because of the length restriction in the raycast and sweep tests.
		Normal = -TraceStartToEnd.GetSafeNormal();
		OutResult.Normal = Normal;
		OutResult.ImpactNormal = Normal;
	}

	const PxGeometryType::Enum SweptGeometryType = Geom ? Geom->getType() : PxGeometryType::eINVALID;
	OutResult.ImpactNormal = FindGeomOpposingNormal(SweptGeometryType, PHit, TraceStartToEnd, Normal);
	
	// Fill in Actor, Component, material, etc.
	SetHitResultFromShapeAndFaceIndex(PHit.shape, PHit.actor, PHit.faceIndex, OutResult, bReturnPhysMat);

	if( PHit.shape->getGeometryType() == PxGeometryType::eHEIGHTFIELD)
	{
		// Lookup physical material for heightfields
		if (bReturnPhysMat && PHit.faceIndex != InvalidQueryHit.faceIndex)
		{
			PxMaterial* HitMaterial = PHit.shape->getMaterialFromInternalFaceIndex(PHit.faceIndex);
			if (HitMaterial != NULL)
			{
				OutResult.PhysMaterial = FPhysxUserData::Get<UPhysicalMaterial>(HitMaterial->userData);
			}
		}
	}
	else
	if(bReturnFaceIndex && PHit.shape->getGeometryType() == PxGeometryType::eTRIANGLEMESH)
	{
		PxTriangleMeshGeometry PTriMeshGeom;
		if(	PHit.shape->getTriangleMeshGeometry(PTriMeshGeom) && 
			PTriMeshGeom.triangleMesh != NULL &&
			PHit.faceIndex < PTriMeshGeom.triangleMesh->getNbTriangles() )
		{
			OutResult.FaceIndex	= PTriMeshGeom.triangleMesh->getTrianglesRemap()[PHit.faceIndex];
		}
	}
}
void FIndirectLightingCache::UpdateCachePrimitivesInternal(FScene* Scene, FSceneRenderer& Renderer, bool bAllowUnbuiltPreview, TMap<FIntVector, FBlockUpdateInfo>& OutBlocksToUpdate, TArray<FIndirectLightingCacheAllocation*>& OutTransitionsOverTimeToUpdate)
{
	SCOPE_CYCLE_COUNTER(STAT_UpdateIndirectLightingCachePrims);
	const TMap<FPrimitiveComponentId, FAttachmentGroupSceneInfo>& AttachmentGroups = Scene->AttachmentGroups;
	if (IndirectLightingAllowed(Scene, Renderer))
	{		
		if (bUpdateAllCacheEntries)
		{
			const uint32 PrimitiveCount = Scene->Primitives.Num();

			for (uint32 PrimitiveIndex = 0; PrimitiveIndex < PrimitiveCount; ++PrimitiveIndex)
			{
				FPrimitiveSceneInfo* PrimitiveSceneInfo = Scene->Primitives[PrimitiveIndex];
				const bool bPrecomputedLightingBufferWasDirty = PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate();

				UpdateCachePrimitive(AttachmentGroups, PrimitiveSceneInfo, false, true, OutBlocksToUpdate, OutTransitionsOverTimeToUpdate);

				// If it was already dirty, then the primitive is already in one of the view dirty primitive list at this point.
				// This also ensures that a primitive does not get added twice to the list, which could create an array reallocation.
				if (!bPrecomputedLightingBufferWasDirty)
				{
					PrimitiveSceneInfo->MarkPrecomputedLightingBufferDirty();

					// Check if it is visible otherwise, it will be updated next time it is visible.
					for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
					{
						FViewInfo& View = Renderer.Views[ViewIndex];

						if (View.PrimitiveVisibilityMap[PrimitiveIndex])
						{
							// Since the update can be executed on a threaded job (see GILCUpdatePrimTaskEnabled), no reallocation must happen here.
							checkSlow(View.DirtyPrecomputedLightingBufferPrimitives.Num() < View.DirtyPrecomputedLightingBufferPrimitives.Max());
							View.DirtyPrecomputedLightingBufferPrimitives.Push(PrimitiveSceneInfo);
							break; // We only need to add it in one of the view list.
						}
					}
				}
			}
		}
		else
		{
			TArray<uint32> SetBitIndices[4];
			{
				QUICK_SCOPE_CYCLE_COUNTER(STAT_UpdateCachePreWalk);
			
				for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
				{
					FViewInfo& View = Renderer.Views[ViewIndex];
					SetBitIndices[ViewIndex].Reserve(View.PrimitiveVisibilityMap.Num());

					for (FSceneSetBitIterator BitIt(View.PrimitiveVisibilityMap); BitIt; ++BitIt)
					{
						uint32 PrimitiveIndex = BitIt.GetIndex();
						SetBitIndices[ViewIndex].Add(PrimitiveIndex);					
					}

					// Any visible primitives with an indirect shadow need their ILC updated, since that determines the indirect shadow direction
					for (int32 IndirectPrimitiveIndex = 0; IndirectPrimitiveIndex < View.IndirectShadowPrimitives.Num(); IndirectPrimitiveIndex++)
					{
						int32 PrimitiveIndex = View.IndirectShadowPrimitives[IndirectPrimitiveIndex]->GetIndex();
						SetBitIndices[ViewIndex].AddUnique(PrimitiveIndex);
					}
				}			
			}

			// Go over the views and operate on any relevant visible primitives
			for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
			{
				FViewInfo& View = Renderer.Views[ViewIndex];

				const TArray<uint32>& SetBits = SetBitIndices[ViewIndex];
				for (int32 i = 0; i < SetBits.Num(); ++i)
				{
					uint32 PrimitiveIndex = SetBits[i];

					FPrimitiveSceneInfo* PrimitiveSceneInfo = Scene->Primitives[PrimitiveIndex];
					const bool bPrecomputedLightingBufferWasDirty = PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate();

					const FPrimitiveViewRelevance& PrimitiveRelevance = View.PrimitiveViewRelevanceMap[PrimitiveIndex];
					UpdateCachePrimitive(AttachmentGroups, PrimitiveSceneInfo, bAllowUnbuiltPreview, PrimitiveRelevance.bOpaqueRelevance, OutBlocksToUpdate, OutTransitionsOverTimeToUpdate);

					// If it was already dirty, then the primitive is already in one of the view dirty primitive list at this point.
					// This also ensures that a primitive does not get added twice to the list, which could create an array reallocation.
					if (!bPrecomputedLightingBufferWasDirty && PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate())
					{
						// Since the update can be executed on a threaded job (see GILCUpdatePrimTaskEnabled), no reallocation must happen here.
						checkSlow(View.DirtyPrecomputedLightingBufferPrimitives.Num() < View.DirtyPrecomputedLightingBufferPrimitives.Max());
						View.DirtyPrecomputedLightingBufferPrimitives.Push(PrimitiveSceneInfo);
					}
				}
			}
		}
		bUpdateAllCacheEntries = false;
	}
}
示例#16
0
bool FParse::LineExtended(const TCHAR** Stream, FString& Result, int32& LinesConsumed, bool Exact)
{
	bool GotStream=0;
	bool IsQuoted=0;
	bool Ignore=0;
	int32 BracketDepth = 0;

	Result = TEXT("");
	LinesConsumed = 0;

	while (**Stream != 0 && ((**Stream != 10 && **Stream != 13) || BracketDepth > 0))
	{
		// Start of comments.
		if( !IsQuoted && !Exact && (*Stream)[0]=='/' && (*Stream)[1]=='/' )
			Ignore = 1;

		// Command chaining.
		if( !IsQuoted && !Exact && **Stream=='|' )
			break;

		GotStream = 1;

		// bracketed line break
		if (**Stream == 10 || **Stream == 13)
		{
			checkSlow(BracketDepth > 0);

			Result.AppendChar(TEXT(' '));
			LinesConsumed++;
			(*Stream)++;
			if (**Stream == 10 || **Stream == 13)
			{
				(*Stream)++;
			}
		}
		// allow line break if the end of the line is a backslash
		else if (!IsQuoted && (*Stream)[0] == '\\' && ((*Stream)[1] == 10 || (*Stream)[1] == 13))
		{
			Result.AppendChar(TEXT(' '));
			LinesConsumed++;
			(*Stream) += 2;
			if (**Stream == 10 || **Stream == 13)
			{
				(*Stream)++;
			}
		}
		// check for starting or ending brace
		else if (!IsQuoted && **Stream == '{')
		{
			BracketDepth++;
			(*Stream)++;
		}
		else if (!IsQuoted && **Stream == '}' && BracketDepth > 0)
		{
			BracketDepth--;
			(*Stream)++;
		}
		else
		{
			// Check quoting.
			IsQuoted = IsQuoted ^ (**Stream==34);

			// Got stuff.
			if( !Ignore )
			{
				Result.AppendChar( *((*Stream)++) );
			}
			else
			{
				(*Stream)++;
			}
		}
	}
	if (**Stream == 0)
	{
		if (GotStream)
		{
			LinesConsumed++;
		}
	}
	else if (Exact)
	{
		// Eat up exactly one CR/LF.
		if (**Stream == 13 || **Stream == 10)
		{
			LinesConsumed++;
			if (**Stream == 13)
			{
				(*Stream)++;
			}
			if( **Stream == 10 )
			{
				(*Stream)++;
			}
		}
	}
	else
	{
		// Eat up all CR/LF's.
		while (**Stream == 10 || **Stream == 13 || **Stream == '|')
		{
			if (**Stream != '|')
			{
				LinesConsumed++;
			}
			if (((*Stream)[0] == 10 && (*Stream)[1] == 13) || ((*Stream)[0] == 13 && (*Stream)[1] == 10))
			{
				(*Stream)++;
			}
			(*Stream)++;
		}
	}

	return **Stream!=0 || GotStream;
}
示例#17
0
/**
 * Parse and import text as property values for the object specified.  This function should never be called directly - use ImportObjectProperties instead.
 * 
 * @param	ObjectStruct				the struct for the data we're importing
 * @param	DestData					the location to import the property values to
 * @param	SourceText					pointer to a buffer containing the values that should be parsed and imported
 * @param	SubobjectRoot					when dealing with nested subobjects, corresponds to the top-most outer that
 *										is not a subobject/template
 * @param	SubobjectOuter				the outer to use for creating subobjects/components. NULL when importing structdefaultproperties
 * @param	Warn						output device to use for log messages
 * @param	Depth						current nesting level
 * @param	InstanceGraph				contains the mappings of instanced objects and components to their templates
 *
 * @return	NULL if the default values couldn't be imported
 */
static const TCHAR* ImportProperties(
	uint8*						DestData,
	const TCHAR*				SourceText,
	UStruct*					ObjectStruct,
	UObject*					SubobjectRoot,
	UObject*					SubobjectOuter,
	FFeedbackContext*			Warn,
	int32						Depth,
	FObjectInstancingGraph&		InstanceGraph,
	const TMap<FName, AActor*>* ActorRemapper
	)
{
	check(!GIsUCCMakeStandaloneHeaderGenerator);
	check(ObjectStruct!=NULL);
	check(DestData!=NULL);

	if ( SourceText == NULL )
		return NULL;

	// Cannot create subobjects when importing struct defaults, or if SubobjectOuter (used as the Outer for any subobject declarations encountered) is NULL
	bool bSubObjectsAllowed = !ObjectStruct->IsA(UScriptStruct::StaticClass()) && SubobjectOuter != NULL;

	// true when DestData corresponds to a subobject in a class default object
	bool bSubObject = false;

	UClass* ComponentOwnerClass = NULL;

	if ( bSubObjectsAllowed )
	{
		bSubObject = SubobjectRoot != NULL && SubobjectRoot->HasAnyFlags(RF_ClassDefaultObject);
		if ( SubobjectRoot == NULL )
		{
			SubobjectRoot = SubobjectOuter;
		}

		ComponentOwnerClass = SubobjectOuter != NULL
			? SubobjectOuter->IsA(UClass::StaticClass())
				? CastChecked<UClass>(SubobjectOuter)
				: SubobjectOuter->GetClass()
			: NULL;
	}
	

	// The PortFlags to use for all ImportText calls
	uint32 PortFlags = PPF_Delimited | PPF_CheckReferences;
	if (GIsImportingT3D)
	{
		PortFlags |= PPF_AttemptNonQualifiedSearch;
	}

	FString StrLine;

	TArray<FDefinedProperty> DefinedProperties;

	// Parse all objects stored in the actor.
	// Build list of all text properties.
	bool ImportedBrush = 0;
	int32 LinesConsumed = 0;
	while (FParse::LineExtended(&SourceText, StrLine, LinesConsumed, true))
	{
		// remove extra whitespace and optional semicolon from the end of the line
		{
			int32 Length = StrLine.Len();
			while ( Length > 0 &&
					(StrLine[Length - 1] == TCHAR(';') || StrLine[Length - 1] == TCHAR(' ') || StrLine[Length - 1] == 9) )
			{
				Length--;
			}
			if (Length != StrLine.Len())
			{
				StrLine = StrLine.Left(Length);
			}
		}

		if ( ContextSupplier != NULL )
		{
			ContextSupplier->CurrentLine += LinesConsumed;
		}
		if (StrLine.Len() == 0)
		{
			continue;
		}

		const TCHAR* Str = *StrLine;

		int32 NewLineNumber;
		if( FParse::Value( Str, TEXT("linenumber="), NewLineNumber ) )
		{
			if ( ContextSupplier != NULL )
			{
				ContextSupplier->CurrentLine = NewLineNumber;
			}
		}
		else if( GetBEGIN(&Str,TEXT("Brush")) && ObjectStruct->IsChildOf(ABrush::StaticClass()) )
		{
			// If SubobjectOuter is NULL, we are importing defaults for a UScriptStruct's defaultproperties block
			if ( !bSubObjectsAllowed )
			{
				Warn->Logf(ELogVerbosity::Error, TEXT("BEGIN BRUSH: Subobjects are not allowed in this context"));
				return NULL;
			}

			// Parse brush on this line.
			TCHAR BrushName[NAME_SIZE];
			if( FParse::Value( Str, TEXT("Name="), BrushName, NAME_SIZE ) )
			{
				// If an initialized brush with this name already exists in the level, rename the existing one.
				// It is deemed to be initialized if it has a non-zero poly count.
				// If it is uninitialized, the existing object will have been created by a forward reference in the import text,
				// and it will now be redefined.  This relies on the behavior that NewObject<> will return an existing pointer
				// if an object with the same name and outer is passed.
				UModel* ExistingBrush = FindObject<UModel>( SubobjectRoot, BrushName );
				if (ExistingBrush && ExistingBrush->Polys && ExistingBrush->Polys->Element.Num() > 0)
				{
					ExistingBrush->Rename();
				}

				// Create model.
				UModelFactory* ModelFactory = NewObject<UModelFactory>();
				ModelFactory->FactoryCreateText( UModel::StaticClass(), SubobjectRoot, FName(BrushName, FNAME_Add, true), RF_NoFlags, NULL, TEXT("t3d"), SourceText, SourceText+FCString::Strlen(SourceText), Warn );
				ImportedBrush = 1;
			}
		}
		else if (GetBEGIN(&Str, TEXT("Foliage")))
		{
			UFoliageType* SourceFoliageType;
			FName ComponentName;
			if (SubobjectRoot &&
				ParseObject<UFoliageType>(Str, TEXT("FoliageType="), SourceFoliageType, ANY_PACKAGE) &&
				FParse::Value(Str, TEXT("Component="), ComponentName) )
			{
				UPrimitiveComponent* ActorComponent = FindObjectFast<UPrimitiveComponent>(SubobjectRoot, ComponentName);

				if (ActorComponent && ActorComponent->GetComponentLevel())
				{
					AInstancedFoliageActor* IFA = AInstancedFoliageActor::GetInstancedFoliageActorForLevel(ActorComponent->GetComponentLevel(), true);

					FFoliageMeshInfo* MeshInfo = nullptr;
					UFoliageType* FoliageType = IFA->AddFoliageType(SourceFoliageType, &MeshInfo);

					const TCHAR* StrPtr;
					FString TextLine;
					while (MeshInfo && FParse::Line(&SourceText, TextLine))
					{
						StrPtr = *TextLine;
						if (GetEND(&StrPtr, TEXT("Foliage")))
						{
							break;
						}

						// Parse the instance properties
						FFoliageInstance Instance;
						FString Temp;
						if (FParse::Value(StrPtr, TEXT("Location="), Temp, false))
						{
							GetFVECTOR(*Temp, Instance.Location);
						}
						if (FParse::Value(StrPtr, TEXT("Rotation="), Temp, false))
						{
							GetFROTATOR(*Temp, Instance.Rotation, 1);
						}
						if (FParse::Value(StrPtr, TEXT("PreAlignRotation="), Temp, false))
						{
							GetFROTATOR(*Temp, Instance.PreAlignRotation, 1);
						}
						if (FParse::Value(StrPtr, TEXT("DrawScale3D="), Temp, false))
						{
							GetFVECTOR(*Temp, Instance.DrawScale3D);
						}
						FParse::Value(StrPtr, TEXT("Flags="), Instance.Flags);

						// Add the instance
						MeshInfo->AddInstance(IFA, FoliageType, Instance, ActorComponent);
					}
				}
			}
		}
		else if( GetBEGIN(&Str,TEXT("Object")))
		{
			// If SubobjectOuter is NULL, we are importing defaults for a UScriptStruct's defaultproperties block
			if ( !bSubObjectsAllowed )
			{
				Warn->Logf(ELogVerbosity::Error, TEXT("BEGIN OBJECT: Subobjects are not allowed in this context"));
				return NULL;
			}

			// Parse subobject default properties.
			// Note: default properties subobjects have compiled class as their Outer (used for localization).
			UClass*	TemplateClass = NULL;
			bool bInvalidClass = false;
			ParseObject<UClass>(Str, TEXT("Class="), TemplateClass, ANY_PACKAGE, &bInvalidClass);
			
			if (bInvalidClass)
			{
				Warn->Logf(ELogVerbosity::Error,TEXT("BEGIN OBJECT: Invalid class specified: %s"), *StrLine);
				return NULL;
			}

			// parse the name of the template
			FName	TemplateName = NAME_None;
			FParse::Value(Str,TEXT("Name="),TemplateName);
			if(TemplateName == NAME_None)
			{
				Warn->Logf(ELogVerbosity::Error,TEXT("BEGIN OBJECT: Must specify valid name for subobject/component: %s"), *StrLine);
				return NULL;
			}

			// points to the parent class's template subobject/component, if we are overriding a subobject/component declared in our parent class
			UObject* BaseTemplate = NULL;
			bool bRedefiningSubobject = false;
			if( TemplateClass )
			{
			}
			else
			{
				// next, verify that a template actually exists in the parent class
				UClass* ParentClass = ComponentOwnerClass->GetSuperClass();
				check(ParentClass);

				UObject* ParentCDO = ParentClass->GetDefaultObject();
				check(ParentCDO);

				BaseTemplate = StaticFindObjectFast(UObject::StaticClass(), SubobjectOuter, TemplateName);
				bRedefiningSubobject = (BaseTemplate != NULL);

				if (BaseTemplate == NULL)
				{
					BaseTemplate = StaticFindObjectFast(UObject::StaticClass(), ParentCDO, TemplateName);
				}
				
				if ( BaseTemplate == NULL )
				{
					// wasn't found
					Warn->Logf(ELogVerbosity::Error, TEXT("BEGIN OBJECT: No base template named %s found in parent class %s: %s"), *TemplateName.ToString(), *ParentClass->GetName(), *StrLine);
					return NULL;
				}

				TemplateClass = BaseTemplate->GetClass();
			}

			// because the outer won't be a default object

			checkSlow(TemplateClass != NULL);
			if (bRedefiningSubobject)
			{
				// since we're redefining an object in the same text block, only need to import properties again
				SourceText = ImportObjectProperties( (uint8*)BaseTemplate, SourceText, TemplateClass, SubobjectRoot, BaseTemplate,
													Warn, Depth + 1, ContextSupplier ? ContextSupplier->CurrentLine : 0, &InstanceGraph, ActorRemapper );
			}
			else 
			{
				UObject* Archetype = NULL;
				UObject* ComponentTemplate = NULL;

				// Since we are changing the class we can't use the Archetype,
				// however that is fine since we will have been editing the CDO anyways
				if (!FBlueprintEditorUtils::IsAnonymousBlueprintClass(SubobjectOuter->GetClass()))
				{
					// if an archetype was specified in the Begin Object block, use that as the template for the ConstructObject call.
					FString ArchetypeName;
					if (FParse::Value(Str, TEXT("Archetype="), ArchetypeName))
					{
						// if given a name, break it up along the ' so separate the class from the name
						FString ObjectClass;
						FString ObjectPath;
						if ( FPackageName::ParseExportTextPath(ArchetypeName, &ObjectClass, &ObjectPath) )
						{
							// find the class
							UClass* ArchetypeClass = (UClass*)StaticFindObject(UClass::StaticClass(), ANY_PACKAGE, *ObjectClass);
							if (ArchetypeClass)
							{
								// if we had the class, find the archetype
								Archetype = StaticFindObject(ArchetypeClass, ANY_PACKAGE, *ObjectPath);
							}
						}
					}
				}

				if (SubobjectOuter->HasAnyFlags(RF_ClassDefaultObject))
				{
					if (!Archetype) // if an archetype was specified explicitly, we will stick with that
					{
						Archetype = ComponentOwnerClass->GetDefaultSubobjectByName(TemplateName);
						if(Archetype)
						{
							if ( BaseTemplate == NULL )
							{
								// BaseTemplate should only be NULL if the Begin Object line specified a class
								Warn->Logf(ELogVerbosity::Error, TEXT("BEGIN OBJECT: The component name %s is already used (if you want to override the component, don't specify a class): %s"), *TemplateName.ToString(), *StrLine);
								return NULL;
							}

							// the component currently in the component template map and the base template should be the same
							checkf(Archetype==BaseTemplate,TEXT("OverrideComponent: '%s'   BaseTemplate: '%s'"), *Archetype->GetFullName(), *BaseTemplate->GetFullName());
						}
					}
				}
				else // handle the non-template case (subobjects and non-template components)
				{
					// don't allow Actor-derived subobjects
					if ( TemplateClass->IsChildOf(AActor::StaticClass()) )
					{
						Warn->Logf(ELogVerbosity::Error,TEXT("Cannot create subobjects from Actor-derived classes: %s"), *StrLine);
						return NULL;
					}

					ComponentTemplate = FindObject<UObject>(SubobjectOuter, *TemplateName.ToString());
					if (ComponentTemplate != NULL)
					{
						// if we're overriding a subobject declared in a parent class, we should already have an object with that name that
						// was instanced when ComponentOwnerClass's CDO was initialized; if so, it's archetype should be the BaseTemplate.  If it
						// isn't, then there are two unrelated subobject definitions using the same name.
						if ( ComponentTemplate->GetArchetype() != BaseTemplate )
						{
						}
						else if ( BaseTemplate == NULL )
						{
							// BaseTemplate should only be NULL if the Begin Object line specified a class
							Warn->Logf(ELogVerbosity::Error, TEXT("BEGIN OBJECT: A subobject named %s is already declared in a parent class.  If you intended to override that subobject, don't specify a class in the derived subobject definition: %s"), *TemplateName.ToString(), *StrLine);
							return NULL;
						}
					}

				}

				// Propagate object flags to the sub object.
				EObjectFlags NewFlags = SubobjectOuter->GetMaskedFlags( RF_PropagateToSubObjects );

				if (!Archetype) // no override and we didn't find one from the class table, so go with the base
				{
					Archetype = BaseTemplate;
				}

				UObject* OldComponent = NULL;
				if (ComponentTemplate)
				{
					bool bIsOkToReuse = ComponentTemplate->GetClass() == TemplateClass
						&& ComponentTemplate->GetOuter() == SubobjectOuter
						&& ComponentTemplate->GetFName() == TemplateName 
						&& (ComponentTemplate->GetArchetype() == Archetype || !Archetype);

					if (!bIsOkToReuse)
					{
						UE_LOG(LogEditorObject, Log, TEXT("Could not reuse component instance %s, name clash?"), *ComponentTemplate->GetFullName());
						ComponentTemplate->Rename(); // just abandon the existing component, we are going to create
						OldComponent = ComponentTemplate;
						ComponentTemplate = NULL;
					}
				}


				if (!ComponentTemplate)
				{
					ComponentTemplate = NewObject<UObject>(
						SubobjectOuter,
						TemplateClass,
						TemplateName,
						NewFlags,
						Archetype,
						!!SubobjectOuter,
						&InstanceGraph
						);
				}
				else
				{
					// We do not want to set RF_Transactional for construction script created components, so we have to monkey with things here
					if (NewFlags & RF_Transactional)
					{
						UActorComponent* Component = Cast<UActorComponent>(ComponentTemplate);
						if (Component && Component->IsCreatedByConstructionScript())
						{
							NewFlags &= ~RF_Transactional;
						}
					}

					// Make sure desired flags are set - existing object could be pending kill
					ComponentTemplate->ClearFlags(RF_AllFlags);
					ComponentTemplate->SetFlags(NewFlags);
				}

				// replace all properties in this subobject outer' class that point to the original subobject with the new subobject
				TMap<UObject*, UObject*> ReplacementMap;
				if (Archetype)
				{
					checkSlow(ComponentTemplate->GetArchetype() == Archetype);
					ReplacementMap.Add(Archetype, ComponentTemplate);
					InstanceGraph.AddNewInstance(ComponentTemplate);
				}
				if (OldComponent)
				{
					ReplacementMap.Add(OldComponent, ComponentTemplate);
				}
				FArchiveReplaceObjectRef<UObject> ReplaceAr(SubobjectOuter, ReplacementMap, false, false, true);

				// import the properties for the subobject
				SourceText = ImportObjectProperties(
					(uint8*)ComponentTemplate, 
					SourceText, 
					TemplateClass, 
					SubobjectRoot, 
					ComponentTemplate, 
					Warn, 
					Depth+1,
					ContextSupplier ? ContextSupplier->CurrentLine : 0,
					&InstanceGraph,
					ActorRemapper
					);
			}
		}
		else if( FParse::Command(&Str,TEXT("CustomProperties")))
		{
			check(SubobjectOuter);

			SubobjectOuter->ImportCustomProperties(Str, Warn);
		}
		else if( GetEND(&Str,TEXT("Actor")) || GetEND(&Str,TEXT("DefaultProperties")) || GetEND(&Str,TEXT("structdefaultproperties")) || (GetEND(&Str,TEXT("Object")) && Depth) )
		{
			// End of properties.
			break;
		}
		else if( GetREMOVE(&Str,TEXT("Component")) )
		{
			checkf(false, TEXT("Remove component is illegal in pasted text"));
		}
		else
		{
			// Property.
			UProperty::ImportSingleProperty(Str, DestData, ObjectStruct, SubobjectOuter, PortFlags, Warn, DefinedProperties);
		}
	}

	if (ActorRemapper)
	{
		for (const auto& DefinedProperty : DefinedProperties)
		{
			RemapProperty(DefinedProperty.Property, DefinedProperty.Index, *ActorRemapper, DestData);
		}
	}

	// Prepare brush.
	if( ImportedBrush && ObjectStruct->IsChildOf<ABrush>() && !ObjectStruct->IsChildOf<AVolume>() )
	{
		check(GIsEditor);
		ABrush* Actor = (ABrush*)DestData;
		check(Actor->GetBrushComponent());
		if( Actor->GetBrushComponent()->Mobility == EComponentMobility::Static )
		{
			// Prepare static brush.
			Actor->SetNotForClientOrServer();
		}
		else
		{
			// Prepare moving brush.
			FBSPOps::csgPrepMovingBrush( Actor );
		}
	}

	return SourceText;
}
示例#18
0
UObject* FObjectInstancingGraph::GetInstancedSubobject( UObject* SourceSubobject, UObject* CurrentValue, UObject* CurrentObject, bool bDoNotCreateNewInstance, bool bAllowSelfReference )
{
    checkSlow(SourceSubobject);

    UObject* InstancedSubobject = INVALID_OBJECT;

    if ( SourceSubobject != NULL && CurrentValue != NULL )
    {
        bool bAllowedSelfReference = bAllowSelfReference && SourceSubobject == SourceRoot;

        bool bShouldInstance = bAllowedSelfReference || SourceSubobject->IsIn(SourceRoot);
        if ( !bShouldInstance && CurrentValue->GetOuter() == CurrentObject->GetArchetype() )
        {
            // this code is intended to catch cases where SourceRoot contains subobjects assigned to instanced object properties, where the subobject's class
            // contains components, and the class of the subobject is outside of the inheritance hierarchy of the SourceRoot, for example, a weapon
            // class which contains UIObject subobject definitions in its defaultproperties, where the property referencing the UIObjects is marked instanced.
            bShouldInstance = true;

            // if this case is triggered, ensure that the CurrentValue of the component property is still pointing to the template component.
            check(SourceSubobject == CurrentValue);
        }

        if ( bShouldInstance )
        {
            // search for the unique component instance that corresponds to this component template
            InstancedSubobject = GetDestinationObject(SourceSubobject);
            if ( InstancedSubobject == NULL )
            {
                if (bDoNotCreateNewInstance)
                {
                    InstancedSubobject = INVALID_OBJECT; // leave it unchanged
                }
                else
                {
                    // if the Outer for the component currently assigned to this property is the same as the object that we're instancing components for,
                    // the component does not need to be instanced; otherwise, there are two possiblities:
                    // 1. CurrentValue is a template and needs to be instanced
                    // 2. CurrentValue is an instanced component, in which case it should already be in InstanceGraph, UNLESS the component was created
                    //		at runtime (editinline export properties, for example).  If that is the case, CurrentValue will be an instance that is not linked
                    //		to the component template referenced by CurrentObject's archetype, and in this case, we also don't want to re-instance the component template

                    bool bIsRuntimeInstance = CurrentValue != SourceSubobject && CurrentValue->GetOuter() == CurrentObject;
                    if ( bDoNotCreateNewInstance || bIsRuntimeInstance )
                    {
                        InstancedSubobject = CurrentValue;
                    }
                    else
                    {
                        // If the component template is relevant in this context(client vs server vs editor), instance it.
                        const bool bShouldLoadForClient = SourceSubobject->NeedsLoadForClient();
                        const bool bShouldLoadForServer = SourceSubobject->NeedsLoadForServer();
                        const bool bShouldLoadForEditor = ( GIsEditor && ( bShouldLoadForClient || !CurrentObject->RootPackageHasAnyFlags(PKG_PlayInEditor) ) );

                        if ( ((GIsClient && bShouldLoadForClient) || (GIsServer && bShouldLoadForServer) || bShouldLoadForEditor) )
                        {
                            // this is the first time the instance corresponding to SourceSubobject has been requested

                            // get the object instance corresponding to the source component's Outer - this is the object that
                            // will be used as the Outer for the destination component
                            UObject* SubobjectOuter = GetDestinationObject(SourceSubobject->GetOuter());

                            checkf(SubobjectOuter, TEXT("No corresponding destination object found for '%s' while attempting to instance component '%s'"), *SourceSubobject->GetOuter()->GetFullName(), *SourceSubobject->GetFullName());

                            FName SubobjectName = SourceSubobject->GetFName();

                            // final archetype archetype will be the archetype of the template
                            UObject* FinalSubobjectArchetype = CurrentValue->GetArchetype();

                            // Don't seach for the existing subobjects on Blueprint-generated classes. What we'll find is a subobject
                            // created by the constructor which may not have all of its fields initialized to the correct value (which
                            // should be coming from a blueprint).
                            // NOTE: Since this function is called ONLY for Blueprint-generated classes, we may as well delete this 'if'.
                            if (!SubobjectOuter->GetClass()->HasAnyClassFlags(CLASS_CompiledFromBlueprint))
                            {
                                InstancedSubobject = StaticFindObjectFast(NULL, SubobjectOuter, SubobjectName);
                            }

                            if (InstancedSubobject && IsCreatingArchetype())
                            {
                                // since we are updating an archetype, this needs to reconstruct as that is the mechanism used to copy properties
                                // it will destroy the existing object and overwrite it
                                InstancedSubobject = NULL;
                            }

                            if (!InstancedSubobject)
                            {
                                // finally, create the component instance
                                InstancedSubobject = ConstructObject<UObject>(SourceSubobject->GetClass(), SubobjectOuter,
                                                     SubobjectName, SubobjectOuter->GetMaskedFlags(RF_PropagateToSubObjects), SourceSubobject,
                                                     true, this);
                            }
                        }
                    }
                }
            }
            else if ( IsLoadingObject() && InstancedSubobject->GetClass()->HasAnyClassFlags(CLASS_HasInstancedReference) )
            {
                /* When loading an object from disk, in some cases we have a component which has a reference to another component in DestinationObject which
                	wasn't serialized and hasn't yet been instanced.  For example, the PointLight class declared two component templates:

                		Begin DrawLightRadiusComponent0
                		End
                		Components.Add(DrawLightRadiusComponent0)

                		Begin MyPointLightComponent
                			SomeProperty=DrawLightRadiusComponent
                		End
                		LightComponent=MyPointLightComponent

                	The components array will be processed by UClass::InstanceSubobjectTemplates after the LightComponent property is processed.  If the instance
                	of DrawLightRadiusComponent0 that was created during the last session (i.e. when this object was saved) was identical to the component template
                	from the PointLight class's defaultproperties, and the instance of MyPointLightComponent was serialized, then the MyPointLightComponent instance will
                	exist in the InstanceGraph, but the instance of DrawLightRadiusComponent0 will not.  To handle this case and make sure that the SomeProperty variable of
                	the MyPointLightComponent instance is correctly set to the value of the DrawLightRadiusComponent0 instance that will be created as a result of calling
                	InstanceSubobjectTemplates on the PointLight actor from ConditionalPostLoad, we must call ConditionalPostLoad on each existing component instance that we
                	encounter, while we still have access to all of the component instances owned by the PointLight.
                */
                InstancedSubobject->ConditionalPostLoadSubobjects(this);
            }
        }
    }

    return InstancedSubobject;
}
void UAnimGraphNode_BlendLocomotionFour::CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const
{
	// if pin name starts with BlendPose or BlendWeight, change to enum name 
	bool bIsPosePin;
	bool bIsTimePin;
	int32 RawArrayIndex;
	GetPinInformation(Pin->PinName.ToString(), /*out*/ RawArrayIndex, /*out*/ bIsPosePin, /*out*/ bIsTimePin);
	checkSlow(RawArrayIndex == ArrayIndex);


	if (bIsPosePin)
	{
		if (RawArrayIndex == 0)
		{
			//Pin->PinFriendlyName = FText::FromName("North Pose");
			//FFormatNamedArguments Args;
			//Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName);
			Pin->PinFriendlyName = FText::FromString("N Pose");
		}
		else if (RawArrayIndex == 1)
		{
			Pin->PinFriendlyName = FText::FromString("E Pose");
		}
		else if (RawArrayIndex == 2)
		{
			Pin->PinFriendlyName = FText::FromString("S Pose");
		}
		else if (RawArrayIndex == 3)
		{
			Pin->PinFriendlyName = FText::FromString("W Pose");
		}
	}
	//if (bIsPosePin || bIsTimePin)
	//{
	//	if (RawArrayIndex > 0)
	//	{
	//		const int32 ExposedEnumPinIndex = RawArrayIndex - 1;

	//		// find pose index and see if it's mapped already or not
	//		if (VisibleEnumEntries.IsValidIndex(ExposedEnumPinIndex) && (BoundEnum != NULL))
	//		{
	//			const FName& EnumElementName = VisibleEnumEntries[ExposedEnumPinIndex];
	//			const int32 EnumIndex = BoundEnum->GetIndexByName(EnumElementName);
	//			if (EnumIndex != INDEX_NONE)
	//			{
	//				Pin->PinFriendlyName = BoundEnum->GetDisplayNameTextByIndex(EnumIndex);
	//			}
	//			else
	//			{
	//				Pin->PinFriendlyName = FText::FromName(EnumElementName);
	//			}
	//		}
	//		else
	//		{
	//			Pin->PinFriendlyName = LOCTEXT("InvalidIndex", "Invalid index");
	//		}
	//	}
	//	else if (ensure(RawArrayIndex == 0))
	//	{
	//		Pin->PinFriendlyName = LOCTEXT("Default", "Default");
	//	}

	//	// Append the pin type
	//	if (bIsPosePin)
	//	{
	//		FFormatNamedArguments Args;
	//		Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName);
	//		Pin->PinFriendlyName = FText::Format(LOCTEXT("FriendlyNamePose", "{PinFriendlyName} Pose"), Args);
	//	}

	//	if (bIsTimePin)
	//	{
	//		FFormatNamedArguments Args;
	//		Args.Add(TEXT("PinFriendlyName"), Pin->PinFriendlyName);
	//		Pin->PinFriendlyName = FText::Format(LOCTEXT("FriendlyNameBlendTime", "{PinFriendlyName} Blend Time"), Args);
	//	}
	//}
}
示例#20
0
bool FCanvasBatchedElementRenderItem::Render( const FCanvas* Canvas )
{	
	checkSlow(Data);
	bool bDirty=false;		
	if( Data->BatchedElements.HasPrimsToDraw() )
	{
		bDirty = true;

		// current render target set for the canvas
		const FRenderTarget* CanvasRenderTarget = Canvas->GetRenderTarget();
		float Gamma = 1.0f / CanvasRenderTarget->GetDisplayGamma();
		if ( Data->Texture && Data->Texture->bIgnoreGammaConversions )
		{
			Gamma = 1.0f;
		}

		// this allows us to use FCanvas operations from the rendering thread (ie, render subtitles
		// on top of a movie that is rendered completely in rendering thread)
		if (IsInRenderingThread())
		{
			const bool bNeedsToSwitchVerticalAxis = IsES2Platform(GRHIShaderPlatform) && !IsPCPlatform(GRHIShaderPlatform);

			// draw batched items
			Data->BatchedElements.Draw(
				bNeedsToSwitchVerticalAxis,
				Data->Transform.GetMatrix(),
				CanvasRenderTarget->GetSizeXY().X,
				CanvasRenderTarget->GetSizeXY().Y,
				Canvas->IsHitTesting(),
				Gamma
				);

			if( Canvas->GetAllowedModes() & FCanvas::Allow_DeleteOnRender )
			{
				// delete data since we're done rendering it
				delete Data;
			}
		}
		else
		{
			// Render the batched elements.
			struct FBatchedDrawParameters
			{
				FRenderData* RenderData;
				uint32 bHitTesting : 1;
				uint32 ViewportSizeX;
				uint32 ViewportSizeY;
				float DisplayGamma;
				uint32 AllowedCanvasModes;
			};
			// all the parameters needed for rendering
			FBatchedDrawParameters DrawParameters =
			{
				Data,
				Canvas->IsHitTesting(),
				(uint32)CanvasRenderTarget->GetSizeXY().X,
				(uint32)CanvasRenderTarget->GetSizeXY().Y,
				Gamma,
				Canvas->GetAllowedModes()
			};
			ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
				BatchedDrawCommand,
				FBatchedDrawParameters,Parameters,DrawParameters,
			{
				const bool bNeedsToSwitchVerticalAxis = IsES2Platform(GRHIShaderPlatform) && !IsPCPlatform(GRHIShaderPlatform);

				// draw batched items
				Parameters.RenderData->BatchedElements.Draw(
					bNeedsToSwitchVerticalAxis,
					Parameters.RenderData->Transform.GetMatrix(),
					Parameters.ViewportSizeX,
					Parameters.ViewportSizeY,
					Parameters.bHitTesting,
					Parameters.DisplayGamma
					);
				if( Parameters.AllowedCanvasModes & FCanvas::Allow_DeleteOnRender )
				{
					delete Parameters.RenderData;
				}
			});
		}
//------------------------------------------------------------------------------
FBlueprintDragDropMenuItem::FBlueprintDragDropMenuItem(FBlueprintActionContext const& Context, UBlueprintNodeSpawner const* SampleAction, int32 MenuGrouping/* = 0*/)
{
	AppendAction(SampleAction);
	check(SampleAction != nullptr);
	Grouping  = MenuGrouping;

	UProperty const* SampleProperty = nullptr;
	if (UBlueprintDelegateNodeSpawner const* DelegateSpawner = Cast<UBlueprintDelegateNodeSpawner const>(SampleAction))
	{
		SampleProperty = DelegateSpawner->GetDelegateProperty();
	}
	else if (UBlueprintVariableNodeSpawner const* VariableSpawner = Cast<UBlueprintVariableNodeSpawner const>(SampleAction))
	{
		SampleProperty = VariableSpawner->GetVarProperty();
	}

	if (SampleProperty != nullptr)
	{
		bool const bShowFriendlyNames = GetDefault<UEditorStyleSettings>()->bShowFriendlyNames;
		MenuDescription = bShowFriendlyNames ? FText::FromString(UEditorEngine::GetFriendlyName(SampleProperty)) : FText::FromName(SampleProperty->GetFName());

		TooltipDescription = SampleProperty->GetToolTipText().ToString();
		Category = FObjectEditorUtils::GetCategory(SampleProperty);

		bool const bIsDelegateProperty = SampleProperty->IsA<UMulticastDelegateProperty>();
		if (bIsDelegateProperty && Category.IsEmpty())
		{
			Category = FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Delegates).ToString();
		}
		else if (!bIsDelegateProperty)
		{
			check(Context.Blueprints.Num() > 0);
			UBlueprint const* Blueprint = Context.Blueprints[0];
			UClass const*     BlueprintClass = (Blueprint->SkeletonGeneratedClass != nullptr) ? Blueprint->SkeletonGeneratedClass : Blueprint->ParentClass;

			UClass const* PropertyClass = SampleProperty->GetOwnerClass();
			checkSlow(PropertyClass != nullptr);
			bool const bIsMemberProperty = BlueprintClass->IsChildOf(PropertyClass);

			FText TextCategory;
			if (Category.IsEmpty())
			{
				TextCategory = FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Variables);
			}
			else if (bIsMemberProperty)
			{
				TextCategory = FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Variables, FText::FromString(Category));
			}
			
			if (!bIsMemberProperty)
			{
				TextCategory = FText::Format(LOCTEXT("NonMemberVarCategory", "Class|{0}|{1}"), PropertyClass->GetDisplayNameText(), TextCategory);
			}
			Category = TextCategory.ToString();
		}
	}
	else
	{
		UE_LOG(LogBlueprintDragDropMenuItem, Warning, TEXT("Unhandled (or invalid) spawner: '%s'"), *SampleAction->GetName());
	}
}
示例#22
0
void UUnrealEdEngine::UpdatePivotLocationForSelection( bool bOnChange )
{
	// Pick a new common pivot, or not.
	AActor* SingleActor = nullptr;
	USceneComponent* SingleComponent = nullptr;

	if (GetSelectedComponentCount() > 0)
	{
		for (FSelectedEditableComponentIterator It(*GetSelectedComponents()); It; ++It)
		{
			UActorComponent* Component = CastChecked<UActorComponent>(*It);
			AActor* ComponentOwner = Component->GetOwner();

			if (ComponentOwner != nullptr)
			{
				auto SelectedActors = GetSelectedActors();
				const bool bIsOwnerSelected = SelectedActors->IsSelected(ComponentOwner);
				check(bIsOwnerSelected);

				if (ComponentOwner->GetWorld() == GWorld)
				{
					SingleActor = ComponentOwner;
					if (Component->IsA<USceneComponent>())
					{
						SingleComponent = CastChecked<USceneComponent>(Component);
					}

					const bool IsTemplate = ComponentOwner->IsTemplate();
					const bool LevelLocked = !FLevelUtils::IsLevelLocked(ComponentOwner->GetLevel());
					check(IsTemplate || LevelLocked);
				}
			}
		}
	}
	else
	{
		for (FSelectionIterator It(GetSelectedActorIterator()); It; ++It)
		{
			AActor* Actor = static_cast<AActor*>(*It);
			checkSlow(Actor->IsA(AActor::StaticClass()));

			if (Actor->GetWorld() == GWorld)
			{
				const bool IsTemplate = Actor->IsTemplate();
				const bool LevelLocked = !FLevelUtils::IsLevelLocked(Actor->GetLevel());
				check(IsTemplate || LevelLocked);

				SingleActor = Actor;
			}
		}
	}
	
	if (SingleComponent != NULL)
	{
		SetPivot(SingleComponent->GetComponentLocation(), false, true);
	}
	else if( SingleActor != NULL ) 
	{		
		// For geometry mode use current pivot location as it's set to selected face, not actor
		FEditorModeTools& Tools = GLevelEditorModeTools();
		if( Tools.IsModeActive(FBuiltinEditorModes::EM_Geometry) == false || bOnChange == true )
		{
			// Set pivot point to the actor's location
			FVector PivotPoint = SingleActor->GetActorLocation();

			// If grouping is active, see if this actor is part of a locked group and use that pivot instead
			if(GEditor->bGroupingActive)
			{
				AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(SingleActor, true, true);
				if(ActorGroupRoot)
				{
					PivotPoint = ActorGroupRoot->GetActorLocation();
				}
			}
			SetPivot( PivotPoint, false, true );
		}
	}
	else
	{
		ResetPivot();
	}
}
const FIndirectLightingCacheBlock& FIndirectLightingCache::FindBlock(FIntVector TexelMin) const
{
	checkSlow(IsTexelMinValid(TexelMin));
	return VolumeBlocks.FindChecked(TexelMin);
}
示例#24
0
void USwFMOD::RegisterSound( USound* Sound )
{
	guard(USwFMOD::RegisterSound);
	//SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: [%s]"), SWF_LOGP, *ToStr(Sound) );
	FMOD_RESULT result;

	checkSlow(Sound);
	if( !Sound->Handle )
	{
		FMOD::Sound* sound;

		// Load the data.
		Sound->Data.LoadSpecial();
		SWF_LOG( NAME_DevSound, TEXT("Register sound: %s (%i)"), Sound->GetPathName(), Sound->Data.Num() );
		check(Sound->Data.Num()>0);

		// Sound extended data
#pragma pack(push)
#pragma pack(8)
		FMOD_CREATESOUNDEXINFO exinfo;
		appMemset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
		exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
		exinfo.length = Sound->Data.Num();
#pragma pack(pop)

		// Sound flags
		FMOD_MODE fmode = 0
			| FMOD_SOFTWARE
			| FMOD_IGNORETAGS
		//	| FMOD_LOOP_OFF
		//	| FMOD_2D
			| FMOD_OPENMEMORY
			| FMOD_CREATESAMPLE
			| FMOD_3D 
			| FMOD_3D_LINEARROLLOFF
			;
	

		// Format-specific flags
		if( Sound->FileType == SoundType_WAV )
		{
			// WAV
			exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV;
		}
		else if( Sound->FileType == SoundType_MP2 || Sound->FileType == SoundType_MP3 )
		{
			// MP3 
			fmode |= FMOD_ACCURATETIME;
			exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG;
		}
		else
		{
			// Unknown, try anyway
			fmode |= FMOD_ACCURATETIME;
		}

		// Create sound
		SWF_FMOD_CALL( System->createSound( static_cast<const char*>(Sound->Data.GetData()), fmode, &exinfo, &sound ));
		if( result == FMOD_OK )
		{
			// Register the sound.
			Sound->Handle = sound;
			SWF_FMOD_CALL( sound->setUserData(Sound) );

			unsigned int length;
			SWF_FMOD_CALL( sound->getLength(&length,FMOD_TIMEUNIT_MS) );
			Sound->Duration = length*0.001f;
		}
		else
		{
			SWF_LOG_WARN( FString::Printf(TEXT("Couldn't register sound [%s][%i][%s]"), Sound->GetPathName(), Sound->Data.Num(), *ToStr(result)) );
		}
		
		// Unload the data.
		Sound->Data.Unload();
	}

	unguard;
}
void FIndirectLightingCache::InterpolateBlock(
	FScene* Scene, 
	const FIndirectLightingCacheBlock& Block, 
	TArray<float>& AccumulatedWeight, 
	TArray<FSHVectorRGB2>& AccumulatedIncidentRadiance)
{
	const FBoxCenterAndExtent BlockBoundingBox(Block.Min + Block.Size / 2, Block.Size / 2);
	const FVector HalfTexelWorldOffset = BlockBoundingBox.Extent / FVector(Block.TexelSize);	

	if (GCacheLimitQuerySize && Block.TexelSize > 2)
	{
		for (int32 VolumeIndex = 0; VolumeIndex < Scene->PrecomputedLightVolumes.Num(); VolumeIndex++)
		{
			const FPrecomputedLightVolume* PrecomputedLightVolume = Scene->PrecomputedLightVolumes[VolumeIndex];

			// Compute the target query size
			// We will try to split up the allocation into groups that are smaller than this before querying the octree
			// This prevents very large objects from finding all the samples in the level in their octree search
			const float WorldTargetSize = PrecomputedLightVolume->GetNodeLevelExtent(GCacheQueryNodeLevel) * 2;

			const FVector WorldCellSize = Block.Size / FVector(Block.TexelSize);

			// Number of cells to increment by for query blocks
			FIntVector NumStepCells;
			NumStepCells.X = FMath::Max(1, FMath::FloorToInt(WorldTargetSize / WorldCellSize.X));
			NumStepCells.Y = FMath::Max(1, FMath::FloorToInt(WorldTargetSize / WorldCellSize.Y));
			NumStepCells.Z = FMath::Max(1, FMath::FloorToInt(WorldTargetSize / WorldCellSize.Z));
			FIntVector NumQueryStepCells(0, 0, 0);

			// World space size to increment by for query blocks
			const FVector WorldStepSize = FVector(NumStepCells) * WorldCellSize;
			FVector QueryWorldStepSize(0, 0, 0);

			check(NumStepCells.X > 0 && NumStepCells.Y > 0 && NumStepCells.Z > 0);

			// This will track the position in cells of the query block being built
			FIntVector CellIndex(0, 0, 0);

			// This will track the min world position of the query block being built
			FVector MinPosition = Block.Min;

			for (MinPosition.Z = Block.Min.Z, CellIndex.Z = 0; 
				CellIndex.Z < Block.TexelSize;
				MinPosition.Z += WorldStepSize.Z, CellIndex.Z += NumStepCells.Z)
			{
				QueryWorldStepSize.Z = WorldStepSize.Z;
				NumQueryStepCells.Z = NumStepCells.Z;

				// If this is the last query block in this dimension, adjust both the world space and cell sizes to match
				if (CellIndex.Z + NumStepCells.Z > Block.TexelSize)
				{
					QueryWorldStepSize.Z = Block.Min.Z + Block.Size.Z - MinPosition.Z;
					NumQueryStepCells.Z = Block.TexelSize - CellIndex.Z;
				}

				for (MinPosition.Y = Block.Min.Y, CellIndex.Y = 0; 
					CellIndex.Y < Block.TexelSize;
					MinPosition.Y += WorldStepSize.Y, CellIndex.Y += NumStepCells.Y)
				{
					QueryWorldStepSize.Y = WorldStepSize.Y;
					NumQueryStepCells.Y = NumStepCells.Y;

					if (CellIndex.Y + NumStepCells.Y > Block.TexelSize)
					{
						QueryWorldStepSize.Y = Block.Min.Y + Block.Size.Y - MinPosition.Y;
						NumQueryStepCells.Y = Block.TexelSize - CellIndex.Y;
					}

					for (MinPosition.X = Block.Min.X, CellIndex.X = 0; 
						CellIndex.X < Block.TexelSize;
						MinPosition.X += WorldStepSize.X, CellIndex.X += NumStepCells.X)
					{
						QueryWorldStepSize.X = WorldStepSize.X;
						NumQueryStepCells.X = NumStepCells.X;

						if (CellIndex.X + NumStepCells.X > Block.TexelSize)
						{
							QueryWorldStepSize.X = Block.Min.X + Block.Size.X - MinPosition.X;
							NumQueryStepCells.X = Block.TexelSize - CellIndex.X;
						}

						FVector BoxExtent = QueryWorldStepSize / 2;
						// Use a 0 query extent in dimensions that only have one cell, these become point queries
						BoxExtent.X = NumQueryStepCells.X == 1 ? 0 : BoxExtent.X;
						BoxExtent.Y = NumQueryStepCells.Y == 1 ? 0 : BoxExtent.Y;
						BoxExtent.Z = NumQueryStepCells.Z == 1 ? 0 : BoxExtent.Z;

						// Build a bounding box for the query block
						const FBoxCenterAndExtent BoundingBox(MinPosition + BoxExtent + HalfTexelWorldOffset, BoxExtent);

						checkSlow(CellIndex.X < Block.TexelSize && CellIndex.Y < Block.TexelSize && CellIndex.Z < Block.TexelSize);
						checkSlow(CellIndex.X + NumQueryStepCells.X <= Block.TexelSize
							&& CellIndex.Y + NumQueryStepCells.Y <= Block.TexelSize
							&& CellIndex.Z + NumQueryStepCells.Z <= Block.TexelSize);

						// Interpolate from the SH volume lighting samples that Lightmass computed
						PrecomputedLightVolume->InterpolateIncidentRadianceBlock(
							BoundingBox,
							NumQueryStepCells,
							FIntVector(Block.TexelSize),
							CellIndex,
							AccumulatedWeight,
							AccumulatedIncidentRadiance);
					}
				}
			}
		}
	}
	else
	{
		for (int32 VolumeIndex = 0; VolumeIndex < Scene->PrecomputedLightVolumes.Num(); VolumeIndex++)
		{
			const FPrecomputedLightVolume* PrecomputedLightVolume = Scene->PrecomputedLightVolumes[VolumeIndex];
			check(PrecomputedLightVolume);
			check(PrecomputedLightVolume->IsUsingHighQualityLightMap() == AllowHighQualityLightmaps(Scene->GetFeatureLevel()));
			// Interpolate from the SH volume lighting samples that Lightmass computed
			// Query using the bounds of all the samples in this block
			// There will be a performance cliff for large objects which end up intersecting with the entire octree
			PrecomputedLightVolume->InterpolateIncidentRadianceBlock(
				FBoxCenterAndExtent(BlockBoundingBox.Center + HalfTexelWorldOffset, BlockBoundingBox.Extent), 
				FIntVector(Block.TexelSize), 
				FIntVector(Block.TexelSize), 
				FIntVector(0), 
				AccumulatedWeight, 
				AccumulatedIncidentRadiance);
		}
	}	
}
示例#26
0
void UUnrealEdEngine::SetPivot( FVector NewPivot, bool bSnapPivotToGrid, bool bIgnoreAxis, bool bAssignPivot/*=false*/ )
{
	FEditorModeTools& EditorModeTools = GLevelEditorModeTools();

	if( !bIgnoreAxis )
	{
		// Don't stomp on orthonormal axis.
		if( NewPivot.X==0 ) NewPivot.X=EditorModeTools.PivotLocation.X;
		if( NewPivot.Y==0 ) NewPivot.Y=EditorModeTools.PivotLocation.Y;
		if( NewPivot.Z==0 ) NewPivot.Z=EditorModeTools.PivotLocation.Z;
	}

	// Set the pivot.
	//EditorModeTools.CachedLocation	= NewPivot;	// Don't set the cached location, this is our pre-move point
	EditorModeTools.PivotLocation		= NewPivot;
	EditorModeTools.SnappedLocation		= NewPivot;
	EditorModeTools.GridBase			= FVector::ZeroVector;

	if( bSnapPivotToGrid )
	{
		FRotator DummyRotator(0,0,0);
		FSnappingUtils::SnapToBSPVertex( EditorModeTools.SnappedLocation, EditorModeTools.GridBase, DummyRotator );
		EditorModeTools.PivotLocation = EditorModeTools.SnappedLocation;
	}

	// Check all actors.
	int32 Count=0, SnapCount=0;

	//default to using the x axis for the translate rotate widget
	EditorModeTools.TranslateRotateXAxisAngle = 0.0f;
	EditorModeTools.TranslateRotate2DAngle = 0.0f;
	FVector TranslateRotateWidgetWorldXAxis;

	FVector Widget2DWorldXAxis;

	AActor* LastSelectedActor = NULL;
	for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It )
	{
		AActor* Actor = static_cast<AActor*>( *It );
		checkSlow( Actor->IsA(AActor::StaticClass()) );

		if (Count==0)
		{
			TranslateRotateWidgetWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1.0f, 0.0f, 0.0f));
			//get the xy plane project of this vector
			TranslateRotateWidgetWorldXAxis.Z = 0.0f;
			if (!TranslateRotateWidgetWorldXAxis.Normalize())
			{
				TranslateRotateWidgetWorldXAxis = FVector(1.0f, 0.0f, 0.0f);
			}

			Widget2DWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1, 0, 0));
			Widget2DWorldXAxis.Y = 0;
			if (!Widget2DWorldXAxis.Normalize())
			{
				Widget2DWorldXAxis = FVector(1, 0, 0);
			}
		}

		LastSelectedActor = Actor;
		++Count;
		++SnapCount;
	}
	
	if( bAssignPivot && LastSelectedActor && GEditor->bGroupingActive ) 
	{
		// set group pivot for the root-most group
		AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(LastSelectedActor, true, true);
		if(ActorGroupRoot)
		{
			ActorGroupRoot->SetActorLocation( EditorModeTools.PivotLocation, false );
		}
	}

	//if there are multiple actors selected, just use the x-axis for the "translate/rotate" or 2D widgets
	if (Count == 1)
	{
		EditorModeTools.TranslateRotateXAxisAngle = TranslateRotateWidgetWorldXAxis.Rotation().Yaw;
		EditorModeTools.TranslateRotate2DAngle = FMath::RadiansToDegrees(FMath::Atan2(Widget2DWorldXAxis.Z, Widget2DWorldXAxis.X));
	}

	// Update showing.
	EditorModeTools.PivotShown = SnapCount>0 || Count>1;
}
int32 FA2CSPose::GetParentBoneIndex(const int32& BoneIndex) const
{
	checkSlow( IsValid() );
	return BoneContainer->GetParentBoneIndex(BoneIndex);
}
示例#28
0
void UUnrealEdEngine::NoteActorMovement()
{
	if( !GUndo && !(GEditor->ClickFlags & CF_MOVE_ACTOR) )
	{
		GEditor->ClickFlags |= CF_MOVE_ACTOR;

		const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "ActorMovement", "Actor Movement") );
		GLevelEditorModeTools().Snapping=0;
		
		AActor* SelectedActor = NULL;
		for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It )
		{
			AActor* Actor = static_cast<AActor*>( *It );
			checkSlow( Actor->IsA(AActor::StaticClass()) );

			SelectedActor = Actor;
			break;
		}

		if( SelectedActor == NULL )
		{
			USelection* SelectedActors = GetSelectedActors();
			SelectedActors->Modify();
			SelectActor( GWorld->GetDefaultBrush(), true, true );
		}

		// Look for an actor that requires snapping.
		for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It )
		{
			AActor* Actor = static_cast<AActor*>( *It );
			checkSlow( Actor->IsA(AActor::StaticClass()) );

			GLevelEditorModeTools().Snapping = 1;
			break;
		}

		TSet<AGroupActor*> GroupActors;

		// Modify selected actors.
		for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It )
		{
			AActor* Actor = static_cast<AActor*>( *It );
			checkSlow( Actor->IsA(AActor::StaticClass()) );

			Actor->Modify();

			if (GEditor->bGroupingActive)
			{
				// if this actor is in a group, add the GroupActor into a list to be modified shortly
				AGroupActor* ActorLockedRootGroup = AGroupActor::GetRootForActor(Actor, true);
				if (ActorLockedRootGroup != nullptr)
				{
					GroupActors.Add(ActorLockedRootGroup);
				}
			}

			ABrush* Brush = Cast< ABrush >( Actor );
			if ( Brush )
			{
				if( Brush->Brush )
				{
					Brush->Brush->Polys->Element.ModifyAllItems();
				}
			}
		}

		// Modify unique group actors
		for (auto* GroupActor : GroupActors)
		{
			GroupActor->Modify();
		}
	}
}
示例#29
0
void FInputBindingManager::CreateInputCommand( const TSharedRef<FBindingContext>& InBindingContext, TSharedRef<FUICommandInfo> InCommandInfo )
{
	check( InCommandInfo->BindingContext == InBindingContext->GetContextName() );

	// The command name should be valid
	check( InCommandInfo->CommandName != NAME_None );

	// Should not have already created a gesture for this command
	check( !InCommandInfo->ActiveGesture->IsValidGesture() );
	
	const FName ContextName = InBindingContext->GetContextName();

	FContextEntry& ContextEntry = ContextMap.FindOrAdd( ContextName );
	
	// Our parent context must exist.
	check( InBindingContext->GetContextParent() == NAME_None || ContextMap.Find( InBindingContext->GetContextParent() ) != NULL );

	FCommandInfoMap& CommandInfoMap = ContextEntry.CommandInfoMap;

	if( !ContextEntry.BindingContext.IsValid() )
	{
		ContextEntry.BindingContext = InBindingContext;
	}

	if( InBindingContext->GetContextParent() != NAME_None  )
	{
		check( InBindingContext->GetContextName() != InBindingContext->GetContextParent() );
		// Set a mapping from the parent of the current context to the current context
		ParentToChildMap.AddUnique( InBindingContext->GetContextParent(), InBindingContext->GetContextName() );
	}

	if( InCommandInfo->DefaultGesture.IsValidGesture() )
	{
		CheckForDuplicateDefaultGestures( *InBindingContext, InCommandInfo );
	}
	
	{
		TSharedPtr<FUICommandInfo> ExistingInfo = CommandInfoMap.FindRef( InCommandInfo->CommandName );
		ensureMsgf( !ExistingInfo.IsValid(), TEXT("A command with name %s already exists in context %s"), *InCommandInfo->CommandName.ToString(), *InBindingContext->GetContextName().ToString() );
	}

	// Add the command info to the list of known infos.  It can only exist once.
	CommandInfoMap.Add( InCommandInfo->CommandName, InCommandInfo );

	// See if there are user defined gestures for this command
	FInputGesture UserDefinedGesture;
	bool bFoundUserDefinedGesture = GetUserDefinedGesture( ContextName, InCommandInfo->CommandName, UserDefinedGesture );

	
	if( !bFoundUserDefinedGesture && InCommandInfo->DefaultGesture.IsValidGesture() )
	{
		// Find any existing command with the same gesture 
		// This is for inconsistency between default and user defined gesture.  We need to make sure that if default gestures are changed to a gesture that a user set to a different command, that the default gesture doesn't replace
		// the existing commands gesture. Note: Duplicate default gestures are found above in CheckForDuplicateDefaultGestures
		FName ExisingCommand = ContextEntry.GestureToCommandInfoMap.FindRef( InCommandInfo->DefaultGesture );

		if( ExisingCommand == NAME_None )
		{
			// No existing command has a user defined gesture and no user defined gesture is available for this command 
			TSharedRef<FInputGesture> NewGesture = MakeShareable( new FInputGesture( InCommandInfo->DefaultGesture ) );
			InCommandInfo->ActiveGesture = NewGesture;
		}

	}
	else if( bFoundUserDefinedGesture )
	{
		// Find any existing command with the same gesture 
		// This is for inconsistency between default and user defined gesture.  We need to make sure that if default gestures are changed to a gesture that a user set to a different command, that the default gesture doesn't replace
		// the existing commands gesture.
		FName ExisingCommandName = ContextEntry.GestureToCommandInfoMap.FindRef( UserDefinedGesture );

		if( ExisingCommandName != NAME_None )
		{
			// Get the command with using the same gesture
			TSharedPtr<FUICommandInfo> ExistingInfo = CommandInfoMap.FindRef( ExisingCommandName );
			if( *ExistingInfo->ActiveGesture != ExistingInfo->DefaultGesture )
			{
				// two user defined gestures are the same within a context.  If the keybinding editor was used this wont happen so this must have been directly a modified user setting file
				UE_LOG(LogSlate, Error, TEXT("Duplicate user defined gestures found: [%s,%s].  Gesture for %s being removed"), *InCommandInfo->GetLabel().ToString(), *ExistingInfo->GetLabel().ToString(), *ExistingInfo->GetLabel().ToString() );
			}
			ContextEntry.GestureToCommandInfoMap.Remove( *ExistingInfo->ActiveGesture );
			// Remove the existing gesture. 
			ExistingInfo->ActiveGesture = MakeShareable( new FInputGesture() );
		
		}

		TSharedRef<FInputGesture> NewGesture = MakeShareable( new FInputGesture( UserDefinedGesture ) );
		// Set the active gesture on the command info
		InCommandInfo->ActiveGesture = NewGesture;
	}

	// If the active gesture is valid, map the gesture to the map for fast lookup when processing bindings
	if( InCommandInfo->ActiveGesture->IsValidGesture() )
	{
		checkSlow( !ContextEntry.GestureToCommandInfoMap.Contains( *InCommandInfo->GetActiveGesture() ) );
		ContextEntry.GestureToCommandInfoMap.Add( *InCommandInfo->GetActiveGesture(), InCommandInfo->GetCommandName() );
	}
}
示例#30
0
void USwFMOD::RegisterMusic( UMusic* Music )
{
	guard(USwFMOD::RegisterMusic);
	//SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: [%s]"), SWF_LOGP, *ToStr(Music) );
	FMOD_RESULT result;

	checkSlow(Music);
	if( !Music->Handle )
	{
		FMOD::Sound* sound;

		// Load the data.
		Music->Data.Load();
		SWF_LOG( NAME_DevSound, TEXT("Register music: %s (%i)"), Music->GetPathName(), Music->Data.Num() );
		check(Music->Data.Num()>0);

		// Sound extended data
#pragma pack(push)
#pragma pack(8)
		FMOD_CREATESOUNDEXINFO exinfo;
		appMemset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
		exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
		exinfo.length = Music->Data.Num();
#pragma pack(pop)

		// Sound flags
		FMOD_MODE fmode = 0
			| FMOD_SOFTWARE
		//	| FMOD_IGNORETAGS
		//	| FMOD_LOOP_NORMAL
			| FMOD_2D
			| FMOD_OPENMEMORY
		//	| FMOD_ACCURATETIME
			| FMOD_CREATESTREAM
			;
	
		// Format-specific flags
		if( Music->FileType == SoundType_OGG )
		{
			exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS;
			fmode |= FMOD_LOOP_NORMAL;
		}
		else if( Music->FileType == SoundType_MP2 || Music->FileType == SoundType_MP3 )
		{
			exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG;
			fmode |= FMOD_LOOP_NORMAL;
		}
		else
		{
		}

		// Create sound
		SWF_FMOD_CALL( System->createStream( static_cast<const char*>(Music->Data.GetData()), fmode, &exinfo, &sound ));
		if( result == FMOD_OK )
		{
			// Register the sound.
			Music->Handle = sound;
			SWF_FMOD_CALL( sound->setUserData(Music) );
		}
		else
		{
			SWF_LOG_WARN( FString::Printf(TEXT("Couldn't register music [%s][%i][%s]"), Music->GetPathName(), Music->Data.Num(), *ToStr(result)) );
		}
		
		// Do not unload yet.
		//Music->Data.Unload();
	}

	unguard;
}