void FLightmapCustomNodeBuilder::RefreshLightmapItems() { LightmapItems.Empty(); FWorldContext& Context = GEditor->GetEditorWorldContext(); UWorld* World = Context.World(); if ( World ) { TArray<UTexture2D*> LightMapsAndShadowMaps; World->GetLightMapsAndShadowMaps(World->GetCurrentLevel(), LightMapsAndShadowMaps); for ( auto ObjIt = LightMapsAndShadowMaps.CreateConstIterator(); ObjIt; ++ObjIt ) { UTexture2D* CurrentObject = *ObjIt; if (CurrentObject) { FAssetData AssetData = FAssetData(CurrentObject); const uint32 ThumbnailResolution = 64; TSharedPtr<FAssetThumbnail> LightMapThumbnail = MakeShareable( new FAssetThumbnail( AssetData, ThumbnailResolution, ThumbnailResolution, ThumbnailPool ) ); TSharedPtr<FLightmapItem> NewItem = MakeShareable( new FLightmapItem(CurrentObject->GetPathName(), LightMapThumbnail) ); LightmapItems.Add(NewItem); } } } if ( LightmapListView.IsValid() ) { LightmapListView->RequestListRefresh(); } }
bool FLightPointLightSetLocation::RunTest(const FString& Parameters) { //** SETUP **// // Create a new level. UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Light Setup APointLight* PointLight = nullptr; const FTransform Transform; if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), Transform)); PointLight->SetActorLocation(POINT_LIGHT_UPDATED_LOCATION); //** VERIFY **// FVector CurrentLocation; LightingTestHelpers::GetActorCurrentLocation(CurrentLevel, PointLight->GetName(), CurrentLocation); TestEqual<FVector>(TEXT("The point light is not in correct location"), POINT_LIGHT_UPDATED_LOCATION, CurrentLocation); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
bool FLightingPromotionModifyProperties::RunTest(const FString& Parameters) { //** SETUP **// UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Test Summary AddLogItem(TEXT("The properties values for a point light are modified.\n- Intensity is set to 1000.\n- Color is set to R=0,G=0,B=255.\n- Attenuation Radius is set to 1024.")); if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. APointLight* PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), FTransform())); // Modify the Lights Intensity, Light Color, and Attenuation Radius using it's properties. LightingTestHelpers::SetPropertyByName(PointLight->PointLightComponent, TEXT("Intensity"), TEXT("1000.f")); LightingTestHelpers::SetPropertyByName(PointLight->PointLightComponent, TEXT("LightColor"), TEXT("(R=0,G=0,B=255)")); LightingTestHelpers::SetPropertyByName(PointLight->PointLightComponent, TEXT("AttenuationRadius"), TEXT("1024.f")); //** VERIFY **// TestEqual<float>(TEXT("Light brightness property was not modified."), 1000.f, PointLight->PointLightComponent->Intensity); TestEqual<FColor>(TEXT("Light color property was not modified."), FColor(0,0,255), PointLight->PointLightComponent->LightColor); TestEqual<float>(TEXT("Light attenuation radius was not modified."), 1024.f, PointLight->PointLightComponent->AttenuationRadius); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
bool FLightingPromotionDuplicationTest::RunTest(const FString& Parameters) { //** SETUP **// UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Test Summary AddLogItem(TEXT("Duplicate and Copy Paste\n- Duplicates a point light.\n- Copies and Pastes a point light.")); if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. APointLight* PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), FTransform())); // Deselect all and then Select the light LightingTestHelpers::SelectActorInLevel(PointLight); // Copy and Paste. GEngine->Exec(World, TEXT("EDIT COPY")); GEngine->Exec(World, TEXT("EDIT PASTE")); // Deselect all and then select a light LightingTestHelpers::SelectActorInLevel(PointLight); // Duplicate the light GEngine->Exec(World, TEXT("DUPLICATE")); //** Verify **// int32 NumberOfPointLights = 0; // Count the number of point lights in the level. for (TObjectIterator<APointLight> It; It; ++It) { NumberOfPointLights++; } // We are expecting three point lights to be in the level now. TestEqual<int32>(TEXT("After duplicating a light the total number of them in the level is not correct."), 3, NumberOfPointLights); return true; } AddError(TEXT("A point light already exists in this level which would dirty the test results.")); return false; }
void FScriptExecutionInstance::RefreshPIEInstance() const { if (!bPIEInstanceDestroyed) { const FWorldContext* PIEWorldContext = GEditor->GetPIEWorldContext(); UWorld* PIEWorld = PIEWorldContext ? PIEWorldContext->World() : nullptr; ULevel* CurrentLevel = PIEWorld ? PIEWorld->GetCurrentLevel() : nullptr; if (CurrentLevel && ObservedObject.IsValid()) { PIEInstance = FindObject<UObject>(CurrentLevel, *ObservedObject.Get()->GetName()); } } }
bool FLightingPromotionPointLightPlaceRotScaleTest::RunTest(const FString& Parameters) { //** SETUP **// // Create the world. UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Test Summary AddLogItem(TEXT("Place, Scale, and Rotate.\n- A Point light is placed into the world.\n- The light is moved.\n- The light is rotated.\n- The light is scaled up.")); if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. APointLight* PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), FTransform())); // Set the actors location, rotation, and scale3D. PointLight->SetActorLocation(POINT_LIGHT_UPDATED_LOCATION); PointLight->SetActorRotation(POINT_LIGHT_UPDATED_ROTATION); PointLight->SetActorScale3D(POINT_LIGHT_UPDATED_SCALE3D); //** VERIFY **// FVector CurrentLocation; LightingTestHelpers::GetActorCurrentLocation(CurrentLevel, PointLight->GetName(), CurrentLocation); FRotator CurrentRotation; LightingTestHelpers::GetActorCurrentRotation(CurrentLevel, PointLight->GetName(), CurrentRotation); FVector CurrentScale3D; LightingTestHelpers::GetActorCurrentScale3D(CurrentLevel, PointLight->GetName(), CurrentScale3D); bool RotationsAreEqual = CurrentRotation.Equals(POINT_LIGHT_UPDATED_ROTATION, 1); TestTrue(TEXT("The placed point light was not found."), LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, PointLight->GetName(), PointLight->GetClass())); TestEqual<FVector>(TEXT("The point light is not in correct location"), POINT_LIGHT_UPDATED_LOCATION, CurrentLocation); TestTrue(TEXT("The point light is not rotated correctly."), RotationsAreEqual); TestEqual<FVector>(TEXT("The point light is not scaled correctly."), POINT_LIGHT_UPDATED_SCALE3D, CurrentScale3D); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
bool FSaveLevelCommand::Update() { if (!GUnrealEd->IsLightingBuildCurrentlyExporting() && !GUnrealEd->IsLightingBuildCurrentlyRunning()) { UWorld* World = GEditor->GetEditorWorldContext().World(); ULevel* Level = World->GetCurrentLevel(); MapName += TEXT("_Copy.umap"); FString TempMapLocation = FPaths::Combine(*FPaths::GameContentDir(), TEXT("Maps"), TEXT("Automation_TEMP"), *MapName); FEditorFileUtils::SaveLevel(Level, TempMapLocation); return true; } return false; }
bool FLightPointLightPlacement::RunTest(const FString& Parameters) { //** SETUP **// // Create a new level. UWorld* World = AutomationEditorCommonUtils::CreateNewMap(); ULevel* CurrentLevel = World->GetCurrentLevel(); // Light Setup APointLight* PointLight = nullptr; const FTransform Transform; if (!LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, TEXT("PointLight"), APointLight::StaticClass())) { //** TEST **// // Add a point light to the level. PointLight = Cast<APointLight>(GEditor->AddActor(World->GetCurrentLevel(), APointLight::StaticClass(), Transform)); //** VERIFY **// TestTrue(TEXT("The placed point light was not found."), LightingTestHelpers::DoesActorExistInTheLevel(CurrentLevel, PointLight->GetName(), PointLight->GetClass())); return true; } AddError(TEXT("A point light already exists in this level which will block the verification of a new point light.")); return false; }
void UUnrealEdEngine::ConvertMatinees() { FVector StartLocation= FVector::ZeroVector; UWorld* World = GWorld; if( World ) { ULevel* Level = World->GetCurrentLevel(); if( !Level ) { Level = World->PersistentLevel; } check(Level); for( TObjectIterator<UInterpData> It; It; ++It ) { UInterpData* InterpData = *It; if( InterpData->IsIn( Level ) ) { // We dont care about renaming references or adding redirectors. References to this will be old seqact_interps GEditor->RenameObject( InterpData, Level->GetOutermost(), *InterpData->GetName() ); AMatineeActor* MatineeActor = Level->OwningWorld->SpawnActor<AMatineeActor>(StartLocation, FRotator::ZeroRotator); StartLocation.Y += 50; MatineeActor->MatineeData = InterpData; UProperty* MatineeDataProp = NULL; for( UProperty* Property = MatineeActor->GetClass()->PropertyLink; Property != NULL; Property = Property->PropertyLinkNext ) { if( Property->GetName() == TEXT("MatineeData") ) { MatineeDataProp = Property; break; } } FPropertyChangedEvent PropertyChangedEvent( MatineeDataProp ); MatineeActor->PostEditChangeProperty( PropertyChangedEvent ); } } } }
/** Updates GCurrentSelectedLightmapSample given a selected actor's components and the location of the click. */ void SetDebugLightmapSample(TArray<UActorComponent*>* Components, UModel* Model, int32 iSurf, FVector ClickLocation) { UStaticMeshComponent* SMComponent = NULL; if (Components) { // Find the first supported component for (int32 ComponentIndex = 0; ComponentIndex < Components->Num() && !SMComponent; ComponentIndex++) { SMComponent = Cast<UStaticMeshComponent>((*Components)[ComponentIndex]); if (SMComponent && (!SMComponent->StaticMesh || SMComponent->LODData.Num() == 0)) { SMComponent = NULL; } } } bool bFoundLightmapSample = false; // Only static mesh components and BSP handled for now if (SMComponent) { UStaticMesh* StaticMesh = SMComponent->StaticMesh; check(StaticMesh); check(StaticMesh->RenderData); check(StaticMesh->RenderData->LODResources.Num()); // Only supporting LOD0 const int32 LODIndex = 0; FStaticMeshLODResources& LODModel = StaticMesh->RenderData->LODResources[LODIndex]; FIndexArrayView Indices = LODModel.IndexBuffer.GetArrayView(); const bool bHasStaticLighting = SMComponent->HasStaticLighting(); if (bHasStaticLighting) { bool bUseTextureMap = false; int32 LightmapSizeX = 0; int32 LightmapSizeY = 0; SMComponent->GetLightMapResolution(LightmapSizeX, LightmapSizeY); if (LightmapSizeX > 0 && LightmapSizeY > 0 && StaticMesh->LightMapCoordinateIndex >= 0 && (uint32)StaticMesh->LightMapCoordinateIndex < LODModel.VertexBuffer.GetNumTexCoords() ) { bUseTextureMap = true; } else { bUseTextureMap = false; } // Search through the static mesh's triangles for the one that was hit (since we can't get triangle index from a line check) for(int32 TriangleIndex = 0; TriangleIndex < Indices.Num(); TriangleIndex += 3) { uint32 Index0 = Indices[TriangleIndex]; uint32 Index1 = Indices[TriangleIndex + 1]; uint32 Index2 = Indices[TriangleIndex + 2]; // Transform positions to world space FVector Position0 = SMComponent->ComponentToWorld.TransformPosition(LODModel.PositionVertexBuffer.VertexPosition(Index0)); FVector Position1 = SMComponent->ComponentToWorld.TransformPosition(LODModel.PositionVertexBuffer.VertexPosition(Index1)); FVector Position2 = SMComponent->ComponentToWorld.TransformPosition(LODModel.PositionVertexBuffer.VertexPosition(Index2)); FVector BaryCentricWeights; // Continue if click location is in the triangle and get its barycentric weights if (GetBarycentricWeights(Position0, Position1, Position2, ClickLocation, .001f, BaryCentricWeights)) { RestoreSelectedLightmapSample(); if (bUseTextureMap) { // Fetch lightmap UV's FVector2D LightmapUV0 = LODModel.VertexBuffer.GetVertexUV(Index0, StaticMesh->LightMapCoordinateIndex); FVector2D LightmapUV1 = LODModel.VertexBuffer.GetVertexUV(Index1, StaticMesh->LightMapCoordinateIndex); FVector2D LightmapUV2 = LODModel.VertexBuffer.GetVertexUV(Index2, StaticMesh->LightMapCoordinateIndex); // Interpolate lightmap UV's to the click location FVector2D InterpolatedUV = LightmapUV0 * BaryCentricWeights.X + LightmapUV1 * BaryCentricWeights.Y + LightmapUV2 * BaryCentricWeights.Z; int32 PaddedSizeX = LightmapSizeX; int32 PaddedSizeY = LightmapSizeY; if (GLightmassDebugOptions.bPadMappings && GAllowLightmapPadding && LightmapSizeX - 2 > 0 && LightmapSizeY - 2 > 0) { PaddedSizeX -= 2; PaddedSizeY -= 2; } const int32 LocalX = FMath::TruncToInt(InterpolatedUV.X * PaddedSizeX); const int32 LocalY = FMath::TruncToInt(InterpolatedUV.Y * PaddedSizeY); if (LocalX < 0 || LocalX >= PaddedSizeX || LocalY < 0 || LocalY >= PaddedSizeY) { UE_LOG(LogStaticLightingSystem, Log, TEXT("Texel selection failed because the lightmap UV's wrap!")); } else { bFoundLightmapSample = UpdateSelectedTexel(SMComponent, -1, SMComponent->LODData[LODIndex].LightMap, ClickLocation, InterpolatedUV, LocalX, LocalY, LightmapSizeX, LightmapSizeY); } } break; } } if (!bFoundLightmapSample && Indices.Num() > 0) { const int32 SelectedTriangle = FMath::RandRange(0, Indices.Num() / 3 - 1); uint32 Index0 = Indices[SelectedTriangle]; uint32 Index1 = Indices[SelectedTriangle + 1]; uint32 Index2 = Indices[SelectedTriangle + 2]; FVector2D LightmapUV0 = LODModel.VertexBuffer.GetVertexUV(Index0, StaticMesh->LightMapCoordinateIndex); FVector2D LightmapUV1 = LODModel.VertexBuffer.GetVertexUV(Index1, StaticMesh->LightMapCoordinateIndex); FVector2D LightmapUV2 = LODModel.VertexBuffer.GetVertexUV(Index2, StaticMesh->LightMapCoordinateIndex); FVector BaryCentricWeights; BaryCentricWeights.X = FMath::FRandRange(0, 1); BaryCentricWeights.Y = FMath::FRandRange(0, 1); if (BaryCentricWeights.X + BaryCentricWeights.Y >= 1) { BaryCentricWeights.X = 1 - BaryCentricWeights.X; BaryCentricWeights.Y = 1 - BaryCentricWeights.Y; } BaryCentricWeights.Z = 1 - BaryCentricWeights.X - BaryCentricWeights.Y; FVector2D InterpolatedUV = LightmapUV0 * BaryCentricWeights.X + LightmapUV1 * BaryCentricWeights.Y + LightmapUV2 * BaryCentricWeights.Z; UE_LOG(LogStaticLightingSystem, Log, TEXT("Failed to intersect any triangles, picking random texel")); int32 PaddedSizeX = LightmapSizeX; int32 PaddedSizeY = LightmapSizeY; if (GLightmassDebugOptions.bPadMappings && GAllowLightmapPadding && LightmapSizeX - 2 > 0 && LightmapSizeY - 2 > 0) { PaddedSizeX -= 2; PaddedSizeY -= 2; } const int32 LocalX = FMath::TruncToInt(InterpolatedUV.X * PaddedSizeX); const int32 LocalY = FMath::TruncToInt(InterpolatedUV.Y * PaddedSizeY); if (LocalX < 0 || LocalX >= PaddedSizeX || LocalY < 0 || LocalY >= PaddedSizeY) { UE_LOG(LogStaticLightingSystem, Log, TEXT("Texel selection failed because the lightmap UV's wrap!")); } else { bFoundLightmapSample = UpdateSelectedTexel(SMComponent, -1, SMComponent->LODData[LODIndex].LightMap, ClickLocation, InterpolatedUV, LocalX, LocalY, LightmapSizeX, LightmapSizeY); } } } } else if (Model) { UWorld* World = Model->LightingLevel->OwningWorld; check( World); for (int32 ModelIndex = 0; ModelIndex < World->GetCurrentLevel()->ModelComponents.Num(); ModelIndex++) { UModelComponent* CurrentComponent = World->GetCurrentLevel()->ModelComponents[ModelIndex]; int32 LightmapSizeX = 0; int32 LightmapSizeY = 0; CurrentComponent->GetLightMapResolution(LightmapSizeX, LightmapSizeY); if (LightmapSizeX > 0 && LightmapSizeY > 0) { for (int32 ElementIndex = 0; ElementIndex < CurrentComponent->GetElements().Num(); ElementIndex++) { FModelElement& Element = CurrentComponent->GetElements()[ElementIndex]; TScopedPointer<FRawIndexBuffer16or32>* IndexBufferRef = Model->MaterialIndexBuffers.Find(Element.Material); check(IndexBufferRef); for(uint32 TriangleIndex = Element.FirstIndex; TriangleIndex < Element.FirstIndex + Element.NumTriangles * 3; TriangleIndex += 3) { uint32 Index0 = (*IndexBufferRef)->Indices[TriangleIndex]; uint32 Index1 = (*IndexBufferRef)->Indices[TriangleIndex + 1]; uint32 Index2 = (*IndexBufferRef)->Indices[TriangleIndex + 2]; FModelVertex* ModelVertices = (FModelVertex*)Model->VertexBuffer.Vertices.GetData(); FVector Position0 = ModelVertices[Index0].Position; FVector Position1 = ModelVertices[Index1].Position; FVector Position2 = ModelVertices[Index2].Position; FVector BaryCentricWeights; // Continue if click location is in the triangle and get its barycentric weights if (GetBarycentricWeights(Position0, Position1, Position2, ClickLocation, .001f, BaryCentricWeights)) { RestoreSelectedLightmapSample(); // Fetch lightmap UV's FVector2D LightmapUV0 = ModelVertices[Index0].ShadowTexCoord; FVector2D LightmapUV1 = ModelVertices[Index1].ShadowTexCoord; FVector2D LightmapUV2 = ModelVertices[Index2].ShadowTexCoord; // Interpolate lightmap UV's to the click location FVector2D InterpolatedUV = LightmapUV0 * BaryCentricWeights.X + LightmapUV1 * BaryCentricWeights.Y + LightmapUV2 * BaryCentricWeights.Z; // Find the node index belonging to the selected triangle const UModel* CurrentModel = CurrentComponent->GetModel(); int32 SelectedNodeIndex = INDEX_NONE; for (int32 ElementNodeIndex = 0; ElementNodeIndex < Element.Nodes.Num(); ElementNodeIndex++) { const FBspNode& CurrentNode = CurrentModel->Nodes[Element.Nodes[ElementNodeIndex]]; if ((int32)Index0 >= CurrentNode.iVertexIndex && (int32)Index0 < CurrentNode.iVertexIndex + CurrentNode.NumVertices) { SelectedNodeIndex = Element.Nodes[ElementNodeIndex]; } } check(SelectedNodeIndex >= 0); TArray<ULightComponentBase*> DummyLights; // fill out the model's NodeGroups (not the mapping part of it, but the nodes part) Model->GroupAllNodes(World->GetCurrentLevel(), DummyLights); // Find the FGatheredSurface that the selected node got put into during the last lighting rebuild TArray<int32> GatheredNodes; // find the NodeGroup that this node went into, and get all of its node for (TMap<int32, FNodeGroup*>::TIterator It(Model->NodeGroups); It && GatheredNodes.Num() == 0; ++It) { FNodeGroup* NodeGroup = It.Value(); for (int32 NodeIndex = 0; NodeIndex < NodeGroup->Nodes.Num(); NodeIndex++) { if (NodeGroup->Nodes[NodeIndex] == SelectedNodeIndex) { GatheredNodes = NodeGroup->Nodes; break; } } } check(GatheredNodes.Num() > 0); // use the surface of the selected node, it will have to suffice for the GetSurfaceLightMapResolution() call int32 SelectedGatheredSurfIndex = Model->Nodes[SelectedNodeIndex].iSurf; // Get the lightmap resolution used by the FGatheredSurface containing the selected node FMatrix WorldToMap; CurrentComponent->GetSurfaceLightMapResolution(SelectedGatheredSurfIndex, 1, LightmapSizeX, LightmapSizeY, WorldToMap, &GatheredNodes); int32 PaddedSizeX = LightmapSizeX; int32 PaddedSizeY = LightmapSizeY; if (GLightmassDebugOptions.bPadMappings && GAllowLightmapPadding && LightmapSizeX - 2 > 0 && LightmapSizeY - 2 > 0) { PaddedSizeX -= 2; PaddedSizeY -= 2; } check(LightmapSizeX > 0 && LightmapSizeY > 0); // Apply the transform to the intersection position to find the local texel coordinates const FVector4 StaticLightingTextureCoordinate = WorldToMap.TransformPosition(ClickLocation); const int32 LocalX = FMath::TruncToInt(StaticLightingTextureCoordinate.X * PaddedSizeX); const int32 LocalY = FMath::TruncToInt(StaticLightingTextureCoordinate.Y * PaddedSizeY); check(LocalX >= 0 && LocalX < PaddedSizeX && LocalY >= 0 && LocalY < PaddedSizeY); bFoundLightmapSample = UpdateSelectedTexel( CurrentComponent, SelectedNodeIndex, Element.LightMap, ClickLocation, InterpolatedUV, LocalX, LocalY, LightmapSizeX, LightmapSizeY); if (!bFoundLightmapSample) { RestoreSelectedLightmapSample(); GCurrentSelectedLightmapSample = FSelectedLightmapSample(); } return; } } } } } } if (!bFoundLightmapSample) { RestoreSelectedLightmapSample(); GCurrentSelectedLightmapSample = FSelectedLightmapSample(); } }