FBoxSphereBounds UPaperGroupedSpriteComponent::CalcBounds(const FTransform& BoundTransform) const
{
	bool bHadAnyBounds = false;
	FBoxSphereBounds NewBounds(ForceInit);

	if (PerInstanceSpriteData.Num() > 0)
	{
		const FMatrix BoundTransformMatrix = BoundTransform.ToMatrixWithScale();

		for (const FSpriteInstanceData& InstanceData : PerInstanceSpriteData)
		{
			if (InstanceData.SourceSprite != nullptr)
			{
				const FBoxSphereBounds RenderBounds = InstanceData.SourceSprite->GetRenderBounds();
				const FBoxSphereBounds InstanceBounds = RenderBounds.TransformBy(InstanceData.Transform * BoundTransformMatrix);

				if (bHadAnyBounds)
				{
					NewBounds = NewBounds + InstanceBounds;
				}
				else
				{
					NewBounds = InstanceBounds;
					bHadAnyBounds = true;
				}
			}
		}
	}

	return bHadAnyBounds ? NewBounds : FBoxSphereBounds(BoundTransform.GetLocation(), FVector::ZeroVector, 0.f);
}
Exemplo n.º 2
0
FBoxSphereBounds UPaperTerrainComponent::CalcBounds(const FTransform& LocalToWorld) const
{
	// Determine the rendering bounds
	FBoxSphereBounds LocalRenderBounds;
	{
		FBox BoundingBox(ForceInit);

		for (const FPaperTerrainSpriteGeometry& DrawCall : GeneratedSpriteGeometry)
		{
			for (const FSpriteDrawCallRecord& Record : DrawCall.Records)
			{
				for (const FVector4& VertXYUV : Record.RenderVerts)
				{
					const FVector Vert((PaperAxisX * VertXYUV.X) + (PaperAxisY * VertXYUV.Y));
					BoundingBox += Vert;
				}
			}
		}

		// Make the whole thing a single unit 'deep'
		const FVector HalfThicknessVector = 0.5f * PaperAxisZ;
		BoundingBox.Min -= HalfThicknessVector;
		BoundingBox.Max += HalfThicknessVector;

		LocalRenderBounds = FBoxSphereBounds(BoundingBox);
	}

	// Graphics bounds.
	FBoxSphereBounds NewBounds = LocalRenderBounds.TransformBy(LocalToWorld);

	// Add bounds of collision geometry (if present).
	if (CachedBodySetup != nullptr)
	{
		const FBox AggGeomBox = CachedBodySetup->AggGeom.CalcAABB(LocalToWorld);
		if (AggGeomBox.IsValid)
		{
			NewBounds = Union(NewBounds, FBoxSphereBounds(AggGeomBox));
		}
	}

	// Apply bounds scale
	NewBounds.BoxExtent *= BoundsScale;
	NewBounds.SphereRadius *= BoundsScale;

	return NewBounds;
}
bool UPostProcessComponent::EncompassesPoint(FVector Point, float SphereRadius/*=0.f*/, float* OutDistanceToPoint)
{
	UShapeComponent* ParentShape = Cast<UShapeComponent>(GetAttachParent());
	if (ParentShape != nullptr)
	{
#if WITH_PHYSX
		FVector ClosestPoint;
		float Distance = ParentShape->GetDistanceToCollision(Point, ClosestPoint);
#else
		FBoxSphereBounds Bounds = ParentShape->CalcBounds(ParentShape->ComponentToWorld);
		float Distance = 0;
		if (ParentShape->IsA<USphereComponent>())
		{
			const FSphere& Sphere = Bounds.GetSphere();
			const FVector& Dist = Sphere.Center - Point;
			Distance = FMath::Max(0.0f, Dist.Size() - Sphere.W);
		}
		else // UBox or UCapsule shape (approx).
		{
			Distance = FMath::Sqrt(Bounds.GetBox().ComputeSquaredDistanceToPoint(Point));
		}
#endif

		if (OutDistanceToPoint)
		{
			*OutDistanceToPoint = Distance;
		}

		return Distance >= 0.f && Distance <= SphereRadius;
	}
	if (OutDistanceToPoint != nullptr)
	{
		*OutDistanceToPoint = 0;
	}
	return true;
}
bool UDebugSkelMeshComponent::CheckIfBoundsAreCorrrect()
{
	if (GetPhysicsAsset())
	{
		bool bWasUsingInGameBounds = IsUsingInGameBounds();
		FTransform TempTransform = FTransform::Identity;
		UseInGameBounds(true);
		FBoxSphereBounds InGameBounds = CalcBounds(TempTransform);
		UseInGameBounds(false);
		FBoxSphereBounds PreviewBounds = CalcBounds(TempTransform);
		UseInGameBounds(bWasUsingInGameBounds);
		// calculate again to have bounds as requested
		CalcBounds(TempTransform);
		// if in-game bounds are of almost same size as preview bounds or bigger, it seems to be fine
		if (! InGameBounds.GetSphere().IsInside(PreviewBounds.GetSphere(), PreviewBounds.GetSphere().W * 0.1f) && // for spheres: A.IsInside(B) checks if A is inside of B
			! PreviewBounds.GetBox().IsInside(InGameBounds.GetBox().ExpandBy(PreviewBounds.GetSphere().W * 0.1f))) // for boxes: A.IsInside(B) checks if B is inside of A
		{
			return true;
		}
	}
	return false;
}
FVector UTextRenderComponent::GetTextWorldSize() const
{
	FBoxSphereBounds Bounds = CalcBounds(ComponentToWorld);
	return Bounds.GetBox().GetSize();
}
FVector UTextRenderComponent::GetTextLocalSize() const
{
	FBoxSphereBounds Bounds = CalcBounds(FTransform::Identity);
	return Bounds.GetBox().GetSize();
}
void UPaperSpriteThumbnailRenderer::DrawFrame(class UPaperSprite* Sprite, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget*, FCanvas* Canvas, FBoxSphereBounds* OverrideRenderBounds)
{
	const UTexture2D* SourceTexture = nullptr;
	if (Sprite != nullptr)
	{
		SourceTexture = Sprite->GetBakedTexture() ? Sprite->GetBakedTexture() : Sprite->GetSourceTexture();
	}

	if (SourceTexture != nullptr)
	{
		const bool bUseTranslucentBlend = SourceTexture->HasAlphaChannel();

		// Draw the grid behind the sprite
		if (bUseTranslucentBlend)
		{
			DrawGrid(X, Y, Width, Height, Canvas);
		}

		// Draw the sprite itself
		// Use the baked render data, so we don't have to care about rotations and possibly
		// other sprites overlapping in source, UV region, etc.
		const TArray<FVector4>& BakedRenderData = Sprite->BakedRenderData;
		TArray<FVector2D> CanvasPositions;
		TArray<FVector2D> CanvasUVs;

		for (int Vertex = 0; Vertex < BakedRenderData.Num(); ++Vertex)
		{
			new (CanvasPositions) FVector2D(BakedRenderData[Vertex].X, BakedRenderData[Vertex].Y);
			new (CanvasUVs) FVector2D(BakedRenderData[Vertex].Z, BakedRenderData[Vertex].W);
		}

		// Determine the bounds to use
		FBoxSphereBounds* RenderBounds = OverrideRenderBounds;
		FBoxSphereBounds FrameBounds;
		if (RenderBounds == nullptr)
		{
			FrameBounds = Sprite->GetRenderBounds();
			RenderBounds = &FrameBounds;
		}

		const FVector MinPoint3D = RenderBounds->GetBoxExtrema(0);
		const FVector MaxPoint3D = RenderBounds->GetBoxExtrema(1);
		const FVector2D MinPoint(FVector::DotProduct(MinPoint3D, PaperAxisX), FVector::DotProduct(MinPoint3D, PaperAxisY));
		const FVector2D MaxPoint(FVector::DotProduct(MaxPoint3D, PaperAxisX), FVector::DotProduct(MaxPoint3D, PaperAxisY));

		const float UnscaledWidth = MaxPoint.X - MinPoint.X;
		const float UnscaledHeight = MaxPoint.Y - MinPoint.Y;
		const FVector2D Origin(X + Width * 0.5f, Y + Height * 0.5f);
		const bool bIsWider = (UnscaledWidth > 0.0f) && (UnscaledHeight > 0.0f) && (UnscaledWidth > UnscaledHeight);
		const float ScaleFactor = bIsWider ? (Width / UnscaledWidth) : (Height / UnscaledHeight);

		// Scale and recenter
		const FVector2D CanvasPositionCenter = (MaxPoint + MinPoint) * 0.5f;
		for (int Vertex = 0; Vertex < CanvasPositions.Num(); ++Vertex)
		{
			CanvasPositions[Vertex] = (CanvasPositions[Vertex] - CanvasPositionCenter) * ScaleFactor + Origin;
			CanvasPositions[Vertex].Y = Height - CanvasPositions[Vertex].Y;
		}

		// Draw triangles
		if ((CanvasPositions.Num() > 0) && (SourceTexture->Resource != nullptr))
		{
			TArray<FCanvasUVTri> Triangles;
			const FLinearColor SpriteColor(FLinearColor::White);
			for (int Vertex = 0; Vertex < CanvasPositions.Num(); Vertex += 3)
			{
				FCanvasUVTri* Triangle = new (Triangles) FCanvasUVTri();
				Triangle->V0_Pos = CanvasPositions[Vertex + 0]; Triangle->V0_UV = CanvasUVs[Vertex + 0]; Triangle->V0_Color = SpriteColor;
				Triangle->V1_Pos = CanvasPositions[Vertex + 1]; Triangle->V1_UV = CanvasUVs[Vertex + 1]; Triangle->V1_Color = SpriteColor;
				Triangle->V2_Pos = CanvasPositions[Vertex + 2]; Triangle->V2_UV = CanvasUVs[Vertex + 2]; Triangle->V2_Color = SpriteColor;
			}
			FCanvasTriangleItem CanvasTriangle(Triangles, SourceTexture->Resource);
			CanvasTriangle.BlendMode = bUseTranslucentBlend ? ESimpleElementBlendMode::SE_BLEND_Translucent : ESimpleElementBlendMode::SE_BLEND_Opaque;
			Canvas->DrawItem(CanvasTriangle);
		}
	}
	else
	{
		// Fallback for a bogus sprite
		DrawGrid(X, Y, Width, Height, Canvas);
	}
}
Exemplo n.º 8
0
bool FVertexSnappingImpl::SnapDraggedActorsToNearestVertex( FVector& DragDelta, FLevelEditorViewportClient* ViewportClient )
{
	int32 MouseX = ViewportClient->Viewport->GetMouseX();
	int32 MouseY = ViewportClient->Viewport->GetMouseY();
	FVector2D MousePosition = FVector2D( MouseX, MouseY ) ;
	
	EAxisList::Type CurrentAxis = ViewportClient->GetCurrentWidgetAxis();

	bool bSnapped = false;
	if( !DragDelta.IsNearlyZero() )
	{
		// Are there selected actors?
		USelection* Selection = GEditor->GetSelectedActors();

		FVector Direction = DragDelta.GetSafeNormal();

		FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
			ViewportClient->Viewport, 
			ViewportClient->GetScene(),
			ViewportClient->EngineShowFlags )
			.SetRealtimeUpdate( ViewportClient->IsRealtime() ));

		FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily );

		FVector StartLocation = ViewportClient->GetModeTools()->PivotLocation;

		FVector DesiredUnsnappedLocation = StartLocation+DragDelta;
					
		// Plane facing in the direction of axis movement.  This is for clipping actors which are behind the desired location (they should not be considered for snap)
		FPlane ActorPlane( DesiredUnsnappedLocation, Direction );

		TSet< TWeakObjectPtr<AActor> > ActorsToIgnore;
	
		// Snap each selected actor
		for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
		{
			// Build up a region that actors must be in for snapping
			FBoxSphereBounds SnappingAreaBox( FBox( DesiredUnsnappedLocation-VertexSnappingConstants::MaxSnappingDistance, DesiredUnsnappedLocation+VertexSnappingConstants::MaxSnappingDistance )  );

			AActor* Actor = CastChecked<AActor>( *It );

			if( Actor->GetRootComponent() != NULL )
			{
				// Get a bounding box around the actor
				const bool bNonColliding = true;
				FBoxSphereBounds ActorBounds = Actor->GetComponentsBoundingBox(bNonColliding);

				// The allowed snapping box is a box around the selected actor plus a region around the actor that other actors must be in for snapping
				FBox AllowedSnappingBox = ActorBounds.GetBox();

				// Extend the box to include the drag point
				AllowedSnappingBox += SnappingAreaBox.GetBox();

				GetActorsToIgnore( Actor, ActorsToIgnore );

				FVertexSnappingArgs Args
				( 
					ActorPlane, 
					DesiredUnsnappedLocation,
					ViewportClient,
					View,
					MousePosition,
					CurrentAxis,
					true
				);

				// Snap the drag delta
				SnapDragDelta( Args, StartLocation, AllowedSnappingBox, ActorsToIgnore, DragDelta );
			}
		}
	}

	return bSnapped;
}