Пример #1
0
void USplineComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	if (PropertyChangedEvent.Property != nullptr)
	{
		const FName PropertyName(PropertyChangedEvent.Property->GetFName());
		if (PropertyName == GET_MEMBER_NAME_CHECKED(USplineComponent, ReparamStepsPerSegment) ||
			PropertyName == GET_MEMBER_NAME_CHECKED(USplineComponent, bStationaryEndpoints))
		{
			UpdateSpline();
		}

		if (PropertyName == GET_MEMBER_NAME_CHECKED(USplineComponent, bClosedLoop))
		{
			if (bClosedLoop)
			{
				// Spline is guaranteed to be non-looping when we get here (due to PreEditChange).
				// Now just force the loop endpoint to be added if bClosedLoop == true.
				AddLoopEndpoint();
			}

			UpdateSpline();
		}
	}

	Super::PostEditChangeProperty(PropertyChangedEvent);
}
void USplineComponent::ClearSplinePoints()
{
	SplineInfo.Points.Reset();
	SplineRotInfo.Points.Reset();
	SplineScaleInfo.Points.Reset();
	UpdateSpline();
}
void USplineComponent::Serialize(FArchive& Ar)
{
	Super::Serialize(Ar);

	// Support old resources which don't have the rotation and scale splines present
	const int32 ArchiveUE4Version = Ar.UE4Ver();
	if (ArchiveUE4Version < VER_UE4_INTERPCURVE_SUPPORTS_LOOPING)
	{
		int32 NumPoints = SplineInfo.Points.Num();

		// The start point is no longer cloned as the endpoint when the spline is looped, so remove the extra endpoint if present
		const bool bHasExtraEndpoint = bClosedLoop && (SplineInfo.Points[0].OutVal == SplineInfo.Points[NumPoints - 1].OutVal);

		if (bHasExtraEndpoint)
		{
			SplineInfo.Points.RemoveAt(NumPoints - 1, 1, false);
			NumPoints--;
		}

		// Fill the other two splines with some defaults
		SplineRotInfo.Points.Reset(NumPoints);
		SplineScaleInfo.Points.Reset(NumPoints);
		for (int32 Count = 0; Count < NumPoints; Count++)
		{
			SplineRotInfo.Points.Emplace(0.0f, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto);
			SplineScaleInfo.Points.Emplace(0.0f, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);
		}

		USplineComponent* Archetype = CastChecked<USplineComponent>(GetArchetype());
		bSplineHasBeenEdited = (SplineInfo.Points != Archetype->SplineInfo.Points);
		UpdateSpline();
	}
}
Пример #4
0
void USplineComponent::SetSplinePointType(int32 PointIndex, ESplinePointType::Type Type)
{
	EInterpCurveMode InterpMode = CIM_Constant;
	switch (Type)
	{
		case ESplinePointType::Curve:			InterpMode = CIM_CurveAuto; break;
		case ESplinePointType::CurveClamped:	InterpMode = CIM_CurveAutoClamped; break;
		case ESplinePointType::Linear:			InterpMode = CIM_Linear; break;
	}

	const int32 NumPoints = SplineInfo.Points.Num();

	if ((PointIndex >= 0) && (PointIndex < NumPoints))
	{
		SplineInfo.Points[PointIndex].InterpMode = InterpMode;

		if (IsClosedLoop())
		{
			// In a closed loop, the first and last points are tied, so update one with the other
			if (PointIndex == 0)
			{
				SplineInfo.Points[NumPoints - 1].InterpMode = InterpMode;
			}
			else if (PointIndex == NumPoints - 1)
			{
				SplineInfo.Points[0].InterpMode = InterpMode;
			}
		}

		UpdateSpline();
	}
}
Пример #5
0
void USplineComponent::ApplyComponentInstanceData(FSplineInstanceData* SplineInstanceData)
{
	if (SplineInstanceData)
	{
		if (bAllowSplineEditingPerInstance)
		{
			SplineInfo = SplineInstanceData->SplineInfo;

			// If the construction script changed bClosedLoop, amend the applied points accordingly
			if (SplineInstanceData->bClosedLoop != bClosedLoop)
			{
				if (bClosedLoop)
				{
					AddLoopEndpoint();
				}
				else
				{
					RemoveLoopEndpoint();
				}
			}

			UpdateSpline();
		}
	}
}
USplineComponent::USplineComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
	, bAllowSplineEditingPerInstance_DEPRECATED(true)
	, ReparamStepsPerSegment(10)
	, Duration(1.0f)
	, bStationaryEndpoints(false)
	, bSplineHasBeenEdited(false)
	, bClosedLoop(false)
	, DefaultUpVector(FVector::UpVector)
