static void DrawAngles(FCanvas* Canvas, int32 XPos, int32 YPos, EAxisList::Type ManipAxis, FWidget::EWidgetMode MoveMode, const FRotator& Rotation, const FVector& Translation) { FString OutputString(TEXT("")); if (MoveMode == FWidget::WM_Rotate && Rotation.IsZero() == false) { //Only one value moves at a time const FVector EulerAngles = Rotation.Euler(); if (ManipAxis == EAxisList::X) { OutputString += FString::Printf(TEXT("Roll: %0.2f"), EulerAngles.X); } else if (ManipAxis == EAxisList::Y) { OutputString += FString::Printf(TEXT("Pitch: %0.2f"), EulerAngles.Y); } else if (ManipAxis == EAxisList::Z) { OutputString += FString::Printf(TEXT("Yaw: %0.2f"), EulerAngles.Z); } } else if (MoveMode == FWidget::WM_Translate && Translation.IsZero() == false) { //Only one value moves at a time if (ManipAxis == EAxisList::X) { OutputString += FString::Printf(TEXT(" %0.2f"), Translation.X); } else if (ManipAxis == EAxisList::Y) { OutputString += FString::Printf(TEXT(" %0.2f"), Translation.Y); } else if (ManipAxis == EAxisList::Z) { OutputString += FString::Printf(TEXT(" %0.2f"), Translation.Z); } } if (OutputString.Len() > 0) { FCanvasTextItem TextItem( FVector2D(XPos, YPos), FText::FromString( OutputString ), GEngine->GetSmallFont(), FLinearColor::White ); Canvas->DrawItem( TextItem ); } }
bool FSplineComponentVisualizer::HandleInputDelta(FEditorViewportClient* ViewportClient, FViewport* Viewport, FVector& DeltaTranslate, FRotator& DeltaRotate, FVector& DeltaScale) { USplineComponent* SplineComp = GetEditedSplineComponent(); if (SplineComp != nullptr) { FInterpCurveVector& SplineInfo = SplineComp->SplineInfo; FInterpCurveQuat& SplineRotInfo = SplineComp->SplineRotInfo; FInterpCurveVector& SplineScaleInfo = SplineComp->SplineScaleInfo; const int32 NumPoints = SplineInfo.Points.Num(); if (SelectedTangentHandle != INDEX_NONE) { // When tangent handles are manipulated... check(SelectedTangentHandle < NumPoints); if (!DeltaTranslate.IsZero()) { check(SelectedTangentHandleType != ESelectedTangentHandle::None); SplineComp->Modify(); FInterpCurvePoint<FVector>& EditedPoint = SplineInfo.Points[SelectedTangentHandle]; const FVector Delta = (SelectedTangentHandleType == ESelectedTangentHandle::Leave) ? DeltaTranslate : -DeltaTranslate; const FVector Tangent = EditedPoint.LeaveTangent + SplineComp->ComponentToWorld.InverseTransformVector(Delta); EditedPoint.LeaveTangent = Tangent; EditedPoint.ArriveTangent = Tangent; EditedPoint.InterpMode = CIM_CurveUser; } } else { // When spline keys are manipulated... check(LastKeyIndexSelected != INDEX_NONE); check(LastKeyIndexSelected < NumPoints); check(SelectedKeys.Num() > 0); SplineComp->Modify(); if (ViewportClient->IsAltPressed() && bAllowDuplication) { OnDuplicateKey(); // Don't duplicate again until we release LMB bAllowDuplication = false; } for (int32 SelectedKeyIndex : SelectedKeys) { FInterpCurvePoint<FVector>& EditedPoint = SplineInfo.Points[SelectedKeyIndex]; FInterpCurvePoint<FQuat>& EditedRotPoint = SplineRotInfo.Points[SelectedKeyIndex]; FInterpCurvePoint<FVector>& EditedScalePoint = SplineScaleInfo.Points[SelectedKeyIndex]; if (!DeltaTranslate.IsZero()) { // Find key position in world space const FVector CurrentWorldPos = SplineComp->ComponentToWorld.TransformPosition(EditedPoint.OutVal); // Move in world space const FVector NewWorldPos = CurrentWorldPos + DeltaTranslate; // Convert back to local space EditedPoint.OutVal = SplineComp->ComponentToWorld.InverseTransformPosition(NewWorldPos); } if (!DeltaRotate.IsZero()) { // Set point tangent as user controlled EditedPoint.InterpMode = CIM_CurveUser; // Rotate tangent according to delta rotation FVector NewTangent = SplineComp->ComponentToWorld.GetRotation().RotateVector(EditedPoint.LeaveTangent); // convert local-space tangent vector to world-space NewTangent = DeltaRotate.RotateVector(NewTangent); // apply world-space delta rotation to world-space tangent NewTangent = SplineComp->ComponentToWorld.GetRotation().Inverse().RotateVector(NewTangent); // convert world-space tangent vector back into local-space EditedPoint.LeaveTangent = NewTangent; EditedPoint.ArriveTangent = NewTangent; // Rotate spline rotation according to delta rotation FQuat NewRot = SplineComp->ComponentToWorld.GetRotation() * EditedRotPoint.OutVal; // convert local-space rotation to world-space NewRot = DeltaRotate.Quaternion() * NewRot; // apply world-space rotation NewRot = SplineComp->ComponentToWorld.GetRotation().Inverse() * NewRot; // convert world-space rotation to local-space EditedRotPoint.OutVal = NewRot; } if (DeltaScale.X != 0.0f) { // Set point tangent as user controlled EditedPoint.InterpMode = CIM_CurveUser; const FVector NewTangent = EditedPoint.LeaveTangent * (1.0f + DeltaScale.X); EditedPoint.LeaveTangent = NewTangent; EditedPoint.ArriveTangent = NewTangent; } if (DeltaScale.Y != 0.0f) { // Scale in Y adjusts the scale spline EditedScalePoint.OutVal.Y *= (1.0f + DeltaScale.Y); } if (DeltaScale.Z != 0.0f) { // Scale in Z adjusts the scale spline EditedScalePoint.OutVal.Z *= (1.0f + DeltaScale.Z); } } } NotifyComponentModified(); return true; } return false; }
bool FInstancedStaticMeshSCSEditorCustomization::HandleViewportDrag(class USceneComponent* InSceneComponent, class USceneComponent* InComponentTemplate, const FVector& InDeltaTranslation, const FRotator& InDeltaRotation, const FVector& InDeltaScale, const FVector& InPivot) { check(InSceneComponent->IsA(UInstancedStaticMeshComponent::StaticClass())); UInstancedStaticMeshComponent* InstancedStaticMeshComponentScene = CastChecked<UInstancedStaticMeshComponent>(InSceneComponent); UInstancedStaticMeshComponent* InstancedStaticMeshComponentTemplate = CastChecked<UInstancedStaticMeshComponent>(InComponentTemplate); // transform pivot into component's space const FVector LocalPivot = InstancedStaticMeshComponentScene->GetComponentToWorld().InverseTransformPosition(InPivot); // Ensure that selected instances are up-to-date ValidateSelectedInstances(InstancedStaticMeshComponentScene); bool bMovedInstance = false; check(InstancedStaticMeshComponentScene->SelectedInstances.Num() == InstancedStaticMeshComponentScene->PerInstanceSMData.Num()); for(int32 InstanceIndex = 0; InstanceIndex < InstancedStaticMeshComponentScene->SelectedInstances.Num(); InstanceIndex++) { if (InstancedStaticMeshComponentScene->SelectedInstances[InstanceIndex] && InstancedStaticMeshComponentTemplate->PerInstanceSMData.IsValidIndex(InstanceIndex)) { FMatrix& MatrixScene = InstancedStaticMeshComponentScene->PerInstanceSMData[InstanceIndex].Transform; FMatrix& MatrixTemplate = InstancedStaticMeshComponentTemplate->PerInstanceSMData[InstanceIndex].Transform; FVector Translation = MatrixScene.GetOrigin(); FRotator Rotation = MatrixScene.Rotator(); FVector Scale = MatrixScene.GetScaleVector(); FVector NewTranslation = Translation; FRotator NewRotation = Rotation; FVector NewScale = Scale; if( !InDeltaRotation.IsZero() ) { NewRotation = FRotator( InDeltaRotation.Quaternion() * Rotation.Quaternion() ); NewTranslation -= LocalPivot; NewTranslation = FRotationMatrix( InDeltaRotation ).TransformPosition( NewTranslation ); NewTranslation += LocalPivot; } NewTranslation += InDeltaTranslation; if( !InDeltaScale.IsNearlyZero() ) { const FScaleMatrix ScaleMatrix( InDeltaScale ); FVector DeltaScale3D = ScaleMatrix.TransformPosition( Scale ); NewScale = Scale + DeltaScale3D; NewTranslation -= LocalPivot; NewTranslation += ScaleMatrix.TransformPosition( NewTranslation ); NewTranslation += LocalPivot; } MatrixScene = FScaleRotationTranslationMatrix(NewScale, NewRotation, NewTranslation); MatrixTemplate = FScaleRotationTranslationMatrix(NewScale, NewRotation, NewTranslation); bMovedInstance = true; } } return bMovedInstance; }
/** * @return true if the delta was handled by this editor mode tool. */ bool FModeTool_Texture::InputDelta(FEditorViewportClient* InViewportClient,FViewport* InViewport,FVector& InDrag,FRotator& InRot,FVector& InScale) { if( InViewportClient->GetCurrentWidgetAxis() == EAxisList::None ) { return false; } // calculate delta drag for this tick for the call to GEditor->polyTexPan below which is using relative (delta) mode FVector deltaDrag = InDrag; if (true == InViewportClient->IsPerspective()) { // perspective viewports pass the absolute drag so subtract the last tick's drag value to get the delta deltaDrag -= PreviousInputDrag; } PreviousInputDrag = InDrag; if( !deltaDrag.IsZero() ) { // Ensure each polygon has a unique base point index. for( FConstLevelIterator Iterator = InViewportClient->GetWorld()->GetLevelIterator(); Iterator; ++Iterator ) { UModel* Model = (*Iterator)->Model; for(int32 SurfaceIndex = 0;SurfaceIndex < Model->Surfs.Num();SurfaceIndex++) { FBspSurf& Surf = Model->Surfs[SurfaceIndex]; if(Surf.PolyFlags & PF_Selected) { const FVector Base = Model->Points[Surf.pBase]; Surf.pBase = Model->Points.Add(Base); } } FMatrix Mat = GLevelEditorModeTools().GetCustomDrawingCoordinateSystem(); FVector UVW = Mat.InverseTransformVector( deltaDrag ); // InverseTransformNormal because Mat is the transform from the surface/widget's coords to world coords GEditor->polyTexPan( Model, UVW.X, UVW.Y, 0 ); // 0 is relative mode because UVW is made from deltaDrag - the user input since the last tick } } if( !InRot.IsZero() ) { const FRotationMatrix RotationMatrix( InRot ); // Ensure each polygon has unique texture vector indices. for ( TSelectedSurfaceIterator<> It(InViewportClient->GetWorld()) ; It ; ++It ) { FBspSurf* Surf = *It; UModel* Model = It.GetModel(); FVector TextureU = Model->Vectors[Surf->vTextureU]; FVector TextureV = Model->Vectors[Surf->vTextureV]; TextureU = RotationMatrix.TransformPosition( TextureU ); TextureV = RotationMatrix.TransformPosition( TextureV ); Surf->vTextureU = Model->Vectors.Add(TextureU); Surf->vTextureV = Model->Vectors.Add(TextureV); const bool bUpdateTexCoords = true; const bool bOnlyRefreshSurfaceMaterials = true; GEditor->polyUpdateMaster(Model, It.GetSurfaceIndex(), bUpdateTexCoords, bOnlyRefreshSurfaceMaterials); } } if( !InScale.IsZero() ) { float ScaleU = InScale.X / GEditor->GetGridSize(); float ScaleV = InScale.Y / GEditor->GetGridSize(); ScaleU = 1.f - (ScaleU / 100.f); ScaleV = 1.f - (ScaleV / 100.f); // Ensure each polygon has unique texture vector indices. for( FConstLevelIterator Iterator = InViewportClient->GetWorld()->GetLevelIterator(); Iterator; ++Iterator ) { UModel* Model = (*Iterator)->Model; for(int32 SurfaceIndex = 0;SurfaceIndex < Model->Surfs.Num();SurfaceIndex++) { FBspSurf& Surf = Model->Surfs[SurfaceIndex]; if(Surf.PolyFlags & PF_Selected) { const FVector TextureU = Model->Vectors[Surf.vTextureU]; const FVector TextureV = Model->Vectors[Surf.vTextureV]; Surf.vTextureU = Model->Vectors.Add(TextureU); Surf.vTextureV = Model->Vectors.Add(TextureV); } } GEditor->polyTexScale( Model, ScaleU, 0.f, 0.f, ScaleV, false ); } } return true; }