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); } } }
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; }
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); }
/** * 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); }
/** 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; }
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; } }
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; }
/** * 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; }
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); // } //} }
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()); } }
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); }
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); } } }
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); }
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(); } } }
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() ); } }
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; }