Files
UnrealEngineUWP/Engine/Source/Editor/UnrealEd/Private/TexAlignTools.cpp

541 lines
16 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
TexAlignTools.cpp: Tools for aligning textures on surfaces
=============================================================================*/
#include "TexAlignTools.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "Engine/Level.h"
#include "Model.h"
#include "TexAligner/TexAlignerBox.h"
#include "TexAligner/TexAlignerDefault.h"
#include "TexAligner/TexAlignerFit.h"
#include "TexAligner/TexAlignerPlanar.h"
#include "Engine/Polys.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3209340 on 2016/11/23 by Ben.Marsh Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h. Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms. * Every header now includes everything it needs to compile. * There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first. * There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h. * Every .cpp file includes its matching .h file first. * This helps validate that each header is including everything it needs to compile. * No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more. * You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there. * There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible. * No engine code explicitly includes a precompiled header any more. * We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies. * PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files. Tool used to generate this transform is at Engine\Source\Programs\IncludeTool. [CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
#include "Editor.h"
#include "BSPOps.h"
FTexAlignTools GTexAlignTools;
static int32 GetMajorAxis( FVector3f InNormal, int32 InForceAxis )
{
// Figure out the major axis information.
int32 Axis = TAXIS_X;
if( FMath::Abs(InNormal.Y) >= 0.5f ) Axis = TAXIS_Y;
else
{
// Only check Z if we aren't aligned to walls
if( InForceAxis != TAXIS_WALLS )
if( FMath::Abs(InNormal.Z) >= 0.5f ) Axis = TAXIS_Z;
}
return Axis;
}
// Checks the normal of the major axis ... if it's negative, returns 1.
static bool ShouldFlipVectors( FVector3f InNormal, int32 InAxis )
{
if( InAxis == TAXIS_X )
if( InNormal.X < 0 ) return 1;
if( InAxis == TAXIS_Y )
if( InNormal.Y < 0 ) return 1;
if( InAxis == TAXIS_Z )
if( InNormal.Z < 0 ) return 1;
return 0;
}
UTexAligner::UTexAligner(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UTexAligner::PostInitProperties()
{
Super::PostInitProperties();
Desc = TEXT("N/A");
TAxis = TAXIS_AUTO;
UTile = VTile = 1.f;
DefTexAlign = TEXALIGN_Default;
}
void UTexAligner::Align( UWorld* InWorld, ETexAlign InTexAlignType )
{
for( int32 LevelIndex = 0; LevelIndex < InWorld->GetNumLevels(); ++LevelIndex )
{
ULevel* Level = InWorld->GetLevel(LevelIndex);
Align( InWorld, InTexAlignType, Level->Model );
}
}
void UTexAligner::Align( UWorld* InWorld, ETexAlign InTexAlignType, UModel* InModel )
{
//
// Build an initial list of BSP surfaces to be aligned.
//
FPoly EdPoly;
TArray<FBspSurfIdx> InitialSurfList;
for( int32 i = 0 ; i < InModel->Surfs.Num() ; i++ )
{
FBspSurf* Surf = &InModel->Surfs[i];
if( Surf->PolyFlags & PF_Selected )
{
new(InitialSurfList)FBspSurfIdx( Surf, i );
}
}
//
// Create a final list of BSP surfaces ...
//
// - allows for rejection of surfaces
// - allows for specific ordering of faces
//
TArray<FBspSurfIdx> FinalSurfList;
FVector Normal;
for( int32 i = 0 ; i < InitialSurfList.Num() ; i++ )
{
FBspSurfIdx* Surf = &InitialSurfList[i];
// Normal = InModel->Vectors[ Surf->Surf->vNormal ];
// GEditor->polyFindMaster( InModel, Surf->Idx, EdPoly );
bool bOK = 1;
/*
switch( InTexAlignType )
{
}
*/
if( bOK )
new(FinalSurfList)FBspSurfIdx( Surf->Surf, Surf->Idx );
}
//
// Align the final surfaces.
//
for( int32 i = 0 ; i < FinalSurfList.Num() ; i++ )
{
FBspSurfIdx* Surf = &FinalSurfList[i];
GEditor->polyFindMaster( InModel, Surf->Idx, EdPoly );
Normal = (FVector)InModel->Vectors[ Surf->Surf->vNormal ];
AlignSurf( InTexAlignType == TEXALIGN_None ? (ETexAlign)DefTexAlign : InTexAlignType, InModel, Surf, &EdPoly, &Normal );
const bool bUpdateTexCoords = true;
const bool bOnlyRefreshSurfaceMaterials = true;
GEditor->polyUpdateMaster(InModel, Surf->Idx, bUpdateTexCoords, bOnlyRefreshSurfaceMaterials);
}
GEditor->RedrawLevelEditingViewports();
InWorld->MarkPackageDirty();
ULevel::LevelDirtiedEvent.Broadcast();
}
void UTexAligner::AlignSurf( ETexAlign InTexAlignType, UModel* InModel, FBspSurfIdx* InSurfIdx, FPoly* InPoly, FVector* InNormal )
{
}
UTexAlignerPlanar::UTexAlignerPlanar(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UTexAlignerPlanar::PostInitProperties()
{
Super::PostInitProperties();
Desc = NSLOCTEXT("UnrealEd", "Planar", "Planar").ToString();
DefTexAlign = TEXALIGN_Planar;
}
void UTexAlignerPlanar::AlignSurf( ETexAlign InTexAlignType, UModel* InModel, FBspSurfIdx* InSurfIdx, FPoly* InPoly, FVector* InNormal )
{
if( InTexAlignType == TEXALIGN_PlanarAuto )
TAxis = TAXIS_AUTO;
else if( InTexAlignType == TEXALIGN_PlanarWall )
TAxis = TAXIS_WALLS;
else if( InTexAlignType == TEXALIGN_PlanarFloor )
TAxis = TAXIS_Z;
int32 Axis = GetMajorAxis( (FVector3f)*InNormal, TAxis );
if( TAxis != TAXIS_AUTO && TAxis != TAXIS_WALLS )
Axis = TAxis;
bool bFlip = ShouldFlipVectors( (FVector3f)*InNormal, Axis );
// Determine the texturing vectors.
FVector U, V;
if( Axis == TAXIS_X )
{
U = FVector(0, (bFlip ? 1 : -1) ,0);
V = FVector(0,0,-1);
}
else if( Axis == TAXIS_Y )
{
U = FVector((bFlip ? -1 : 1),0,0);
V = FVector(0,0,-1);
}
else
{
U = FVector((bFlip ? 1 : -1),0,0);
V = FVector(0,-1,0);
}
FVector Base = FVector::ZeroVector;
U *= UTile;
V *= VTile;
InSurfIdx->Surf->pBase = FBSPOps::bspAddPoint(InModel,&Base,0);
InSurfIdx->Surf->vTextureU = FBSPOps::bspAddVector( InModel, &U, 0);
InSurfIdx->Surf->vTextureV = FBSPOps::bspAddVector( InModel, &V, 0);
}
UTexAlignerDefault::UTexAlignerDefault(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UTexAlignerDefault::PostInitProperties()
{
Super::PostInitProperties();
Desc = NSLOCTEXT("UnrealEd", "Default", "Default").ToString();
DefTexAlign = TEXALIGN_Default;
}
void UTexAlignerDefault::AlignSurf( ETexAlign InTexAlignType, UModel* InModel, FBspSurfIdx* InSurfIdx, FPoly* InPoly, FVector* InNormal )
{
InPoly->Base = InPoly->Vertices[0];
InPoly->TextureU = FVector3f::ZeroVector;
InPoly->TextureV = FVector3f::ZeroVector;
InPoly->Finalize( NULL, 0 );
InPoly->TextureU *= UTile;
InPoly->TextureV *= VTile;
ABrush* Actor = InSurfIdx->Surf->Actor;
const FVector PrePivot = Actor->GetPivotOffset();
const FVector Location = Actor->GetActorLocation();
const FRotator Rotation = Actor->GetActorRotation();
const FVector Scale = Actor->GetActorScale();
const FRotationMatrix RotMatrix(Rotation);
FVector Base = RotMatrix.TransformVector(((FVector)InPoly->Base - PrePivot) * Scale) + Location;
FVector TextureU = RotMatrix.TransformVector((FVector)InPoly->TextureU / Scale);
FVector TextureV = RotMatrix.TransformVector((FVector)InPoly->TextureV / Scale);
InSurfIdx->Surf->pBase = FBSPOps::bspAddPoint(InModel, &Base, 0);
InSurfIdx->Surf->vTextureU = FBSPOps::bspAddVector( InModel, &TextureU, 0);
InSurfIdx->Surf->vTextureV = FBSPOps::bspAddVector( InModel, &TextureV, 0);
}
UTexAlignerBox::UTexAlignerBox(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UTexAlignerBox::PostInitProperties()
{
Super::PostInitProperties();
Desc = NSLOCTEXT("UnrealEd", "Box", "Box").ToString();
DefTexAlign = TEXALIGN_Box;
}
void UTexAlignerBox::AlignSurf( ETexAlign InTexAlignType, UModel* InModel, FBspSurfIdx* InSurfIdx, FPoly* InPoly, FVector* InNormal )
{
FVector U, V;
FVector Normal = *InNormal;
Normal.FindBestAxisVectors( V, U );
U *= -1.0;
V *= -1.0;
U *= UTile;
V *= VTile;
FVector Base = FVector::ZeroVector;
InSurfIdx->Surf->pBase = FBSPOps::bspAddPoint(InModel,&Base,0);
InSurfIdx->Surf->vTextureU = FBSPOps::bspAddVector( InModel, &U, 0 );
InSurfIdx->Surf->vTextureV = FBSPOps::bspAddVector( InModel, &V, 0 );
}
UTexAlignerFit::UTexAlignerFit(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void UTexAlignerFit::PostInitProperties()
{
Super::PostInitProperties();
Desc = NSLOCTEXT("UnrealEd", "Fit", "Fit").ToString();
DefTexAlign = TEXALIGN_Fit;
}
void UTexAlignerFit::AlignSurf( ETexAlign InTexAlignType, UModel* InModel, FBspSurfIdx* InSurfIdx, FPoly* InPoly, FVector* InNormal )
{
// @todo: Support cycling between texture corners by FIT'ing again? Each Ctrl+Shift+F would rotate texture.
// @todo: Consider making initial FIT match the texture's current orientation as close as possible?
// @todo: Handle subtractive brush polys differently? (flip U texture direction)
// @todo: Option to ignore pixel aspect for quads (e.g. stretch full texture non-uniformly over quad)
// Compute world space vertex positions
TArray< FVector > WorldSpacePolyVertices;
for( int32 VertexIndex = 0; VertexIndex < InPoly->Vertices.Num(); ++VertexIndex )
{
WorldSpacePolyVertices.Add( InSurfIdx->Surf->Actor->ActorToWorld().TransformPosition( (FVector)InPoly->Vertices[ VertexIndex ] ) );
}
// Create an orthonormal basis for the polygon
FMatrix WorldToPolyRotationMatrix;
const FVector& FirstPolyVertex = WorldSpacePolyVertices[ 0 ];
{
const FVector& VertexA = FirstPolyVertex;
const FVector& VertexB = WorldSpacePolyVertices[ 1 ];
FVector UpVec = ( VertexB - VertexA ).GetSafeNormal();
FVector RightVec = (FVector)InPoly->Normal ^ UpVec;
WorldToPolyRotationMatrix.SetIdentity();
FVector Normal = (FVector)InPoly->Normal;
WorldToPolyRotationMatrix.SetAxes( &RightVec, &UpVec, &Normal );
}
// Find a corner of the polygon that's closest to a 90 degree angle. When there are multiple corners with
// similar angles, we'll use the one closest to the local space bottom-left along the polygon's plane
const float DesiredAbsDotProduct = 0.0f;
int32 BestVertexIndex = INDEX_NONE;
float BestDotProductDiff = 10000.0f;
float BestPositivity = 10000.0f;
for( int32 VertexIndex = 0; VertexIndex < WorldSpacePolyVertices.Num(); ++VertexIndex )
{
// Compute the previous and next vertex in the winding
const int32 PrevWindingVertexIndex = ( VertexIndex > 0 ) ? ( VertexIndex - 1 ) : ( WorldSpacePolyVertices.Num() - 1 );
const int32 NextWindingVertexIndex = ( VertexIndex < WorldSpacePolyVertices.Num() - 1 ) ? ( VertexIndex + 1 ) : 0;
const FVector& PrevVertex = WorldSpacePolyVertices[ PrevWindingVertexIndex ];
const FVector& CurVertex = WorldSpacePolyVertices[ VertexIndex ];
const FVector& NextVertex = WorldSpacePolyVertices[ NextWindingVertexIndex ];
// Compute the corner angle
float AbsDotProduct = FMath::Abs( ( PrevVertex - CurVertex ).GetSafeNormal() | ( NextVertex - CurVertex ).GetSafeNormal() );
// Compute how 'positive' this vertex is relative to the bottom left position in the polygon's plane
FVector PolySpaceVertex = WorldToPolyRotationMatrix.InverseTransformVector( CurVertex - FirstPolyVertex );
const float Positivity = PolySpaceVertex.X + PolySpaceVertex.Y;
// Is the corner angle closer to 90 degrees than our current best?
const float DotProductDiff = FMath::Abs( AbsDotProduct - DesiredAbsDotProduct );
if( FMath::IsNearlyEqual( DotProductDiff, BestDotProductDiff, 0.1f ) )
{
// This angle is just as good as the current best, so check to see which is closer to the local space
// bottom-left along the polygon's plane
if( Positivity < BestPositivity )
{
// This vertex is in a more suitable location for the bottom-left of the texture
BestVertexIndex = VertexIndex;
if( DotProductDiff < BestDotProductDiff )
{
// Only store the new dot product if it's actually better than the existing one
BestDotProductDiff = DotProductDiff;
}
BestPositivity = Positivity;
}
}
else if( DotProductDiff <= BestDotProductDiff )
{
// This angle is definitely better!
BestVertexIndex = VertexIndex;
BestDotProductDiff = DotProductDiff;
BestPositivity = Positivity;
}
}
// Compute orthonormal basis for the 'best corner' of the polygon. The texture will be positioned at the corner
// of the bounds of the poly in this coordinate system
const FVector& BestVertex = WorldSpacePolyVertices[ BestVertexIndex ];
const int32 NextWindingVertexIndex = ( BestVertexIndex < WorldSpacePolyVertices.Num() - 1 ) ? ( BestVertexIndex + 1 ) : 0;
const FVector& NextVertex = WorldSpacePolyVertices[ NextWindingVertexIndex ];
FVector TextureUpVec = ( NextVertex - BestVertex ).GetSafeNormal();
FVector TextureRightVec = (FVector)InPoly->Normal ^ TextureUpVec;
FMatrix WorldToTextureRotationMatrix;
WorldToTextureRotationMatrix.SetIdentity();
FVector PolyNormal = (FVector)InPoly->Normal;
WorldToTextureRotationMatrix.SetAxes( &TextureRightVec, &TextureUpVec, &PolyNormal );
// Compute bounds of polygon along plane
float MinX = FLT_MAX;
float MaxX = -FLT_MAX;
float MinY = FLT_MAX;
float MaxY = -FLT_MAX;
for( int32 VertexIndex = 0; VertexIndex < WorldSpacePolyVertices.Num(); ++VertexIndex )
{
const FVector& CurVertex = WorldSpacePolyVertices[ VertexIndex ];
// Transform vertex into the coordinate system of our texture
FVector TextureSpaceVertex = WorldToTextureRotationMatrix.InverseTransformVector( CurVertex - BestVertex );
if( TextureSpaceVertex.X < MinX )
{
MinX = TextureSpaceVertex.X;
}
if( TextureSpaceVertex.X > MaxX )
{
MaxX = TextureSpaceVertex.X;
}
if( TextureSpaceVertex.Y < MinY )
{
MinY = TextureSpaceVertex.Y;
}
if( TextureSpaceVertex.Y > MaxY )
{
MaxY = TextureSpaceVertex.Y;
}
}
// We'll use the texture space corner of the bounds as the origin of the texture. This ensures that
// the texture fits over the entire polygon without revealing any tiling
const FVector TextureSpaceBasePos( MinX, MinY, 0.0f );
FVector WorldSpaceBasePos = WorldToTextureRotationMatrix.TransformVector( TextureSpaceBasePos ) + BestVertex;
// Apply scale to UV vectors. We incorporate the parameterized tiling rations and scale by our texture size
const float WorldTexelScale = UModel::GetGlobalBSPTexelScale();
const float TextureSizeU = FMath::Abs( MaxX - MinX );
const float TextureSizeV = FMath::Abs( MaxY - MinY );
FVector TextureUVector = UTile * TextureRightVec * WorldTexelScale / TextureSizeU;
FVector TextureVVector = VTile * TextureUpVec * WorldTexelScale / TextureSizeV;
// Flip the texture vertically if we want that
const bool bFlipVertically = true;
if( bFlipVertically )
{
WorldSpaceBasePos += TextureUpVec * TextureSizeV;
TextureVVector *= -1.0f;
}
// Apply texture base position
{
const bool bExactMatch = false;
InSurfIdx->Surf->pBase = FBSPOps::bspAddPoint( InModel, const_cast< FVector* >( &WorldSpaceBasePos ), bExactMatch );
}
// Apply texture UV vectors
{
const bool bExactMatch = false;
InSurfIdx->Surf->vTextureU = FBSPOps::bspAddVector( InModel, const_cast< FVector* >( &TextureUVector ), bExactMatch );
InSurfIdx->Surf->vTextureV = FBSPOps::bspAddVector( InModel, const_cast< FVector* >( &TextureVVector ), bExactMatch );
}
}
/*------------------------------------------------------------------------------
FTexAlignTools.
A helper class to store the state of the various texture alignment tools.
------------------------------------------------------------------------------*/
void FTexAlignTools::Init()
{
//Never call Init more then once except if Release was call
check(!bIsInit);
// Create the list of aligners.
Aligners.Empty();
Copying //UE4/Dev-Core to //UE4/Main ========================== MAJOR FEATURES + CHANGES ========================== Change 2717513 on 2015/10/06 by Robert.Manuszewski@Robert_Manuszewski_EGUK_M1 GC and WeakObjectPtr performance optimizations. - Moved some of the EObjectFlags to EInternalObjectFlags and merged them with FUObjectArray - Moved WeakObjectPtr serial numbersto FUObjectArray - Added pre-allocated UObject array Change 2716517 on 2015/10/05 by Robert.Manuszewski@Robert_Manuszewski_EGUK_M1 Make SavePackage thread safe UObject-wise so that StaticFindObject etc can't run in parallel when packages are being saved. Change 2721142 on 2015/10/08 by Mikolaj.Sieluzycki@Dev-Core_D0920 UHT will now use makefiles to speed up iterative runs. Change 2726320 on 2015/10/13 by Jaroslaw.Palczynski@jaroslaw.palczynski_D1732_2963 Hot-reload performance optimizations: 1. Got rid of redundant touched BPs optimization (which was necessary before major HR fixes submitted earlier). 2. Parallelized search for old CDOs referencers. Change 2759032 on 2015/11/09 by Graeme.Thornton@GThornton_DesktopMaster Dependency preloading improvements - Asset registry dependencies now resolve asset redirectors - Rearrange runtime loading to put dependency preloads within BeginLoad/EndLoad for the source package Change 2754342 on 2015/11/04 by Robert.Manuszewski@Robert_Manuszewski_Stream1 Allow UnfocusedVolumeMultiplier to be set programmatically Change 2764008 on 2015/11/12 by Robert.Manuszewski@Robert_Manuszewski_Stream1 When cooking, don't add imports that are outers of objects excluded from the current cook target. Change 2755562 on 2015/11/05 by Steve.Robb@Dev-Core Inline storage for TFunction. Fix for delegate inline storage on Win64. Some build fixes. Visualizer fixes for new TFunction format. Change 2735084 on 2015/10/20 by Jaroslaw.Surowiec@Stream.1.JarekSurowiec CrashReporter Web - Search by Platform Added initial support for streams (GetBranchesAsListItems, CopyToJira) Change 2762387 on 2015/11/11 by Steve.Robb@Dev-Core Unnecessary allocation removed when loading empty files in FFileHelper::LoadFileToString. Change 2762632 on 2015/11/11 by Steve.Robb@Dev-Core Some TSet function optimisations: Avoiding unnecessary hashing of function arguments if the container is empty (rather than the hash being empty, which is not necessarily equivalent). Taking local copies of HashSize during iterations. Change 2762936 on 2015/11/11 by Steve.Robb@Dev-Core BulkData zero byte allocations are now handled by an RAII object which owns the memory. Change 2765758 on 2015/11/13 by Steve.Robb@Dev-Core FName::operator== and != optimised to be a single comparison. Change 2757195 on 2015/11/06 by Jaroslaw.Surowiec@Stream.1.JarekSurowiec PR #1305: Improvements in CrashReporter for Symbol Server usage (Contributed by bozaro) Change 2760778 on 2015/11/10 by Jaroslaw.Surowiec@Stream.1.JarekSurowiec PR #1725: Fixed typos in ProfilerCommon.h; Added comments (Contributed by BGR360) Also fixed starting condition. Change 2739804 on 2015/10/23 by Robert.Manuszewski@Robert_Manuszewski_Stream1 PR #1470: [UObjectGlobals] Do not overwrite instanced subobjects with ones from CDO (Contributed by slonopotamus) Change 2744733 on 2015/10/28 by Steve.Robb@Dev-Core PR #1540 - Specifying a different Saved folder at launch through a command line parameter Integrated and optimized. #lockdown Nick.Penwarden [CL 2772222 by Robert Manuszewski in Main branch]
2015-11-18 16:20:49 -05:00
Aligners.Add(NewObject<UTexAlignerDefault>(GetTransientPackage(), NAME_None, RF_Public | RF_Standalone));
Aligners.Add(NewObject<UTexAlignerPlanar>(GetTransientPackage(), NAME_None, RF_Public | RF_Standalone));
Aligners.Add(NewObject<UTexAlignerBox>(GetTransientPackage(), NAME_None, RF_Public | RF_Standalone));
Aligners.Add(NewObject<UTexAlignerFit>(GetTransientPackage(), NAME_None, RF_Public | RF_Standalone));
for (UObject* Aligner : Aligners)
{
Aligner->AddToRoot();
}
FEditorDelegates::FitTextureToSurface.AddRaw(this, &FTexAlignTools::OnEditorFitTextureToSurface);
bIsInit = true;
}
void FTexAlignTools::Release()
{
if (bIsInit)
{
for (UObject* Aligner : Aligners)
{
Aligner->RemoveFromRoot();
}
Aligners.Empty();
FEditorDelegates::FitTextureToSurface.RemoveAll(this);
}
bIsInit = false;
}
FTexAlignTools::FTexAlignTools()
{
bIsInit = false;
}
FTexAlignTools::~FTexAlignTools()
{
Release();
}
// Returns the most appropriate texture aligner based on the type passed in.
UTexAligner* FTexAlignTools::GetAligner( ETexAlign InTexAlign )
{
switch( InTexAlign )
{
case TEXALIGN_Planar:
case TEXALIGN_PlanarAuto:
case TEXALIGN_PlanarWall:
case TEXALIGN_PlanarFloor:
return Aligners[1];
break;
case TEXALIGN_Default:
return Aligners[0];
break;
case TEXALIGN_Box:
return Aligners[2];
break;
case TEXALIGN_Fit:
return Aligners[3];
break;
}
check(0); // Unknown type!
return NULL;
}
void FTexAlignTools::OnEditorFitTextureToSurface(UWorld* InWorld)
{
UTexAligner* FitAligner = GTexAlignTools.Aligners[ 3 ];
for ( int32 LevelIndex = 0; LevelIndex < InWorld->GetNumLevels() ; ++LevelIndex )
{
ULevel* Level = InWorld->GetLevel(LevelIndex);
FitAligner->Align( InWorld, TEXALIGN_None, Level->Model );
}
}