bool FIOSDeviceHelper::InstallIPAOnDevice(const FTargetDeviceId& DeviceId, const FString& IPAPath) { // check for valid path if (IPAPath.Len() == 0) { return false; } // check for valid device IOSDevice* device = NULL; FIOSLaunchDaemonPong DeviceMessage; for (auto DeviceIterator = ConnectedDevices.CreateIterator(); DeviceIterator; ++DeviceIterator) { DeviceMessage = DeviceIterator.Value(); if (DeviceMessage.DeviceID == DeviceId.ToString()) { device = DeviceIterator.Key(); break; } } if (device == NULL) { return false; } // we have the device and a IPA path // copy to the stage if (device->CopyFileToPublicStaging(IPAPath)) { // install on the device return device->TryUpgrade(IPAPath); } return false; }
void UActorComponent::ConsolidatedPostEditChange(const FPropertyChangedEvent& PropertyChangedEvent) { FComponentReregisterContext* ReregisterContext = nullptr; if(EditReregisterContexts.RemoveAndCopyValue(this, ReregisterContext)) { delete ReregisterContext; AActor* MyOwner = GetOwner(); if ( MyOwner && !MyOwner->IsTemplate() && PropertyChangedEvent.ChangeType != EPropertyChangeType::Interactive ) { MyOwner->RerunConstructionScripts(); } } else { // This means there are likely some stale elements left in there now, strip them out for (auto It(EditReregisterContexts.CreateIterator()); It; ++It) { if (!It.Key().IsValid()) { It.RemoveCurrent(); } } } // The component or its outer could be pending kill when calling PostEditChange when applying a transaction. // Don't do do a full recreate in this situation, and instead simply detach. if( IsPendingKill() ) { // @todo UE4 james should this call UnregisterComponent instead to remove itself from the RegisteredComponents array on the owner? ExecuteUnregisterEvents(); World = NULL; } }
void UDestructibleComponent::UpdateDestructibleChunkTM(const TArray<const PxRigidActor*>& ActiveActors) { //We want to consolidate the transforms so that we update each destructible component once by passing it an array of chunks to update. //This helps avoid a lot of duplicated work like marking render dirty, computing inverse world component, etc... TMap<UDestructibleComponent*, TArray<FUpdateChunksInfo> > ComponentUpdateMapping; //prepare map to update destructible components TArray<PxShape*> Shapes; for (const PxRigidActor* RigidActor : ActiveActors) { if (const FDestructibleChunkInfo* DestructibleChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(RigidActor->userData)) { if (GApexModuleDestructible->owns(RigidActor) && DestructibleChunkInfo->OwningComponent.IsValid()) { Shapes.AddUninitialized(RigidActor->getNbShapes()); int32 NumShapes = RigidActor->getShapes(Shapes.GetData(), Shapes.Num()); for (int32 ShapeIdx = 0; ShapeIdx < Shapes.Num(); ++ShapeIdx) { PxShape* Shape = Shapes[ShapeIdx]; int32 ChunkIndex; if (NxDestructibleActor* DestructibleActor = GApexModuleDestructible->getDestructibleAndChunk(Shape, &ChunkIndex)) { const physx::PxMat44 ChunkPoseRT = DestructibleActor->getChunkPose(ChunkIndex); const physx::PxTransform Transform(ChunkPoseRT); if (UDestructibleComponent* DestructibleComponent = Cast<UDestructibleComponent>(FPhysxUserData::Get<UPrimitiveComponent>(DestructibleActor->userData))) { if (DestructibleComponent->IsRegistered()) { TArray<FUpdateChunksInfo>& UpdateInfos = ComponentUpdateMapping.FindOrAdd(DestructibleComponent); FUpdateChunksInfo* UpdateInfo = new (UpdateInfos)FUpdateChunksInfo(ChunkIndex, P2UTransform(Transform)); } } } } Shapes.Empty(Shapes.Num()); //we want to keep largest capacity array to avoid reallocs } } } //update each component for (auto It = ComponentUpdateMapping.CreateIterator(); It; ++It) { UDestructibleComponent* DestructibleComponent = It.Key(); TArray<FUpdateChunksInfo>& UpdateInfos = It.Value(); if (DestructibleComponent->IsFracturedOrInitiallyStatic()) { DestructibleComponent->SetChunksWorldTM(UpdateInfos); } else { //if we haven't fractured it must mean that we're simulating a destructible and so we should update our ComponentToWorld based on the single rigid body DestructibleComponent->SyncComponentToRBPhysics(); } } }
void EmptyD3DSamplerStateCache() { for (auto Iter = GSamplerStateCache.CreateIterator(); Iter; ++Iter ) { auto* State = Iter.Value(); // Manually release State->Release(); } GSamplerStateCache.Empty(); }
/** Called once all stats are gathered into the map */ void Generate() { // consolidate averages etc. for( auto It = ResourceToStatsMap.CreateIterator(); It; ++It ) { It.Value()->InstTriangles = It.Value()->Count * It.Value()->Triangles; It.Value()->LightsTotal = ( (float)It.Value()->LightsLM + It.Value()->LightsOther ) / (float)It.Value()->Count; It.Value()->ObjLightCost = It.Value()->LightsOther * It.Value()->Sections; It.Value()->LightsOther = It.Value()->LightsOther / It.Value()->Count; It.Value()->RadiusAvg /= It.Value()->Count; It.Value()->LMSMResolution /= It.Value()->Count; } }
TSharedRef<SWidget> FAnimTransitionNodeDetails::OnGetShareableNodesMenu(bool bShareRules) { FMenuBuilder MenuBuilder(true, NULL); FText SectionText; if (bShareRules) { SectionText = LOCTEXT("PickSharedAnimTransition", "Shared Transition Rules"); } else { SectionText = LOCTEXT("PickSharedAnimCrossfadeSettings", "Shared Settings"); } MenuBuilder.BeginSection("AnimTransitionSharableNodes", SectionText); if (UAnimStateTransitionNode* TransNode = TransitionNode.Get()) { const UEdGraph* CurrentGraph = TransNode->GetGraph(); // Loop through the graph and build a list of the unique shared transitions TMap<FString, UAnimStateTransitionNode*> SharedTransitions; for (int32 NodeIdx=0; NodeIdx < CurrentGraph->Nodes.Num(); NodeIdx++) { if (UAnimStateTransitionNode* GraphTransNode = Cast<UAnimStateTransitionNode>(CurrentGraph->Nodes[NodeIdx])) { if (bShareRules && !GraphTransNode->SharedRulesName.IsEmpty()) { SharedTransitions.Add(GraphTransNode->SharedRulesName, GraphTransNode); } if (!bShareRules && !GraphTransNode->SharedCrossfadeName.IsEmpty()) { SharedTransitions.Add(GraphTransNode->SharedCrossfadeName, GraphTransNode); } } } for (auto Iter = SharedTransitions.CreateIterator(); Iter; ++Iter) { FUIAction Action = FUIAction( FExecuteAction::CreateSP(this, &FAnimTransitionNodeDetails::BecomeSharedWith, Iter.Value(), bShareRules) ); MenuBuilder.AddMenuEntry( FText::FromString( Iter.Key() ), LOCTEXT("ShaerdTransitionToolTip", "Use this shared transition"), FSlateIcon(), Action); } } MenuBuilder.EndSection(); return MenuBuilder.MakeWidget(); }
void EmptyD3DSamplerStateCache() { #if LOCK_GSamplerStateCache FScopeLock Lock(&GSamplerStateCacheLock); #endif for (auto Iter = GSamplerStateCache.CreateIterator(); Iter; ++Iter ) { auto* State = Iter.Value(); // Manually release State->Release(); } GSamplerStateCache.Empty(); }
void ACullDistanceVolume::GetPrimitiveMaxDrawDistances(TMap<UPrimitiveComponent*,float>& OutCullDistances) { // Nothing to do if there is no brush component or no cull distances are set if (GetBrushComponent() && CullDistances.Num() > 0 && bEnabled) { for (auto It(OutCullDistances.CreateIterator()); It; ++It) { UPrimitiveComponent* PrimitiveComponent = It.Key(); // Check whether primitive can be affected by cull distance volumes. if( ACullDistanceVolume::CanBeAffectedByVolumes( PrimitiveComponent ) ) { // Check whether primitive supports cull distance volumes and its center point is being encompassed by this volume. if( EncompassesPoint( PrimitiveComponent->GetComponentLocation() ) ) { // Find best match in CullDistances array. float PrimitiveSize = PrimitiveComponent->Bounds.SphereRadius * 2; float CurrentError = FLT_MAX; float CurrentCullDistance = 0; for( int32 CullDistanceIndex=0; CullDistanceIndex<CullDistances.Num(); CullDistanceIndex++ ) { const FCullDistanceSizePair& CullDistancePair = CullDistances[CullDistanceIndex]; if( FMath::Abs( PrimitiveSize - CullDistancePair.Size ) < CurrentError ) { CurrentError = FMath::Abs( PrimitiveSize - CullDistancePair.Size ); CurrentCullDistance = CullDistancePair.CullDistance; } } float& CullDistance = It.Value(); // LD or other volume specified cull distance, use minimum of current and one used for this volume. if (CullDistance > 0) { CullDistance = FMath::Min(CullDistance, CurrentCullDistance); } // LD didn't specify cull distance, use current setting directly. else { CullDistance = CurrentCullDistance; } } } } } }
/** * Compare two object property maps * @param OrigName The name of the original object being compared against * @param OrigMap The property map for the object * @param CmpName The name of the object to compare * @param CmpMap The property map for the object to compare */ static bool ComparePropertyMaps(FName OrigName, TMap<FString, FString>& OrigMap, FName CmpName, FPropertiesMap& CmpMap, FCompilerResultsLog& Results) { if (OrigMap.Num() != CmpMap.Num()) { Results.Error( *FString::Printf(TEXT("Objects have a different number of properties (%d vs %d)"), OrigMap.Num(), CmpMap.Num()) ); return false; } bool bMatch = true; for (auto PropIt = OrigMap.CreateIterator(); PropIt; ++PropIt) { FString Key = PropIt.Key(); FString Val = PropIt.Value(); const FString* CmpValue = CmpMap.Find(Key); // Value is missing if (CmpValue == NULL) { bMatch = false; Results.Error( *FString::Printf(TEXT("Property is missing in object being compared: (%s %s)"), *Key, *Val) ); break; } else if (Val != *CmpValue) { // string out object names and retest FString TmpCmp(*CmpValue); TmpCmp.ReplaceInline(*CmpName.ToString(), TEXT("")); FString TmpVal(Val); TmpVal.ReplaceInline(*OrigName.ToString(), TEXT("")); if (TmpCmp != TmpVal) { bMatch = false; Results.Error( *FString::Printf(TEXT("Object properties do not match: %s (%s vs %s)"), *Key, *Val, *(*CmpValue)) ); break; } } } return bMatch; }
UJavascriptDelegate* FindJavascriptDelegateByFunction(Local<Function> function) { HandleScope handle_scope(isolate_); bool bWasSuccessful = false; for (auto it = functions.CreateIterator(); it; ++it) { if (Local<Function>::New(isolate_, it.Value())->Equals(function)) { for (auto obj : DelegateObjects) { if (obj->UniqueId == it.Key()) { return obj; } } } } return nullptr; }
void FIOSDeviceHelper::DoDeviceDisconnect(void* deviceHandle) { IOSDevice* device = NULL; for (auto DeviceIterator = ConnectedDevices.CreateIterator(); DeviceIterator; ++DeviceIterator) { if (DeviceIterator.Key()->Handle() == deviceHandle) { device = DeviceIterator.Key(); break; } } if (device != NULL) { // extract the device id from the connected list¯ FIOSLaunchDaemonPong Event = ConnectedDevices.FindAndRemoveChecked(device); // fire the event FIOSDeviceHelper::OnDeviceDisconnected().Broadcast(Event); // delete the device delete device; } }
/** * Construct the final microcode from the compiled and verified shader source. * @param ShaderOutput - Where to store the microcode and parameter map. * @param InShaderSource - Metal source with input/output signature. * @param SourceLen - The length of the Metal source code. */ static void BuildMetalShaderOutput( FShaderCompilerOutput& ShaderOutput, const FShaderCompilerInput& ShaderInput, const ANSICHAR* InShaderSource, int32 SourceLen, TArray<FShaderCompilerError>& OutErrors ) { FMetalCodeHeader Header = {0}; const ANSICHAR* ShaderSource = InShaderSource; FShaderParameterMap& ParameterMap = ShaderOutput.ParameterMap; EShaderFrequency Frequency = (EShaderFrequency)ShaderOutput.Target.Frequency; TBitArray<> UsedUniformBufferSlots; UsedUniformBufferSlots.Init(false,32); // Write out the magic markers. Header.Frequency = Frequency; #define DEF_PREFIX_STR(Str) \ const ANSICHAR* Str##Prefix = "// @" #Str ": "; \ const int32 Str##PrefixLen = FCStringAnsi::Strlen(Str##Prefix) DEF_PREFIX_STR(Inputs); DEF_PREFIX_STR(Outputs); DEF_PREFIX_STR(UniformBlocks); DEF_PREFIX_STR(Uniforms); DEF_PREFIX_STR(PackedGlobals); DEF_PREFIX_STR(PackedUB); DEF_PREFIX_STR(PackedUBCopies); DEF_PREFIX_STR(PackedUBGlobalCopies); DEF_PREFIX_STR(Samplers); DEF_PREFIX_STR(UAVs); DEF_PREFIX_STR(SamplerStates); DEF_PREFIX_STR(NumThreads); #undef DEF_PREFIX_STR // Skip any comments that come before the signature. while ( FCStringAnsi::Strncmp(ShaderSource, "//", 2) == 0 && FCStringAnsi::Strncmp(ShaderSource, "// @", 4) != 0 ) { while (*ShaderSource && *ShaderSource++ != '\n') {} } // HLSLCC first prints the list of inputs. if (FCStringAnsi::Strncmp(ShaderSource, InputsPrefix, InputsPrefixLen) == 0) { ShaderSource += InputsPrefixLen; // Only inputs for vertex shaders must be tracked. if (Frequency == SF_Vertex) { const ANSICHAR* AttributePrefix = "in_ATTRIBUTE"; const int32 AttributePrefixLen = FCStringAnsi::Strlen(AttributePrefix); while (*ShaderSource && *ShaderSource != '\n') { // Skip the type. while (*ShaderSource && *ShaderSource++ != ':') {} // Only process attributes. if (FCStringAnsi::Strncmp(ShaderSource, AttributePrefix, AttributePrefixLen) == 0) { ShaderSource += AttributePrefixLen; uint8 AttributeIndex = ParseNumber(ShaderSource); Header.Bindings.InOutMask |= (1 << AttributeIndex); } // Skip to the next. while (*ShaderSource && *ShaderSource != ',' && *ShaderSource != '\n') { ShaderSource++; } if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } else { // Skip to the next line. while (*ShaderSource && *ShaderSource++ != '\n') {} } } // Then the list of outputs. if (FCStringAnsi::Strncmp(ShaderSource, OutputsPrefix, OutputsPrefixLen) == 0) { ShaderSource += OutputsPrefixLen; // Only outputs for pixel shaders must be tracked. if (Frequency == SF_Pixel) { const ANSICHAR* TargetPrefix = "out_Target"; const int32 TargetPrefixLen = FCStringAnsi::Strlen(TargetPrefix); while (*ShaderSource && *ShaderSource != '\n') { // Skip the type. while (*ShaderSource && *ShaderSource++ != ':') {} // Handle targets. if (FCStringAnsi::Strncmp(ShaderSource, TargetPrefix, TargetPrefixLen) == 0) { ShaderSource += TargetPrefixLen; uint8 TargetIndex = ParseNumber(ShaderSource); Header.Bindings.InOutMask |= (1 << TargetIndex); } // Handle depth writes. else if (FCStringAnsi::Strcmp(ShaderSource, "gl_FragDepth") == 0) { Header.Bindings.InOutMask |= 0x8000; } // Skip to the next. while (*ShaderSource && *ShaderSource != ',' && *ShaderSource != '\n') { ShaderSource++; } if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } else { // Skip to the next line. while (*ShaderSource && *ShaderSource++ != '\n') {} } } bool bHasRegularUniformBuffers = false; // Then 'normal' uniform buffers. if (FCStringAnsi::Strncmp(ShaderSource, UniformBlocksPrefix, UniformBlocksPrefixLen) == 0) { ShaderSource += UniformBlocksPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FString BufferName = ParseIdentifier(ShaderSource); verify(BufferName.Len() > 0); verify(Match(ShaderSource, '(')); uint16 UBIndex = ParseNumber(ShaderSource); if (UBIndex >= Header.Bindings.NumUniformBuffers) { Header.Bindings.NumUniformBuffers = UBIndex + 1; } UsedUniformBufferSlots[UBIndex] = true; verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation(*BufferName, UBIndex, 0, 0); bHasRegularUniformBuffers = true; // Skip the comma. if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); } // Then uniforms. const uint16 BytesPerComponent = 4; /* uint16 PackedUniformSize[OGL_NUM_PACKED_UNIFORM_ARRAYS] = {0}; FMemory::Memzero(&PackedUniformSize, sizeof(PackedUniformSize)); */ if (FCStringAnsi::Strncmp(ShaderSource, UniformsPrefix, UniformsPrefixLen) == 0) { // @todo-mobile: Will we ever need to support this code path? check(0); /* ShaderSource += UniformsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 ArrayIndex = 0; uint16 Offset = 0; uint16 NumComponents = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ArrayIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumComponents = ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation( *ParameterName, ArrayIndex, Offset * BytesPerComponent, NumComponents * BytesPerComponent ); if (ArrayIndex < OGL_NUM_PACKED_UNIFORM_ARRAYS) { PackedUniformSize[ArrayIndex] = FMath::Max<uint16>( PackedUniformSize[ArrayIndex], BytesPerComponent * (Offset + NumComponents) ); } // Skip the comma. if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); */ } // Packed global uniforms TMap<ANSICHAR, uint16> PackedGlobalArraySize; if (FCStringAnsi::Strncmp(ShaderSource, PackedGlobalsPrefix, PackedGlobalsPrefixLen) == 0) { ShaderSource += PackedGlobalsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { ANSICHAR ArrayIndex = 0; uint16 Offset = 0; uint16 NumComponents = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ArrayIndex = *ShaderSource++; verify(Match(ShaderSource, ':')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); NumComponents = ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation( *ParameterName, ArrayIndex, Offset * BytesPerComponent, NumComponents * BytesPerComponent ); uint16& Size = PackedGlobalArraySize.FindOrAdd(ArrayIndex); Size = FMath::Max<uint16>(BytesPerComponent * (Offset + NumComponents), Size); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } Match(ShaderSource, '\n'); } // Packed Uniform Buffers TMap<int, TMap<ANSICHAR, uint16> > PackedUniformBuffersSize; while (FCStringAnsi::Strncmp(ShaderSource, PackedUBPrefix, PackedUBPrefixLen) == 0) { ShaderSource += PackedUBPrefixLen; FString BufferName = ParseIdentifier(ShaderSource); verify(BufferName.Len() > 0); verify(Match(ShaderSource, '(')); uint16 BufferIndex = ParseNumber(ShaderSource); check(BufferIndex == Header.Bindings.NumUniformBuffers); verify(Match(ShaderSource, ')')); ParameterMap.AddParameterAllocation(*BufferName, Header.Bindings.NumUniformBuffers++, 0, 0); verify(Match(ShaderSource, ':')); Match(ShaderSource, ' '); while (*ShaderSource && *ShaderSource != '\n') { FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); ParseNumber(ShaderSource); verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } // Packed Uniform Buffers copy lists & setup sizes for each UB/Precision entry if (FCStringAnsi::Strncmp(ShaderSource, PackedUBCopiesPrefix, PackedUBCopiesPrefixLen) == 0) { ShaderSource += PackedUBCopiesPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FMetalUniformBufferCopyInfo CopyInfo; CopyInfo.SourceUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SourceOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, '-')); CopyInfo.DestUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.DestUBTypeName = *ShaderSource++; CopyInfo.DestUBTypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(CopyInfo.DestUBTypeName); verify(Match(ShaderSource, ':')); CopyInfo.DestOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SizeInFloats = ParseNumber(ShaderSource); Header.UniformBuffersCopyInfo.Add(CopyInfo); auto& UniformBufferSize = PackedUniformBuffersSize.FindOrAdd(CopyInfo.DestUBIndex); uint16& Size = UniformBufferSize.FindOrAdd(CopyInfo.DestUBTypeName); Size = FMath::Max<uint16>(BytesPerComponent * (CopyInfo.DestOffsetInFloats + CopyInfo.SizeInFloats), Size); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } if (FCStringAnsi::Strncmp(ShaderSource, PackedUBGlobalCopiesPrefix, PackedUBGlobalCopiesPrefixLen) == 0) { ShaderSource += PackedUBGlobalCopiesPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { FMetalUniformBufferCopyInfo CopyInfo; CopyInfo.SourceUBIndex = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SourceOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, '-')); CopyInfo.DestUBIndex = 0; CopyInfo.DestUBTypeName = *ShaderSource++; CopyInfo.DestUBTypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(CopyInfo.DestUBTypeName); verify(Match(ShaderSource, ':')); CopyInfo.DestOffsetInFloats = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); CopyInfo.SizeInFloats = ParseNumber(ShaderSource); Header.UniformBuffersCopyInfo.Add(CopyInfo); uint16& Size = PackedGlobalArraySize.FindOrAdd(CopyInfo.DestUBTypeName); Size = FMath::Max<uint16>(BytesPerComponent * (CopyInfo.DestOffsetInFloats + CopyInfo.SizeInFloats), Size); if (Match(ShaderSource, '\n')) { break; } verify(Match(ShaderSource, ',')); } } Header.Bindings.bHasRegularUniformBuffers = bHasRegularUniformBuffers; // Setup Packed Array info Header.Bindings.PackedGlobalArrays.Reserve(PackedGlobalArraySize.Num()); for (auto Iterator = PackedGlobalArraySize.CreateIterator(); Iterator; ++Iterator) { ANSICHAR TypeName = Iterator.Key(); uint16 Size = Iterator.Value(); Size = (Size + 0xf) & (~0xf); CrossCompiler::FPackedArrayInfo Info; Info.Size = Size; Info.TypeName = TypeName; Info.TypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(TypeName); Header.Bindings.PackedGlobalArrays.Add(Info); } // Setup Packed Uniform Buffers info Header.Bindings.PackedUniformBuffers.Reserve(PackedUniformBuffersSize.Num()); for (auto Iterator = PackedUniformBuffersSize.CreateIterator(); Iterator; ++Iterator) { int BufferIndex = Iterator.Key(); auto& ArraySizes = Iterator.Value(); TArray<CrossCompiler::FPackedArrayInfo> InfoArray; InfoArray.Reserve(ArraySizes.Num()); for (auto IterSizes = ArraySizes.CreateIterator(); IterSizes; ++IterSizes) { ANSICHAR TypeName = IterSizes.Key(); uint16 Size = IterSizes.Value(); Size = (Size + 0xf) & (~0xf); CrossCompiler::FPackedArrayInfo Info; Info.Size = Size; Info.TypeName = TypeName; Info.TypeIndex = CrossCompiler::PackedTypeNameToTypeIndex(TypeName); InfoArray.Add(Info); } Header.Bindings.PackedUniformBuffers.Add(InfoArray); } // Then samplers. if (FCStringAnsi::Strncmp(ShaderSource, SamplersPrefix, SamplersPrefixLen) == 0) { ShaderSource += SamplersPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 Offset = 0; uint16 NumSamplers = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumSamplers = ParseNumber(ShaderSource); ParameterMap.AddParameterAllocation( *ParameterName, 0, Offset, NumSamplers ); Header.Bindings.NumSamplers = FMath::Max<uint8>( Header.Bindings.NumSamplers, Offset + NumSamplers ); if (Match(ShaderSource, '[')) { // Sampler States do { FString SamplerState = ParseIdentifier(ShaderSource); checkSlow(SamplerState.Len() != 0); ParameterMap.AddParameterAllocation( *SamplerState, 0, Offset, NumSamplers ); } while (Match(ShaderSource, ',')); verify(Match(ShaderSource, ']')); } verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } } // Then UAVs (images in Metal) if (FCStringAnsi::Strncmp(ShaderSource, UAVsPrefix, UAVsPrefixLen) == 0) { ShaderSource += UAVsPrefixLen; while (*ShaderSource && *ShaderSource != '\n') { uint16 Offset = 0; uint16 NumUAVs = 0; FString ParameterName = ParseIdentifier(ShaderSource); verify(ParameterName.Len() > 0); verify(Match(ShaderSource, '(')); Offset = ParseNumber(ShaderSource); verify(Match(ShaderSource, ':')); NumUAVs = ParseNumber(ShaderSource); ParameterMap.AddParameterAllocation( *ParameterName, 0, Offset, NumUAVs ); Header.Bindings.NumUAVs = FMath::Max<uint8>( Header.Bindings.NumUAVs, Offset + NumUAVs ); verify(Match(ShaderSource, ')')); if (Match(ShaderSource, '\n')) { break; } // Skip the comma. verify(Match(ShaderSource, ',')); } } if (FCStringAnsi::Strncmp(ShaderSource, NumThreadsPrefix, NumThreadsPrefixLen) == 0) { ShaderSource += NumThreadsPrefixLen; Header.NumThreadsX = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); Match(ShaderSource, ' '); Header.NumThreadsY = ParseNumber(ShaderSource); verify(Match(ShaderSource, ',')); Match(ShaderSource, ' '); Header.NumThreadsZ = ParseNumber(ShaderSource); verify(Match(ShaderSource, '\n')); } // Build the SRT for this shader. { // Build the generic SRT for this shader. FShaderResourceTable GenericSRT; BuildResourceTableMapping(ShaderInput.Environment.ResourceTableMap, ShaderInput.Environment.ResourceTableLayoutHashes, UsedUniformBufferSlots, ShaderOutput.ParameterMap, GenericSRT); // Copy over the bits indicating which resource tables are active. Header.Bindings.ShaderResourceTable.ResourceTableBits = GenericSRT.ResourceTableBits; Header.Bindings.ShaderResourceTable.ResourceTableLayoutHashes = GenericSRT.ResourceTableLayoutHashes; // Now build our token streams. BuildResourceTableTokenStream(GenericSRT.TextureMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.TextureMap); BuildResourceTableTokenStream(GenericSRT.ShaderResourceViewMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.ShaderResourceViewMap); BuildResourceTableTokenStream(GenericSRT.SamplerMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.SamplerMap); BuildResourceTableTokenStream(GenericSRT.UnorderedAccessViewMap, GenericSRT.MaxBoundResourceTable, Header.Bindings.ShaderResourceTable.UnorderedAccessViewMap); Header.Bindings.NumUniformBuffers = FMath::Max((uint8)GetNumUniformBuffersUsed(GenericSRT), Header.Bindings.NumUniformBuffers); } const int32 MaxSamplers = GetFeatureLevelMaxTextureSamplers(ERHIFeatureLevel::ES3_1); if (Header.Bindings.NumSamplers > MaxSamplers) { ShaderOutput.bSucceeded = false; FShaderCompilerError* NewError = new(ShaderOutput.Errors) FShaderCompilerError(); NewError->StrippedErrorMessage = FString::Printf(TEXT("shader uses %d samplers exceeding the limit of %d"), Header.Bindings.NumSamplers, MaxSamplers); } else { #if METAL_OFFLINE_COMPILE // at this point, the shader source is ready to be compiled FString InputFilename = FPaths::CreateTempFilename(*FPaths::EngineIntermediateDir(), TEXT("ShaderIn"), TEXT("")); FString ObjFilename = InputFilename + TEXT(".o"); FString ArFilename = InputFilename + TEXT(".ar"); FString OutputFilename = InputFilename + TEXT(".lib"); InputFilename = InputFilename + TEXT(".metal"); // write out shader source FFileHelper::SaveStringToFile(FString(ShaderSource), *InputFilename); int32 ReturnCode = 0; FString Results; FString Errors; bool bHadError = true; // metal commandlines FString Params = FString::Printf(TEXT("-std=ios-metal1.0 %s -o %s"), *InputFilename, *ObjFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metal"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*ObjFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { Params = FString::Printf(TEXT("r %s %s"), *ArFilename, *ObjFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metal-ar"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*ArFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { Params = FString::Printf(TEXT("-o %s %s"), *OutputFilename, *ArFilename); FPlatformProcess::ExecProcess( TEXT("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/bin/metallib"), *Params, &ReturnCode, &Results, &Errors ); // handle compile error if (ReturnCode != 0 || IFileManager::Get().FileSize(*OutputFilename) <= 0) { // FShaderCompilerError* Error = new(OutErrors) FShaderCompilerError(); // Error->ErrorFile = InputFilename; // Error->ErrorLineString = TEXT("0"); // Error->StrippedErrorMessage = Results + Errors; } else { bHadError = false; // Write out the header and compiled shader code FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 1; Ar << PrecompiledFlag; Ar << Header; // load output TArray<uint8> CompiledShader; FFileHelper::LoadFileToArray(CompiledShader, *OutputFilename); // jam it into the output bytes Ar.Serialize(CompiledShader.GetData(), CompiledShader.Num()); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; } } } if (bHadError) { // Write out the header and shader source code. FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 0; Ar << PrecompiledFlag; Ar << Header; Ar.Serialize((void*)ShaderSource, SourceLen + 1 - (ShaderSource - InShaderSource)); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; } IFileManager::Get().Delete(*InputFilename); IFileManager::Get().Delete(*ObjFilename); IFileManager::Get().Delete(*ArFilename); IFileManager::Get().Delete(*OutputFilename); #else // Write out the header and shader source code. FMemoryWriter Ar(ShaderOutput.Code, true); uint8 PrecompiledFlag = 0; Ar << PrecompiledFlag; Ar << Header; Ar.Serialize((void*)ShaderSource, SourceLen + 1 - (ShaderSource - InShaderSource)); ShaderOutput.NumInstructions = 0; ShaderOutput.NumTextureSamplers = Header.Bindings.NumSamplers; ShaderOutput.bSucceeded = true; #endif } }
void FComponentEditorUtils::CopyComponents(const TArray<UActorComponent*>& ComponentsToCopy) { FStringOutputDevice Archive; const FExportObjectInnerContext Context; // Clear the mark state for saving. UnMarkAllObjects(EObjectMark(OBJECTMARK_TagExp | OBJECTMARK_TagImp)); // Duplicate the selected component templates into temporary objects that we can modify TMap<FName, FName> ParentMap; TMap<FName, UActorComponent*> ObjectMap; for (UActorComponent* Component : ComponentsToCopy) { // Duplicate the component into a temporary object UObject* DuplicatedComponent = StaticDuplicateObject(Component, GetTransientPackage(), Component->GetFName(), RF_AllFlags & ~RF_ArchetypeObject); if (DuplicatedComponent) { // If the duplicated component is a scene component, wipe its attach parent (to prevent log warnings for referencing a private object in an external package) if (auto DuplicatedCompAsSceneComp = Cast<USceneComponent>(DuplicatedComponent)) { DuplicatedCompAsSceneComp->AttachParent = nullptr; } // Find the closest parent component of the current component within the list of components to copy USceneComponent* ClosestSelectedParent = FindClosestParentInList(Component, ComponentsToCopy); if (ClosestSelectedParent) { // If the parent is included in the list, record it into the node->parent map ParentMap.Add(Component->GetFName(), ClosestSelectedParent->GetFName()); } // Record the temporary object into the name->object map ObjectMap.Add(Component->GetFName(), CastChecked<UActorComponent>(DuplicatedComponent)); } } // Export the component object(s) to text for copying for (auto ObjectIt = ObjectMap.CreateIterator(); ObjectIt; ++ObjectIt) { // Get the component object to be copied UActorComponent* ComponentToCopy = ObjectIt->Value; check(ComponentToCopy); // If this component object had a parent within the selected set if (ParentMap.Contains(ComponentToCopy->GetFName())) { // Get the name of the parent component FName ParentName = ParentMap[ComponentToCopy->GetFName()]; if (ObjectMap.Contains(ParentName)) { // Ensure that this component is a scene component USceneComponent* SceneComponent = Cast<USceneComponent>(ComponentToCopy); if (SceneComponent) { // Set the attach parent to the matching parent object in the temporary set. This allows us to preserve hierarchy in the copied set. SceneComponent->AttachParent = Cast<USceneComponent>(ObjectMap[ParentName]); } } } // Export the component object to the given string UExporter::ExportToOutputDevice(&Context, ComponentToCopy, NULL, Archive, TEXT("copy"), 0, PPF_ExportsNotFullyQualified | PPF_Copy | PPF_Delimited, false, ComponentToCopy->GetOuter()); } // Copy text to clipboard FString ExportedText = Archive; FPlatformMisc::ClipboardCopy(*ExportedText); }
void FVisualLoggerCanvasRenderer::DrawHistogramGraphs(class UCanvas* Canvas, class APlayerController*) { struct FGraphLineData { FName DataName; FVector2D LeftExtreme, RightExtreme; TArray<FVector2D> Samples; }; struct FGraphData { FGraphData() : Min(FVector2D(FLT_MAX, FLT_MAX)), Max(FVector2D(FLT_MIN, FLT_MIN)) {} FVector2D Min, Max; TMap<FName, FGraphLineData> GraphLines; }; if (FLogVisualizer::Get().GetTimeSliderController().IsValid() == false) { return; } TMap<FName, FGraphData> CollectedGraphs; const FVisualLoggerTimeSliderArgs& TimeSliderArgs = FLogVisualizer::Get().GetTimeSliderController()->GetTimeSliderArgs(); TRange<float> LocalViewRange = TimeSliderArgs.ViewRange.Get(); const float LocalViewRangeMin = LocalViewRange.GetLowerBoundValue(); const float LocalViewRangeMax = LocalViewRange.GetUpperBoundValue(); const float LocalSequenceLength = LocalViewRangeMax - LocalViewRangeMin; const float WindowHalfWidth = LocalSequenceLength * TimeSliderArgs.CursorSize.Get() * 0.5f; const FVector2D TimeStampWindow(SelectedEntry.TimeStamp - WindowHalfWidth, SelectedEntry.TimeStamp + WindowHalfWidth); const TArray<FVisualLogDevice::FVisualLogEntryItem> &ObjectItems = CurrentTimeLine.Pin()->GetEntries(); int32 ColorIndex = 0; int32 LeftSideOutsideIndex = INDEX_NONE; int32 RightSideOutsideIndex = INDEX_NONE; for (int32 EntryIndex = 0; EntryIndex < ObjectItems.Num(); ++EntryIndex) { const FVisualLogEntry* CurrentEntry = &(ObjectItems[EntryIndex].Entry); if (CurrentEntry->TimeStamp < TimeStampWindow.X) { LeftSideOutsideIndex = EntryIndex; continue; } if (CurrentEntry->TimeStamp > TimeStampWindow.Y) { RightSideOutsideIndex = EntryIndex; break; } const int32 SamplesNum = CurrentEntry->HistogramSamples.Num(); for (int32 SampleIndex = 0; SampleIndex < SamplesNum; ++SampleIndex) { FVisualLogHistogramSample CurrentSample = CurrentEntry->HistogramSamples[SampleIndex]; const FName CurrentCategory = CurrentSample.Category; const FName CurrentGraphName = CurrentSample.GraphName; const FName CurrentDataName = CurrentSample.DataName; FString GraphFilterName = CurrentSample.GraphName.ToString() +TEXT("$") + CurrentSample.DataName.ToString(); const bool bIsValidByFilter = FCategoryFiltersManager::Get().MatchCategoryFilters(GraphFilterName, ELogVerbosity::All); if (bIsValidByFilter) { FGraphData &GraphData = CollectedGraphs.FindOrAdd(CurrentSample.GraphName); FGraphLineData &LineData = GraphData.GraphLines.FindOrAdd(CurrentSample.DataName); LineData.DataName = CurrentSample.DataName; LineData.Samples.Add(CurrentSample.SampleValue); GraphData.Min.X = FMath::Min(GraphData.Min.X, CurrentSample.SampleValue.X); GraphData.Min.Y = FMath::Min(GraphData.Min.Y, CurrentSample.SampleValue.Y); GraphData.Max.X = FMath::Max(GraphData.Max.X, CurrentSample.SampleValue.X); GraphData.Max.Y = FMath::Max(GraphData.Max.Y, CurrentSample.SampleValue.Y); } } } const int32 ExtremeValueIndexes[] = { LeftSideOutsideIndex != INDEX_NONE ? LeftSideOutsideIndex : 0, RightSideOutsideIndex != INDEX_NONE ? RightSideOutsideIndex : ObjectItems.Num() - 1 }; for (int32 ObjectIndex = 0; ObjectIndex < 2; ++ObjectIndex) { const FVisualLogEntry* CurrentEntry = &(ObjectItems[ExtremeValueIndexes[ObjectIndex]].Entry); const int32 SamplesNum = CurrentEntry->HistogramSamples.Num(); for (int32 SampleIndex = 0; SampleIndex < SamplesNum; ++SampleIndex) { FVisualLogHistogramSample CurrentSample = CurrentEntry->HistogramSamples[SampleIndex]; const FName CurrentCategory = CurrentSample.Category; const FName CurrentGraphName = CurrentSample.GraphName; const FName CurrentDataName = CurrentSample.DataName; FString GraphFilterName = CurrentSample.GraphName.ToString() + TEXT("_") + CurrentSample.DataName.ToString(); const bool bIsValidByFilter = FCategoryFiltersManager::Get().MatchCategoryFilters(GraphFilterName, ELogVerbosity::All); if (bIsValidByFilter) { FGraphData &GraphData = CollectedGraphs.FindOrAdd(CurrentSample.GraphName); FGraphLineData &LineData = GraphData.GraphLines.FindOrAdd(CurrentSample.DataName); LineData.DataName = CurrentSample.DataName; if (ObjectIndex == 0) LineData.LeftExtreme = CurrentSample.SampleValue; else LineData.RightExtreme = CurrentSample.SampleValue; } } } const float GoldenRatioConjugate = 0.618033988749895f; if (CollectedGraphs.Num() > 0) { const FColor GraphsBackgroundColor = ULogVisualizerSettings::StaticClass()->GetDefaultObject<ULogVisualizerSettings>()->GraphsBackgroundColor; const int NumberOfGraphs = CollectedGraphs.Num(); const int32 NumberOfColumns = FMath::CeilToInt(FMath::Sqrt(NumberOfGraphs)); int32 NumberOfRows = FMath::FloorToInt(NumberOfGraphs / NumberOfColumns); if (NumberOfGraphs - NumberOfRows * NumberOfColumns > 0) { NumberOfRows += 1; } const int32 MaxNumberOfGraphs = FMath::Max(NumberOfRows, NumberOfColumns); const float GraphWidth = 0.8f / NumberOfColumns; const float GraphHeight = 0.8f / NumberOfRows; const float XGraphSpacing = 0.2f / (MaxNumberOfGraphs + 1); const float YGraphSpacing = 0.2f / (MaxNumberOfGraphs + 1); const float StartX = XGraphSpacing; float StartY = 0.5 + (0.5 * NumberOfRows - 1) * (GraphHeight + YGraphSpacing); float CurrentX = StartX; float CurrentY = StartY; int32 GraphIndex = 0; int32 CurrentColumn = 0; int32 CurrentRow = 0; bool bDrawExtremesOnGraphs = ULogVisualizerSettings::StaticClass()->GetDefaultObject<ULogVisualizerSettings>()->bDrawExtremesOnGraphs; for (auto It(CollectedGraphs.CreateIterator()); It; ++It) { TWeakObjectPtr<UReporterGraph> HistogramGraph = Canvas->GetReporterGraph(); if (!HistogramGraph.IsValid()) { break; } HistogramGraph->SetNumGraphLines(It->Value.GraphLines.Num()); int32 LineIndex = 0; UFont* Font = GEngine->GetSmallFont(); int32 MaxStringSize = 0; float Hue = 0; auto& CategoriesForGraph = UsedGraphCategories.FindOrAdd(It->Key.ToString()); It->Value.GraphLines.KeySort(TLess<FName>()); for (auto LinesIt(It->Value.GraphLines.CreateConstIterator()); LinesIt; ++LinesIt) { const FString DataName = LinesIt->Value.DataName.ToString(); int32 CategoryIndex = CategoriesForGraph.Find(DataName); if (CategoryIndex == INDEX_NONE) { CategoryIndex = CategoriesForGraph.AddUnique(DataName); } Hue = CategoryIndex * GoldenRatioConjugate; if (Hue > 1) { Hue -= FMath::FloorToFloat(Hue); } HistogramGraph->GetGraphLine(LineIndex)->Color = FLinearColor::FGetHSV(Hue * 255, 0, 244); HistogramGraph->GetGraphLine(LineIndex)->LineName = DataName; HistogramGraph->GetGraphLine(LineIndex)->Data.Append(LinesIt->Value.Samples); HistogramGraph->GetGraphLine(LineIndex)->LeftExtreme = LinesIt->Value.LeftExtreme; HistogramGraph->GetGraphLine(LineIndex)->RightExtreme = LinesIt->Value.RightExtreme; int32 DummyY, StringSizeX; StringSize(Font, StringSizeX, DummyY, *LinesIt->Value.DataName.ToString()); MaxStringSize = StringSizeX > MaxStringSize ? StringSizeX : MaxStringSize; ++LineIndex; } FVector2D GraphSpaceSize; GraphSpaceSize.Y = GraphSpaceSize.X = 0.8f / CollectedGraphs.Num(); HistogramGraph->SetGraphScreenSize(CurrentX, CurrentX + GraphWidth, CurrentY, CurrentY + GraphHeight); CurrentX += GraphWidth + XGraphSpacing; HistogramGraph->SetAxesMinMax(FVector2D(TimeStampWindow.X, It->Value.Min.Y), FVector2D(TimeStampWindow.Y, It->Value.Max.Y)); HistogramGraph->DrawCursorOnGraph(true); HistogramGraph->UseTinyFont(CollectedGraphs.Num() >= 5); HistogramGraph->SetCursorLocation(SelectedEntry.TimeStamp); HistogramGraph->SetNumThresholds(0); HistogramGraph->SetStyles(EGraphAxisStyle::Grid, EGraphDataStyle::Lines); HistogramGraph->SetBackgroundColor(GraphsBackgroundColor); HistogramGraph->SetLegendPosition(/*bShowHistogramLabelsOutside*/ false ? ELegendPosition::Outside : ELegendPosition::Inside); HistogramGraph->OffsetDataSets(/*bOffsetDataSet*/false); HistogramGraph->DrawExtremesOnGraph(bDrawExtremesOnGraphs); HistogramGraph->bVisible = true; HistogramGraph->Draw(Canvas); ++GraphIndex; if (++CurrentColumn >= NumberOfColumns) { CurrentColumn = 0; CurrentRow++; CurrentX = StartX; CurrentY -= GraphHeight + YGraphSpacing; } } } }
void AGameplayDebuggerReplicator::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction) { Super::TickActor(DeltaTime, TickType, ThisTickFunction); #if ENABLED_GAMEPLAY_DEBUGGER UWorld* World = GetWorld(); const ENetMode NetMode = GetNetMode(); if (!World) { // return without world return; } UGameInstance* GameInstance = World->GetGameInstance(); if (!GameInstance || !World->IsGameWorld()) { return; } if (NetMode != NM_DedicatedServer) { if (bActivationKeyPressed) { ActivationKeyTime += DeltaTime; if (ActivationKeyTime >= GameplayDebuggerHelpers::ActivationKeyTimePch) { GEngine->bEnableOnScreenDebugMessages = false; if (AHUD* const GameHUD = LocalPlayerOwner ? LocalPlayerOwner->GetHUD() : nullptr) { GameHUD->bShowHUD = false; } BindKeyboardInput(InputComponent); ServerActivateGameplayDebugger(true); ClientActivateGameplayDebugger(true); bActivationKeyPressed = false; } } if (bEnabledTargetSelection) { if (GetLocalPlayerOwner()) { SelectTargetToDebug(); } } bool bMarkComponentsAsRenderStateDirty = false; for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects) { if (Obj && Obj->IsRenderStateDirty()) { if (!bMarkComponentsAsRenderStateDirty) { MarkComponentsRenderStateDirty(); } bMarkComponentsAsRenderStateDirty = true; Obj->CleanRenderStateDirtyFlag(); } } } if (NetMode < NM_Client && LocalPlayerOwner) { TMap<FString, TArray<UGameplayDebuggerBaseObject*> > CategoryToClasses; for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects) { if (Obj) { FString Category = Obj->GetCategoryName(); if (IsCategoryEnabled(Category)) { CategoryToClasses.FindOrAdd(Category).Add(Obj); } } } for (auto It(CategoryToClasses.CreateIterator()); It; ++It) { TArray<UGameplayDebuggerBaseObject*>& CurrentObjects = It.Value(); for (UGameplayDebuggerBaseObject* Obj : CurrentObjects) { Obj->CollectDataToReplicateOnServer(LocalPlayerOwner, LastSelectedActorToDebug); } } } #endif }
void AGameplayDebuggerReplicator::DrawDebugData(class UCanvas* Canvas, class APlayerController* PC, bool bHideMenu) { #if ENABLED_GAMEPLAY_DEBUGGER if (!LocalPlayerOwner && IsActorTickEnabled()) { return; } const bool bAllowToDraw = Canvas && Canvas->SceneView && (Canvas->SceneView->ViewActor == LocalPlayerOwner->AcknowledgedPawn || Canvas->SceneView->ViewActor == LocalPlayerOwner->GetPawnOrSpectator()); if (!bAllowToDraw) { // check for spectator debug camera during debug camera if (DebugCameraController.IsValid() == false || Canvas->SceneView->ViewActor->GetInstigatorController() != DebugCameraController.Get()) { return; } } const float DebugInfoStartX = UGameplayDebuggerModuleSettings::StaticClass()->GetDefaultObject<UGameplayDebuggerModuleSettings>()->DebugInfoStart.X; const float DebugInfoStartY = UGameplayDebuggerModuleSettings::StaticClass()->GetDefaultObject<UGameplayDebuggerModuleSettings>()->DebugInfoStart.Y; const FVector SelectedActorLoc = LastSelectedActorToDebug ? LastSelectedActorToDebug->GetActorLocation() + FVector(0, 0, LastSelectedActorToDebug->GetSimpleCollisionHalfHeight()) : DebugTools::InvalidLocation; UGameplayDebuggerHelper::FPrintContext DefaultContext(GEngine->GetSmallFont(), Canvas, DebugInfoStartX, DebugInfoStartY); DefaultContext.FontRenderInfo.bEnableShadow = true; const bool bDrawFullData = SelectedActorLoc != DebugTools::InvalidLocation; const FVector ScreenLoc = SelectedActorLoc != DebugTools::InvalidLocation ? UGameplayDebuggerHelper::ProjectLocation(DefaultContext, SelectedActorLoc) : FVector::ZeroVector; UGameplayDebuggerHelper::FPrintContext OverHeadContext(GEngine->GetSmallFont(), Canvas, ScreenLoc.X, ScreenLoc.Y); UGameplayDebuggerHelper::SetOverHeadContext(OverHeadContext); UGameplayDebuggerHelper::SetDefaultContext(DefaultContext); if (DefaultContext.Canvas != nullptr) { float XL, YL; const FString ToolName = FString::Printf(TEXT("Gameplay Debugger [Timestamp: %05.03f]"), GetWorld()->TimeSeconds); UGameplayDebuggerHelper::CalulateStringSize(DefaultContext, nullptr, ToolName, XL, YL); UGameplayDebuggerHelper::PrintString(DefaultContext, FColorList::White, ToolName, DefaultContext.Canvas->ClipX / 2.0f - XL / 2.0f, 0); } if (!bHideMenu) { DrawMenu(DefaultContext, OverHeadContext); } TMap<FString, TArray<UGameplayDebuggerBaseObject*> > CategoryToClasses; for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects) { if (Obj) { FString Category = Obj->GetCategoryName(); CategoryToClasses.FindOrAdd(Category).Add(Obj); } } CategoryToClasses.KeySort(TLess<FString>()); for (auto It(CategoryToClasses.CreateIterator()); It; ++It) { const FGameplayDebuggerCategorySettings* Element = Categories.FindByPredicate([&](const FGameplayDebuggerCategorySettings& C){ return It.Key() == C.CategoryName; }); if (Element == nullptr || Element->bPIE == false) { continue; } UGameplayDebuggerHelper::PrintString(UGameplayDebuggerHelper::GetDefaultContext(), FString::Printf(TEXT("\n{R=0,G=255,B=0,A=255}%s\n"), *It.Key())); TArray<UGameplayDebuggerBaseObject*>& CurrentObjects = It.Value(); for (UGameplayDebuggerBaseObject* Obj : CurrentObjects) { Obj->DrawCollectedData(LocalPlayerOwner, LastSelectedActorToDebug); } } const IConsoleVariable* cvarHighlightSelectedActor = IConsoleManager::Get().FindConsoleVariable(TEXT("ai.gd.HighlightSelectedActor")); const bool bHighlightSelectedActor = !cvarHighlightSelectedActor || cvarHighlightSelectedActor->GetInt(); if (LastSelectedActorToDebug && bHighlightSelectedActor) { FBox ComponentsBoundingBox = LastSelectedActorToDebug->GetComponentsBoundingBox(false); DrawDebugBox(GetWorld(), ComponentsBoundingBox.GetCenter(), ComponentsBoundingBox.GetExtent(), FColor::Red, false); DrawDebugSolidBox(GetWorld(), ComponentsBoundingBox.GetCenter(), ComponentsBoundingBox.GetExtent(), FColor::Red.WithAlpha(25)); } #endif }
void FixUpChunkBoneMaps( FSkelMeshChunk & Chunk, const TMap<FBoneIndexType, FBoneIndexType> &BonesToRepair ) override { // now you have list of bones, remove them from vertex influences { TMap<uint8, uint8> BoneMapRemapTable; // first go through bone map and see if this contains BonesToRemove int32 BoneMapSize = Chunk.BoneMap.Num(); int32 AdjustIndex=0; for (int32 BoneMapIndex=0; BoneMapIndex < BoneMapSize; ++BoneMapIndex ) { // look for this bone to be removed or not? const FBoneIndexType* ParentBoneIndex = BonesToRepair.Find(Chunk.BoneMap[BoneMapIndex]); if ( ParentBoneIndex ) { // this should not happen, I don't ever remove root check (*ParentBoneIndex!=INDEX_NONE); // if Parent already exists in the current BoneMap, we just have to fix up the mapping int32 ParentBoneMapIndex = Chunk.BoneMap.Find(*ParentBoneIndex); // if it exists if (ParentBoneMapIndex != INDEX_NONE) { // if parent index is higher, we have to decrease it to match to new index if (ParentBoneMapIndex > BoneMapIndex) { --ParentBoneMapIndex; } // remove current chunk count, will replace with parent Chunk.BoneMap.RemoveAt(BoneMapIndex); } else { // if parent doens't exists, we have to add one // this doesn't change bone map size Chunk.BoneMap.RemoveAt(BoneMapIndex); ParentBoneMapIndex = Chunk.BoneMap.Add(*ParentBoneIndex); } // first fix up all indices of BoneMapRemapTable for the indices higher than BoneMapIndex, since BoneMapIndex is being removed for (auto Iter = BoneMapRemapTable.CreateIterator(); Iter; ++Iter) { uint8& Value = Iter.Value(); check (Value != BoneMapIndex); if (Value > BoneMapIndex) { --Value; } } int32 OldIndex = BoneMapIndex+AdjustIndex; int32 NewIndex = ParentBoneMapIndex; // you still have to add no matter what even if same since indices might change after added { // add to remap table check (OldIndex < 256 && OldIndex >= 0); check (NewIndex < 256 && NewIndex >= 0); check (BoneMapRemapTable.Contains((uint8)OldIndex) == false); BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex); } // reduce index since the item is removed --BoneMapIndex; --BoneMapSize; // this is to adjust the later indices. We need to refix their indices ++AdjustIndex; } else if (AdjustIndex > 0) { int32 OldIndex = BoneMapIndex+AdjustIndex; int32 NewIndex = BoneMapIndex; check (OldIndex < 256 && OldIndex >= 0); check (NewIndex < 256 && NewIndex >= 0); check (BoneMapRemapTable.Contains((uint8)OldIndex) == false); BoneMapRemapTable.Add((uint8)OldIndex, (uint8)NewIndex); } } if ( BoneMapRemapTable.Num() > 0 ) { // fix up rigid verts for (int32 VertIndex=0; VertIndex < Chunk.RigidVertices.Num(); ++VertIndex) { FRigidSkinVertex & Vert = Chunk.RigidVertices[VertIndex]; uint8 *RemappedBone = BoneMapRemapTable.Find(Vert.Bone); if (RemappedBone) { Vert.Bone = *RemappedBone; } } // fix up soft verts for (int32 VertIndex=0; VertIndex < Chunk.SoftVertices.Num(); ++VertIndex) { FSoftSkinVertex & Vert = Chunk.SoftVertices[VertIndex]; bool ShouldRenormalize = false; for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++) { uint8 *RemappedBone = BoneMapRemapTable.Find(Vert.InfluenceBones[InfluenceIndex]); if (RemappedBone) { Vert.InfluenceBones[InfluenceIndex] = *RemappedBone; ShouldRenormalize = true; } } if (ShouldRenormalize) { // should see if same bone exists for(int32 InfluenceIndex = 0;InfluenceIndex < MAX_TOTAL_INFLUENCES;InfluenceIndex++) { for(int32 InfluenceIndex2 = InfluenceIndex+1;InfluenceIndex2 < MAX_TOTAL_INFLUENCES;InfluenceIndex2++) { // cannot be 0 because we don't allow removing root if (Vert.InfluenceBones[InfluenceIndex] != 0 && Vert.InfluenceBones[InfluenceIndex] == Vert.InfluenceBones[InfluenceIndex2]) { Vert.InfluenceWeights[InfluenceIndex] += Vert.InfluenceWeights[InfluenceIndex2]; // reset Vert.InfluenceBones[InfluenceIndex2] = 0; Vert.InfluenceWeights[InfluenceIndex2] = 0; } } } } } } // @todo fix up RequiredBones/ActiveBoneIndices? } }
void FRawProfilerSession::ProcessStatPacketArray( const FStatPacketArray& StatPacketArray, FProfilerFrame& out_ProfilerFrame, int32 FrameIndex ) { // @TODO yrx 2014-03-24 Standardize thread names and id // @TODO yrx 2014-04-22 Remove all references to the data provider, event graph etc once data graph can visualize. // Raw stats callstack for this stat packet array. TMap<FName,FProfilerStackNode*> ThreadNodes; const FProfilerStatMetaDataRef MetaData = GetMetaData(); FProfilerSampleArray& MutableCollection = const_cast<FProfilerSampleArray&>(DataProvider->GetCollection()); // Add a root sample for this frame. const uint32 FrameRootSampleIndex = DataProvider->AddHierarchicalSample( 0, MetaData->GetStatByID( 1 ).OwningGroup().ID(), 1, 0.0f, 0.0f, 1 ); // Iterate through all stats packets and raw stats messages. FName GameThreadFName = NAME_None; for( int32 PacketIndex = 0; PacketIndex < StatPacketArray.Packets.Num(); PacketIndex++ ) { const FStatPacket& StatPacket = *StatPacketArray.Packets[PacketIndex]; FName ThreadFName = StatsThreadStats.Threads.FindChecked( StatPacket.ThreadId ); const uint32 NewThreadID = MetaData->ThreadIDtoStatID.FindChecked( StatPacket.ThreadId ); // @TODO yrx 2014-04-29 Only game or render thread is supported at this moment. if( StatPacket.ThreadType != EThreadType::Game && StatPacket.ThreadType != EThreadType::Renderer ) { continue; } // Workaround for issue with rendering thread names. if( StatPacket.ThreadType == EThreadType::Renderer ) { ThreadFName = NAME_RenderThread; } else if( StatPacket.ThreadType == EThreadType::Game ) { GameThreadFName = ThreadFName; } FProfilerStackNode* ThreadNode = ThreadNodes.FindRef( ThreadFName ); if( !ThreadNode ) { FString ThreadIdName = FStatsUtils::BuildUniqueThreadName( StatPacket.ThreadId ); FStatMessage ThreadMessage( ThreadFName, EStatDataType::ST_int64, STAT_GROUP_TO_FStatGroup( STATGROUP_Threads )::GetGroupName(), STAT_GROUP_TO_FStatGroup( STATGROUP_Threads )::GetGroupCategory(), *ThreadIdName, true, true ); //FStatMessage ThreadMessage( ThreadFName, EStatDataType::ST_int64, nullptr, nullptr, TEXT( "" ), true, true ); ThreadMessage.NameAndInfo.SetFlag( EStatMetaFlags::IsPackedCCAndDuration, true ); ThreadMessage.Clear(); // Add a thread sample. const uint32 ThreadRootSampleIndex = DataProvider->AddHierarchicalSample ( NewThreadID, MetaData->GetStatByID( NewThreadID ).OwningGroup().ID(), NewThreadID, -1.0f, -1.0f, 1, FrameRootSampleIndex ); ThreadNode = ThreadNodes.Add( ThreadFName, new FProfilerStackNode( nullptr, ThreadMessage, ThreadRootSampleIndex, FrameIndex ) ); } TArray<const FStatMessage*> StartStack; TArray<FProfilerStackNode*> Stack; Stack.Add( ThreadNode ); FProfilerStackNode* Current = Stack.Last(); const FStatMessagesArray& Data = StatPacket.StatMessages; for( int32 Index = 0; Index < Data.Num(); Index++ ) { const FStatMessage& Item = Data[Index]; const EStatOperation::Type Op = Item.NameAndInfo.GetField<EStatOperation>(); const FName LongName = Item.NameAndInfo.GetRawName(); const FName ShortName = Item.NameAndInfo.GetShortName(); const FName RenderingThreadTickCommandName = TEXT("RenderingThreadTickCommand"); // Workaround for render thread hierarchy. EStatOperation::AdvanceFrameEventRenderThread is called within the scope. if( ShortName == RenderingThreadTickCommandName ) { continue; } if( Op == EStatOperation::CycleScopeStart || Op == EStatOperation::CycleScopeEnd || Op == EStatOperation::AdvanceFrameEventRenderThread ) { //check( Item.NameAndInfo.GetFlag( EStatMetaFlags::IsCycle ) ); if( Op == EStatOperation::CycleScopeStart ) { FProfilerStackNode* ChildNode = new FProfilerStackNode( Current, Item, -1, FrameIndex ); Current->Children.Add( ChildNode ); // Add a child sample. const uint32 SampleIndex = DataProvider->AddHierarchicalSample ( NewThreadID, MetaData->GetStatByFName( ShortName ).OwningGroup().ID(), // GroupID MetaData->GetStatByFName( ShortName ).ID(), // StatID MetaData->ConvertCyclesToMS( ChildNode->CyclesStart ), // StartMS MetaData->ConvertCyclesToMS( 0 ), // DurationMS 1, Current->SampleIndex ); ChildNode->SampleIndex = SampleIndex; Stack.Add( ChildNode ); StartStack.Add( &Item ); Current = ChildNode; } // Workaround for render thread hierarchy. EStatOperation::AdvanceFrameEventRenderThread is called within the scope. if( Op == EStatOperation::AdvanceFrameEventRenderThread ) { int k=0;k++; } if( Op == EStatOperation::CycleScopeEnd ) { const FStatMessage ScopeStart = *StartStack.Pop(); const FStatMessage ScopeEnd = Item; const int64 Delta = int32( uint32( ScopeEnd.GetValue_int64() ) - uint32( ScopeStart.GetValue_int64() ) ); Current->CyclesEnd = Current->CyclesStart + Delta; Current->CycleCounterStartTimeMS = MetaData->ConvertCyclesToMS( Current->CyclesStart ); Current->CycleCounterEndTimeMS = MetaData->ConvertCyclesToMS( Current->CyclesEnd ); if( Current->CycleCounterStartTimeMS > Current->CycleCounterEndTimeMS ) { int k=0;k++; } check( Current->CycleCounterEndTimeMS >= Current->CycleCounterStartTimeMS ); FProfilerStackNode* ChildNode = Current; // Update the child sample's DurationMS. MutableCollection[ChildNode->SampleIndex].SetDurationMS( MetaData->ConvertCyclesToMS( Delta ) ); verify( Current == Stack.Pop() ); Current = Stack.Last(); } } } } // Calculate thread times. for( auto It = ThreadNodes.CreateIterator(); It; ++It ) { FProfilerStackNode& ThreadNode = *It.Value(); const int32 ChildrenNum = ThreadNode.Children.Num(); if( ChildrenNum > 0 ) { const int32 LastChildIndex = ThreadNode.Children.Num() - 1; ThreadNode.CyclesStart = ThreadNode.Children[0]->CyclesStart; ThreadNode.CyclesEnd = ThreadNode.Children[LastChildIndex]->CyclesEnd; ThreadNode.CycleCounterStartTimeMS = MetaData->ConvertCyclesToMS( ThreadNode.CyclesStart ); ThreadNode.CycleCounterEndTimeMS = MetaData->ConvertCyclesToMS( ThreadNode.CyclesEnd ); FProfilerSample& ProfilerSample = MutableCollection[ThreadNode.SampleIndex]; ProfilerSample.SetStartAndEndMS( MetaData->ConvertCyclesToMS( ThreadNode.CyclesStart ), MetaData->ConvertCyclesToMS( ThreadNode.CyclesEnd ) ); } } // Get the game thread time. check( GameThreadFName != NAME_None ); const FProfilerStackNode& GameThreadNode = *ThreadNodes.FindChecked( GameThreadFName ); const double GameThreadStartMS = MetaData->ConvertCyclesToMS( GameThreadNode.CyclesStart ); const double GameThreadEndMS = MetaData->ConvertCyclesToMS( GameThreadNode.CyclesEnd ); MutableCollection[FrameRootSampleIndex].SetStartAndEndMS( GameThreadStartMS, GameThreadEndMS ); // Advance frame const uint32 LastFrameIndex = DataProvider->GetNumFrames(); DataProvider->AdvanceFrame( GameThreadEndMS - GameThreadStartMS ); // Update aggregated stats UpdateAggregatedStats( LastFrameIndex ); // Update aggregated events. UpdateAggregatedEventGraphData( LastFrameIndex ); // RootNode is the same as the game thread node. out_ProfilerFrame.Root->CycleCounterStartTimeMS = GameThreadStartMS; out_ProfilerFrame.Root->CycleCounterEndTimeMS = GameThreadEndMS; for( auto It = ThreadNodes.CreateIterator(); It; ++It ) { out_ProfilerFrame.AddChild( It.Value() ); } out_ProfilerFrame.SortChildren(); }
void FAssetTypeActions_SoundCue::ExecuteConsolidateAttenuation(TArray<TWeakObjectPtr<USoundCue>> Objects) { TMap<FAttenuationSettings*,TArray<USoundCue*>> UnmatchedAttenuations; for (auto ObjIt = Objects.CreateConstIterator(); ObjIt; ++ObjIt) { USoundCue* SoundCue = (*ObjIt).Get(); bool bFound = false; if ( SoundCue && SoundCue->bOverrideAttenuation ) { for (auto UnmatchedIt = UnmatchedAttenuations.CreateIterator(); UnmatchedIt; ++UnmatchedIt) { // Found attenuation settings to consolidate together if (SoundCue->AttenuationOverrides == *UnmatchedIt.Key()) { UnmatchedIt.Value().Add(SoundCue); bFound = true; break; } } if (!bFound) { UnmatchedAttenuations.FindOrAdd(&SoundCue->AttenuationOverrides).Add(SoundCue); } } } if (UnmatchedAttenuations.Num() > 0) { FString DefaultSuffix; TArray<UObject*> ObjectsToSync; FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools"); USoundAttenuationFactory* Factory = ConstructObject<USoundAttenuationFactory>(USoundAttenuationFactory::StaticClass()); for (auto UnmatchedIt = UnmatchedAttenuations.CreateConstIterator(); UnmatchedIt; ++UnmatchedIt) { if (UnmatchedIt.Value().Num() > 1) { FString Name; FString PackageName; CreateUniqueAssetName("/Game/Sounds/SoundAttenuations/SharedAttenuation", DefaultSuffix, PackageName, Name); USoundAttenuation* SoundAttenuation = Cast<USoundAttenuation>(AssetToolsModule.Get().CreateAsset(Name, FPackageName::GetLongPackagePath(PackageName), USoundAttenuation::StaticClass(), Factory)); if (SoundAttenuation) { SoundAttenuation->Attenuation = *UnmatchedIt.Key(); for (int32 SoundCueIndex = 0; SoundCueIndex < UnmatchedIt.Value().Num(); ++SoundCueIndex) { USoundCue* SoundCue = UnmatchedIt.Value()[SoundCueIndex]; SoundCue->bOverrideAttenuation = false; SoundCue->AttenuationSettings = SoundAttenuation; SoundCue->MarkPackageDirty(); } } } } if ( ObjectsToSync.Num() > 0 ) { FAssetTools::Get().SyncBrowserToAssets(ObjectsToSync); } } }
void UActorComponent::PostEditUndo() { // Objects marked pending kill don't call PostEditChange() from UObject::PostEditUndo(), // so they can leave an EditReregisterContexts entry around if they are deleted by an undo action. if( IsPendingKill() ) { // The reregister context won't bother attaching components that are 'pending kill'. FComponentReregisterContext* ReregisterContext = nullptr; if (EditReregisterContexts.RemoveAndCopyValue(this, ReregisterContext)) { delete ReregisterContext; } else { // This means there are likely some stale elements left in there now, strip them out for (auto It(EditReregisterContexts.CreateIterator()); It; ++It) { if (!It.Key().IsValid()) { It.RemoveCurrent(); } } } } else { bIsBeingDestroyed = false; Owner = GetTypedOuter<AActor>(); bCanUseCachedOwner = true; // Let the component be properly registered, after it was restored. if (Owner) { Owner->AddOwnedComponent(this); } TArray<UObject*> Children; GetObjectsWithOuter(this, Children); for (UObject* Child : Children) { if (UActorComponent* ChildComponent = Cast<UActorComponent>(Child)) { if (ChildComponent->Owner) { ChildComponent->Owner->RemoveOwnedComponent(ChildComponent); } ChildComponent->Owner = Owner; if (Owner) { Owner->AddOwnedComponent(ChildComponent); } } } if (GetWorld()) { GetWorld()->UpdateActorComponentEndOfFrameUpdateState(this); } } Super::PostEditUndo(); }