#if WITH_EDITORONLY_DATA
	, EditorUnselectedSplineSegmentColor(FLinearColor(1.0f, 1.0f, 1.0f))
	, EditorSelectedSplineSegmentColor(FLinearColor(1.0f, 0.0f, 0.0f))
	, bShouldVisualizeScale(false)
	, ScaleVisualizationWidth(30.0f)
#endif
{
	SplineInfo.Points.Reset(10);
	SplineRotInfo.Points.Reset(10);
	SplineScaleInfo.Points.Reset(10);

	SplineInfo.Points.Emplace(0.0f, FVector(0, 0, 0), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);
	SplineRotInfo.Points.Emplace(0.0f, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto);
	SplineScaleInfo.Points.Emplace(0.0f, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);

	SplineInfo.Points.Emplace(1.0f, FVector(100, 0, 0), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);
	SplineRotInfo.Points.Emplace(1.0f, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto);
	SplineScaleInfo.Points.Emplace(1.0f, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);

	UpdateSpline();
}
void USplineComponent::SetSplinePointType(int32 PointIndex, ESplinePointType::Type Type)
{
	if ((PointIndex >= 0) && (PointIndex < SplineInfo.Points.Num()))
	{
		SplineInfo.Points[PointIndex].InterpMode = ConvertSplinePointTypeToInterpCurveMode(Type);
		UpdateSpline();
	}
}
void USplineComponent::AddSplinePoint(const FVector& Position, ESplineCoordinateSpace::Type CoordinateSpace)
{
	const FVector TransformedPosition = (CoordinateSpace == ESplineCoordinateSpace::World) ?
		ComponentToWorld.InverseTransformPosition(Position) : Position;

	const float InKey = static_cast<float>(SplineInfo.Points.Num());

	SplineInfo.Points.Emplace(InKey, TransformedPosition, FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);
	SplineRotInfo.Points.Emplace(InKey, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto);
	SplineScaleInfo.Points.Emplace(InKey, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);

	UpdateSpline();
}
void USplineComponent::SetDefaultUpVector(const FVector& UpVector, ESplineCoordinateSpace::Type CoordinateSpace)
{
	if (CoordinateSpace == ESplineCoordinateSpace::World)
	{
		DefaultUpVector = ComponentToWorld.InverseTransformVector(UpVector);
	}
	else
	{
		DefaultUpVector = UpVector;
	}

	UpdateSpline();
}
void USplineComponent::SetLocationAtSplinePoint(int32 PointIndex, const FVector& InLocation, ESplineCoordinateSpace::Type CoordinateSpace)
{
	const int32 NumPoints = SplineInfo.Points.Num();

	if ((PointIndex >= 0) && (PointIndex < NumPoints))
	{
		const FVector TransformedLocation = (CoordinateSpace == ESplineCoordinateSpace::World) ?
			ComponentToWorld.InverseTransformPosition(InLocation) : InLocation;

		SplineInfo.Points[PointIndex].OutVal = TransformedLocation;

		UpdateSpline();
	}
}
void USplineComponent::ApplyComponentInstanceData(FSplineInstanceData* SplineInstanceData, const bool bPostUCS)
{
	check(SplineInstanceData);

	if (SplineInstanceData->bSplineHasBeenEdited)
	{
		SplineInfo = SplineInstanceData->SplineInfo;
		SplineRotInfo = SplineInstanceData->SplineRotInfo;
		SplineScaleInfo = SplineInstanceData->SplineScaleInfo;
	}

	bSplineHasBeenEdited = SplineInstanceData->bSplineHasBeenEdited;

	UpdateSpline();
}
Пример #12
0
void USplineComponent::AddSplineLocalPoint(const FVector& Position)
{
	// If it's a closed loop, remove the endpoint before adding a new point
	const bool bWasLoop = IsClosedLoop();
	SetClosedLoop(false);

	float InputKey = static_cast<float>(SplineInfo.Points.Num());
	const int32 PointIndex = SplineInfo.AddPoint(InputKey, Position);
	SplineInfo.Points[PointIndex].InterpMode = CIM_CurveAuto;

	// Then re-close the spline if required
	SetClosedLoop(bWasLoop);

	UpdateSpline();
}
void USplineComponent::SetTangentAtSplinePoint(int32 PointIndex, const FVector& InTangent, ESplineCoordinateSpace::Type CoordinateSpace)
{
	const int32 NumPoints = SplineInfo.Points.Num();

	if ((PointIndex >= 0) && (PointIndex < NumPoints))
	{
		const FVector TransformedTangent = (CoordinateSpace == ESplineCoordinateSpace::World) ?
			ComponentToWorld.InverseTransformVector(InTangent) : InTangent;

		SplineInfo.Points[PointIndex].LeaveTangent = TransformedTangent;
		SplineInfo.Points[PointIndex].ArriveTangent = TransformedTangent;
		SplineInfo.Points[PointIndex].InterpMode = CIM_CurveUser;

		UpdateSpline();
	}
}
Пример #14
0
void USplineComponent::SetSplineLocalPoints(const TArray<FVector>& Points)
{
	const bool bWasLoop = IsClosedLoop();
	SetClosedLoop(false);

	SplineInfo.Points.Reset(bWasLoop ? Points.Num() + 1 : Points.Num());
	float InputKey = 0.0f;
	for (const auto& Point : Points)
	{
		int32 PointIndex = SplineInfo.AddPoint(InputKey, Point);
		SplineInfo.Points[PointIndex].InterpMode = CIM_CurveAuto;
		InputKey += 1.0f;
	}

	SetClosedLoop(bWasLoop);

	UpdateSpline();
}
void USplineComponent::AddSplinePointAtIndex(const FVector& Position, int32 Index, ESplineCoordinateSpace::Type CoordinateSpace)
{
	const FVector TransformedPosition = (CoordinateSpace == ESplineCoordinateSpace::World) ?
		ComponentToWorld.InverseTransformPosition(Position) : Position;

	const float InKey = static_cast<float>(Index);

	if (((Index >= 0) && 
		(Index < SplineInfo.Points.Num())) &&
		(Index < SplineRotInfo.Points.Num()) &&
		(Index < SplineScaleInfo.Points.Num()))
	{
		SplineInfo.Points.Insert(FInterpCurvePoint<FVector>(InKey, TransformedPosition, FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto), Index);
		SplineRotInfo.Points.Insert(FInterpCurvePoint<FQuat>(InKey, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto), Index);
		SplineScaleInfo.Points.Insert(FInterpCurvePoint<FVector>(InKey, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto), Index);
	}

	UpdateSpline();
}
Пример #16
0
void USplineComponent::SetSplineWorldPoints(const TArray<FVector>& Points)
{
	// If it's a closed loop, mark it as not closed before setting a new array of points
	const bool bWasLoop = IsClosedLoop();
	SetClosedLoop(false);

	SplineInfo.Points.Reset(bWasLoop ? Points.Num() + 1 : Points.Num());
	float InputKey = 0.0f;
	for (const auto& Point : Points)
	{
		int32 PointIndex = SplineInfo.AddPoint(InputKey, ComponentToWorld.InverseTransformPosition(Point));
		SplineInfo.Points[PointIndex].InterpMode = CIM_CurveAuto;
		InputKey += 1.0f;
	}

	SetClosedLoop(bWasLoop);

	UpdateSpline();
}
void USplineComponent::RemoveSplinePoint(const int32 Index)
{
	int32 Count = 1;

	if ((Index >= 0) &&
		(SplineInfo.Points.Num() >= 0) &&
		(SplineRotInfo.Points.Num() >= 0) &&
		(SplineScaleInfo.Points.Num() >= 0) &&
		(Index + Count <= SplineInfo.Points.Num()) &&
		(Index + Count <= SplineRotInfo.Points.Num()) &&
		(Index + Count <= SplineScaleInfo.Points.Num())
		)
	{
		SplineInfo.Points.RemoveAt(Index, Count, false);
		SplineRotInfo.Points.RemoveAt(Index, Count, false);
		SplineScaleInfo.Points.RemoveAt(Index, Count, false);
	}

	UpdateSpline();
}
void USplineComponent::SetSplinePoints(const TArray<FVector>& Points, ESplineCoordinateSpace::Type CoordinateSpace)
{
	const int32 NumPoints = Points.Num();
	SplineInfo.Points.Reset(NumPoints);
	SplineRotInfo.Points.Reset(NumPoints);
	SplineScaleInfo.Points.Reset(NumPoints);

	float InputKey = 0.0f;
	for (const auto& Point : Points)
	{
		const FVector TransformedPoint = (CoordinateSpace == ESplineCoordinateSpace::World) ?
			ComponentToWorld.InverseTransformPosition(Point) : Point;

		SplineInfo.Points.Emplace(InputKey, TransformedPoint, FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);
		SplineRotInfo.Points.Emplace(InputKey, FQuat::Identity, FQuat::Identity, FQuat::Identity, CIM_CurveAuto);
		SplineScaleInfo.Points.Emplace(InputKey, FVector(1.0f), FVector::ZeroVector, FVector::ZeroVector, CIM_CurveAuto);

		InputKey += 1.0f;
	}

	UpdateSpline();
}
void USplineComponent::PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent)
{
	if (PropertyChangedEvent.Property != nullptr)
	{
		static const FName ReparamStepsPerSegmentName = GET_MEMBER_NAME_CHECKED(USplineComponent, ReparamStepsPerSegment);
		static const FName StationaryEndpointsName = GET_MEMBER_NAME_CHECKED(USplineComponent, bStationaryEndpoints);
		static const FName DefaultUpVectorName = GET_MEMBER_NAME_CHECKED(USplineComponent, DefaultUpVector);
		static const FName ClosedLoopName = GET_MEMBER_NAME_CHECKED(USplineComponent, bClosedLoop);
		static const FName SplineInfoName = GET_MEMBER_NAME_CHECKED(USplineComponent, SplineInfo);
		static const FName SplineHasBeenEditedName = GET_MEMBER_NAME_CHECKED(USplineComponent, bSplineHasBeenEdited);

		const FName PropertyName(PropertyChangedEvent.Property->GetFName());
		if (PropertyName == ReparamStepsPerSegmentName ||
			PropertyName == StationaryEndpointsName ||
			PropertyName == DefaultUpVectorName ||
			PropertyName == ClosedLoopName)
		{
			UpdateSpline();
		}
	}

	Super::PostEditChangeChainProperty(PropertyChangedEvent);
}
Пример #20
0
USplineComponent::USplineComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
	, bAllowSplineEditingPerInstance(true)
	, ReparamStepsPerSegment(10)
	, Duration(1.0f)
	, bStationaryEndpoints(false)
	, bClosedLoop(false)
