void FStaticMeshEditorViewportClient::Draw(const FSceneView* View,FPrimitiveDrawInterface* PDI) { FEditorViewportClient::Draw(View, PDI); if (bShowCollision && StaticMesh->BodySetup) { const FColor SelectedColor(149, 223, 157); const FColor UnselectedColor(157, 149, 223); // Draw bodies FKAggregateGeom* AggGeom = &StaticMesh->BodySetup->AggGeom; for (int32 i = 0; i < AggGeom->SphereElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Sphere, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKSphereElem& SphereElem = AggGeom->SphereElems[i]; const FTransform ElemTM = SphereElem.GetTransform(); SphereElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->BoxElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Box, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKBoxElem& BoxElem = AggGeom->BoxElems[i]; const FTransform ElemTM = BoxElem.GetTransform(); BoxElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->SphylElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Sphyl, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKSphylElem& SphylElem = AggGeom->SphylElems[i]; const FTransform ElemTM = SphylElem.GetTransform(); SphylElem.DrawElemWire(PDI, ElemTM, 1.f, CollisionColor); PDI->SetHitProxy(NULL); } for (int32 i = 0; i < AggGeom->ConvexElems.Num(); ++i) { HSMECollisionProxy* HitProxy = new HSMECollisionProxy(KPT_Convex, i); PDI->SetHitProxy(HitProxy); const FColor CollisionColor = StaticMeshEditorPtr.Pin()->IsSelectedPrim(HitProxy->PrimData) ? SelectedColor : UnselectedColor; const FKConvexElem& ConvexElem = AggGeom->ConvexElems[i]; const FTransform ElemTM = ConvexElem.GetTransform(); ConvexElem.DrawElemWire(PDI, ElemTM, CollisionColor); PDI->SetHitProxy(NULL); } } if( bShowSockets ) { const FColor SocketColor = FColor(255, 128, 128); for(int32 i=0; i < StaticMesh->Sockets.Num(); i++) { UStaticMeshSocket* Socket = StaticMesh->Sockets[i]; if(Socket) { FMatrix SocketTM; Socket->GetSocketMatrix(SocketTM, StaticMeshComponent); PDI->SetHitProxy( new HSMESocketProxy(i) ); DrawWireDiamond(PDI, SocketTM, 5.f, SocketColor, SDPG_Foreground); PDI->SetHitProxy( NULL ); } } } // Draw any edges that are currently selected by the user if( SelectedEdgeIndices.Num() > 0 ) { for(int32 VertexIndex = 0; VertexIndex < SelectedEdgeVertices.Num(); VertexIndex += 2) { FVector EdgeVertices[ 2 ]; EdgeVertices[ 0 ] = SelectedEdgeVertices[VertexIndex]; EdgeVertices[ 1 ] = SelectedEdgeVertices[VertexIndex + 1]; PDI->DrawLine( StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 0 ] ), StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 1 ] ), FColor( 255, 255, 0 ), SDPG_World ); } } if( bDrawNormals || bDrawTangents || bDrawBinormals ) { FStaticMeshLODResources& LODModel = StaticMesh->RenderData->LODResources[StaticMeshEditorPtr.Pin()->GetCurrentLODIndex()]; FIndexArrayView Indices = LODModel.IndexBuffer.GetArrayView(); uint32 NumIndices = Indices.Num(); FMatrix LocalToWorldInverseTranspose = StaticMeshComponent->ComponentToWorld.ToMatrixWithScale().InverseFast().GetTransposed(); for (uint32 i = 0; i < NumIndices; i++) { const FVector& VertexPos = LODModel.PositionVertexBuffer.VertexPosition( Indices[i] ); const FVector WorldPos = StaticMeshComponent->ComponentToWorld.TransformPosition( VertexPos ); const FVector& Normal = LODModel.VertexBuffer.VertexTangentZ( Indices[i] ); const FVector& Binormal = LODModel.VertexBuffer.VertexTangentY( Indices[i] ); const FVector& Tangent = LODModel.VertexBuffer.VertexTangentX( Indices[i] ); const float Len = 5.0f; if( bDrawNormals ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Normal ).SafeNormal() * Len, FLinearColor( 0.0f, 1.0f, 0.0f), SDPG_World ); } if( bDrawTangents ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Tangent ).SafeNormal() * Len, FLinearColor( 1.0f, 0.0f, 0.0f), SDPG_World ); } if( bDrawBinormals ) { PDI->DrawLine( WorldPos, WorldPos+LocalToWorldInverseTranspose.TransformVector( Binormal ).SafeNormal() * Len, FLinearColor( 0.0f, 0.0f, 1.0f), SDPG_World ); } } } if( bShowPivot ) { FUnrealEdUtils::DrawWidget(View, PDI, StaticMeshComponent->ComponentToWorld.ToMatrixWithScale(), 0, 0, EAxisList::All, EWidgetMovementMode::WMM_Translate, false); } if( bDrawAdditionalData ) { const TArray<UAssetUserData*>* UserDataArray = StaticMesh->GetAssetUserDataArray(); if (UserDataArray != NULL) { for (int32 AdditionalDataIndex = 0; AdditionalDataIndex < UserDataArray->Num(); ++AdditionalDataIndex) { if ((*UserDataArray)[AdditionalDataIndex] != NULL) { (*UserDataArray)[AdditionalDataIndex]->Draw(PDI, View); } } } } }
bool FStaticMeshEditorViewportClient::InputWidgetDelta( FViewport* Viewport, EAxisList::Type CurrentAxis, FVector& Drag, FRotator& Rot, FVector& Scale ) { bool bHandled = false; if (bManipulating) { if (CurrentAxis != EAxisList::None) { UStaticMeshSocket* SelectedSocket = StaticMeshEditorPtr.Pin()->GetSelectedSocket(); if(SelectedSocket) { UProperty* ChangedProperty = NULL; const FWidget::EWidgetMode MoveMode = GetWidgetMode(); if(MoveMode == FWidget::WM_Rotate) { ChangedProperty = FindField<UProperty>( UStaticMeshSocket::StaticClass(), "RelativeRotation" ); SelectedSocket->PreEditChange(ChangedProperty); FRotator CurrentRot = SelectedSocket->RelativeRotation; FRotator SocketWinding, SocketRotRemainder; CurrentRot.GetWindingAndRemainder(SocketWinding, SocketRotRemainder); const FQuat ActorQ = SocketRotRemainder.Quaternion(); const FQuat DeltaQ = Rot.Quaternion(); const FQuat ResultQ = DeltaQ * ActorQ; const FRotator NewSocketRotRem = FRotator( ResultQ ); FRotator DeltaRot = NewSocketRotRem - SocketRotRemainder; DeltaRot.Normalize(); SelectedSocket->RelativeRotation += DeltaRot; SelectedSocket->RelativeRotation = SelectedSocket->RelativeRotation.Clamp(); } else if(MoveMode == FWidget::WM_Translate) { ChangedProperty = FindField<UProperty>( UStaticMeshSocket::StaticClass(), "RelativeLocation" ); SelectedSocket->PreEditChange(ChangedProperty); //FRotationMatrix SocketRotTM( SelectedSocket->RelativeRotation ); //FVector SocketMove = SocketRotTM.TransformVector( Drag ); SelectedSocket->RelativeLocation += Drag; } if ( ChangedProperty ) { FPropertyChangedEvent PropertyChangedEvent( ChangedProperty ); SelectedSocket->PostEditChangeProperty(PropertyChangedEvent); } StaticMeshEditorPtr.Pin()->GetStaticMesh()->MarkPackageDirty(); } else { const bool bSelectedPrim = StaticMeshEditorPtr.Pin()->HasSelectedPrims(); if (bSelectedPrim && CurrentAxis != EAxisList::None) { const FWidget::EWidgetMode MoveMode = GetWidgetMode(); if (MoveMode == FWidget::WM_Rotate) { StaticMeshEditorPtr.Pin()->RotateSelectedPrims(Rot); } else if (MoveMode == FWidget::WM_Scale) { StaticMeshEditorPtr.Pin()->ScaleSelectedPrims(Scale); } else if (MoveMode == FWidget::WM_Translate) { StaticMeshEditorPtr.Pin()->TranslateSelectedPrims(Drag); } StaticMeshEditorPtr.Pin()->GetStaticMesh()->MarkPackageDirty(); } } } Invalidate(); bHandled = true; } return bHandled; }