#if WITH_EDITORONLY_DATA
	, EditorUnselectedSplineSegmentColor(FLinearColor(1.0f, 1.0f, 1.0f))
	, EditorSelectedSplineSegmentColor(FLinearColor(1.0f, 0.0f, 0.0f))
#endif
{
	SplineInfo.Points.Reset(10);

	// Add 2 keys by default
	int32 PointIndex = SplineInfo.AddPoint(0.f, FVector(0,0,0));
	SplineInfo.Points[PointIndex].InterpMode = CIM_CurveAuto;

	PointIndex = SplineInfo.AddPoint(1.f, FVector(100,0,0));
	SplineInfo.Points[PointIndex].InterpMode = CIM_CurveAuto;

	UpdateSpline();
}
Пример #21
0
void USplineComponent::SetWorldLocationAtSplinePoint(int32 PointIndex, const FVector& InLocation)
{
	const int32 NumPoints = SplineInfo.Points.Num();

	if ((PointIndex >= 0) && (PointIndex < NumPoints))
	{
		SplineInfo.Points[PointIndex].OutVal = ComponentToWorld.InverseTransformPosition(InLocation);

		if (IsClosedLoop())
		{
			// In a closed loop, the first and last points are tied, so update one with the other
			if (PointIndex == 0)
			{
				SplineInfo.Points[NumPoints - 1].OutVal = InLocation;
			}
			else if (PointIndex == NumPoints - 1)
			{
				SplineInfo.Points[0].OutVal = InLocation;
			}
		}

		UpdateSpline();
	}
}
Пример #22
0
void USplineComponent::SetClosedLoop(bool bInClosedLoop)
{
	UpdateLoopEndpoint(bInClosedLoop);
	UpdateSpline();
}
Пример #23
0
void USplineComponent::PostEditImport()
{
	Super::PostEditImport();
	UpdateSpline();
}
Пример #24
0
void USplineComponent::PostLoad()
{
	Super::PostLoad();
	UpdateSpline();
}
void USplineComponent::SetClosedLoop(bool bInClosedLoop)
{
	bClosedLoop = bInClosedLoop;
	UpdateSpline();
}