diff --git a/Source/MoCapPlugin/Private/MCController.cpp b/Source/MoCapPlugin/Private/MCController.cpp
index 140e32289f9f21d101b28e883a3999400279e544..b26ecd3be0b85149efd3bafb9ca940815fdf3bbd 100644
--- a/Source/MoCapPlugin/Private/MCController.cpp
+++ b/Source/MoCapPlugin/Private/MCController.cpp
@@ -42,7 +42,7 @@ void AMCController::BeginPlay() {
 		InputComponent->BindAction("SetMarker", EInputEvent::IE_Pressed, this, &AMCController::SetMarker);
 		InputComponent->BindAction("StartRecording", EInputEvent::IE_Pressed, this, &AMCController::ToggleRecording);
 		InputComponent->BindAction("NextSentence", EInputEvent::IE_Pressed, this, &AMCController::SetMarker);
-		InputComponent->BindAction("SaveAnimation", EInputEvent::IE_Pressed, this, &AMCController::SaveAnimation);
+		InputComponent->BindAction("SaveAnimation", EInputEvent::IE_Pressed, this, &AMCController::SaveAnimationEditor);
 	}
 
 	if (!Pawn || !Pawn->GetActorLocation().Equals(FVector(0, 0, 0)) || !Pawn->GetActorRotation().Equals(FRotator(0, 0, 0))) {
@@ -209,9 +209,7 @@ void AMCController::ScaleAnimDataInterval(int start, int end, float DeltaTime) {
 		FProcessedAnimData Data;
 		Data.Timestamp = StartTime + FTimespan::FromSeconds((float)i * NewTime / (float)NewNrFrames);
 		//SmoothStop
-		//float TransformedI = 1.f - FMath::Pow(1.f - ((float)i / (float)NewNrFrames), 4);
-		//SmoothStart
-		float TransformedI = FMath::Pow(((float)i / (float)NewNrFrames), 4);
+		float TransformedI = 1.f - FMath::Pow(1.f - ((float)i / (float)NewNrFrames), GestureHoldExcessEasingExponent);
 		FTimespan OldTimestamp = StartTime + FTimespan::FromSeconds(TransformedI * OldTime);
 
 		bool stop = false;
@@ -287,7 +285,7 @@ void AMCController::ScaleAnimDataInterval(int start, int end, float DeltaTime) {
 
 }
 
-bool AMCController::PreprocessRecording() {
+bool AMCController::PreprocessRecording(const TArray<float>& HaltingPoints) {
 
 	UMCAnimInstance* AI = AnimSaveState.Pawn->GetAnimInstance();
 
@@ -528,101 +526,161 @@ bool AMCController::PreprocessRecording() {
 	//---find last slow part of the gesture and scale it up---
 	
 	TArray<float> GestureSpeed;
+	bool newMethod = true;
 	
-	if (GestureHoldExcessTime > 0.f) {
+	if (!newMethod) {
+		if (GestureHoldExcessTime > 0.f) {
 
-		for (int i = 1; i < AnimSaveState.AnimData.Num(); i++) {
+			for (int i = 1; i < AnimSaveState.AnimData.Num(); i++) {
 
-			FProcessedAnimData& AnimData = AnimSaveState.AnimData[i];
+				FProcessedAnimData& AnimData = AnimSaveState.AnimData[i];
 
-			if (AnimData.IsMarker || AnimData.IsEnd) {
-				continue;
-			}
+				if (AnimData.IsMarker || AnimData.IsEnd) {
+					continue;
+				}
+
+				//process sensor data
 
-			//process sensor data
+				float Speed = 0.f;
+				int SpeedCount = 0;
+				int window = 1;
 
-			float Speed = 0.f;
-			int SpeedCount = 0;
-			int window = 1;
+				FSensorData& SensorData = AnimData.SensorData;
+				for (int j = 0; j < EBodyPart::LAST; j++) {
 
-			FSensorData& SensorData = AnimData.SensorData;
-			for (int j = 0; j < EBodyPart::LAST; j++) {
+					EBodyPart Type = EBodyPart(j);
+					FSensorDataEntry* Entry = SensorData.GetEntry(Type);
 
-				EBodyPart Type = EBodyPart(j);
-				FSensorDataEntry* Entry = SensorData.GetEntry(Type);
+					if (Type == EBodyPart::HandL || Type == EBodyPart::HandR) {
 
-				if (Type == EBodyPart::HandL || Type == EBodyPart::HandR) {
+						for (int w = 0; w < window; w++) {
+							int index = i + w;
+							if (index - 1 >= 0 && index < AnimSaveState.AnimData.Num()) {
+								FProcessedAnimData& Data0 = AnimSaveState.AnimData[index - 1];
+								FProcessedAnimData& Data1 = AnimSaveState.AnimData[index];
+								float Time = (Data1.Timestamp - Data0.Timestamp).GetTotalSeconds();
+								Speed += Time * (Data1.SensorData.GetEntry(Type)->Pos - Data0.SensorData.GetEntry(Type)->Pos).Size();
 
-					for (int w = 0; w < window; w++) {
-						int index = i + w;
-						if (index - 1 >= 0 && index < AnimSaveState.AnimData.Num()) {
-							FProcessedAnimData& Data0 = AnimSaveState.AnimData[index - 1];
-							FProcessedAnimData& Data1 = AnimSaveState.AnimData[index];
-							float Time = (Data1.Timestamp - Data0.Timestamp).GetTotalSeconds();
-							Speed += Time * (Data1.SensorData.GetEntry(Type)->Pos - Data0.SensorData.GetEntry(Type)->Pos).Size();
-							
+							}
 						}
-					}
 
-					SpeedCount++;
+						SpeedCount++;
+
+					}
 
 				}
 
+				GestureSpeed.Push(Speed / (float)SpeedCount);
+
 			}
 
-			GestureSpeed.Push(Speed / (float)SpeedCount);
+			//smooth
+			TArray<float> SmoothedGestureSpeed;
+			int window = 5;
+			int Num = GestureSpeed.Num();
+			for (int i = 0; i < Num; i++) {
+				float avg = 0.f;
+				for (int wInd = -window; wInd <= window; wInd++) {
+					int w = i + wInd;
+					if (w < 0) {
+						avg += (GestureSpeed[0] + GestureSpeed[1] + GestureSpeed[2] + GestureSpeed[3] + GestureSpeed[4]) / 5.f;
+					}
+					else if (w >= Num) {
+						avg += (GestureSpeed[Num - 1] + GestureSpeed[Num - 2] + GestureSpeed[Num - 3] + GestureSpeed[Num - 4] + GestureSpeed[Num - 5]) / 5.f;
+					}
+					else {
+						avg += GestureSpeed[w];
+					}
+				}
+				avg /= (float)(window * 2 + 1);
+				SmoothedGestureSpeed.Push(avg);
+			}
 
-		}
+			GestureSpeed = SmoothedGestureSpeed;
 
-		//smooth
-		TArray<float> SmoothedGestureSpeed;
-		int window = 5;
-		int Num = GestureSpeed.Num();
-		for (int i = 0; i < Num; i++) {
-			float avg = 0.f;
-			for (int wInd = -window; wInd <= window; wInd++) {
-				int w = i + wInd;
-				if (w < 0) {
-					avg += (GestureSpeed[0] + GestureSpeed[1] + GestureSpeed[2] + GestureSpeed[3] + GestureSpeed[4]) / 5.f;
-				}
-				else if (w >= Num) {
-					avg += (GestureSpeed[Num - 1] + GestureSpeed[Num - 2] + GestureSpeed[Num - 3] + GestureSpeed[Num - 4] + GestureSpeed[Num - 5]) / 5.f;
+			int MaxNumToScale = 30;
+
+			//maximum
+			int maxWindow = 8;
+			int ScaleStart;
+			for (ScaleStart = GestureSpeed.Num() - 1; ScaleStart >= 0 && ScaleStart >= GestureSpeed.Num() - MaxNumToScale; ScaleStart--) {
+				bool isMax = true;
+				for (int w = -maxWindow; w <= maxWindow; w++) {
+					int index = ScaleStart + w;
+					if (index >= 0 && index < GestureSpeed.Num() && index != ScaleStart) {
+						if (GestureSpeed[index] >= GestureSpeed[ScaleStart]) {
+							isMax = false;
+							break;
+						}
+					}
 				}
-				else {
-					avg += GestureSpeed[w];
+				if (isMax) {
+					break;
 				}
 			}
-			avg /= (float)(window * 2 + 1);
-			SmoothedGestureSpeed.Push(avg);
+
+			ScaleAnimDataInterval(ScaleStart, AnimSaveState.AnimData.Num() - 2, GestureHoldExcessTime);
+
 		}
+	}
+	else {
+		if (HaltingPoints.Num() > 0) {
 
-		GestureSpeed = SmoothedGestureSpeed;
+			FTimespan Start;
+			bool StartTimeInitialized = false;
+			bool hold = false;
+			int holdStartingIndex = -1;
 
-		int MaxNumToScale = 30;
+			for (int i = 1; i < AnimSaveState.AnimData.Num(); i++) {
+
+				FProcessedAnimData& AnimData = AnimSaveState.AnimData[i];
+
+				if (AnimData.IsMarker || AnimData.IsEnd) {
+					continue;
+				}
+
+				if (!StartTimeInitialized) {
+					StartTimeInitialized = true;
+					Start = AnimData.Timestamp;
+				}
+
+				//process sensor data
+
+				FSensorData& SensorData = AnimData.SensorData;
+				for (int j = 0; j < EBodyPart::LAST; j++) {
+
+					EBodyPart Type = EBodyPart(j);
+					FSensorDataEntry* Entry = SensorData.GetEntry(Type);
+
+					if (Type == EBodyPart::HandL || Type == EBodyPart::HandR
+						|| Type == EBodyPart::LowerArmL || Type == EBodyPart::LowerArmR) {
+
+						if (DoHolding && hold) {
+							if (Type == EBodyPart::HandL || Type == EBodyPart::HandR) {
+								Entry->Pos = AnimSaveState.AnimData[i - 1].SensorData.GetEntry(Type)->Pos;
+							}
+							Entry->Rot = AnimSaveState.AnimData[i - 1].SensorData.GetEntry(Type)->Rot;
+						}
 
-		//maximum
-		int maxWindow = 8;
-		int ScaleStart;
-		for (ScaleStart = GestureSpeed.Num() - 1; ScaleStart >= 0 && ScaleStart >= GestureSpeed.Num() - MaxNumToScale; ScaleStart--) {
-			bool isMax = true;
-			for (int w = -maxWindow; w <= maxWindow; w++) {
-				int index = ScaleStart + w;
-				if (index >= 0 && index < GestureSpeed.Num() && index != ScaleStart) {
-					if (GestureSpeed[index] >= GestureSpeed[ScaleStart]) {
-						isMax = false;
-						break;
 					}
+
 				}
+
+				//or time unit?
+				if (!hold && HaltingPoints[0] <= (AnimData.Timestamp - Start).GetTotalSeconds()) {
+					hold = true;
+					holdStartingIndex = i;
+				}
+
 			}
-			if (isMax) {
-				break;
-			}
-		}
 
-		ScaleAnimDataInterval(ScaleStart, AnimSaveState.AnimData.Num() - 2, GestureHoldExcessTime);
+			if (hold && GestureHoldExcessTime > 0.f) {
+				ScaleAnimDataInterval(holdStartingIndex, AnimSaveState.AnimData.Num() - 2, GestureHoldExcessTime);
+			}
 
+		}
 	}
-	
+
 	//---adjust feet position so that they are located at the green foot indicators---
 
 	int amount = 0;
@@ -1169,7 +1227,11 @@ void AMCController::SetMarker() {
 	}
 }
 
-void AMCController::SaveAnimation() {
+void AMCController::SaveAnimationEditor() {
+	SaveAnimation({}, false);
+}
+
+void AMCController::SaveAnimation(const TArray<float>& HaltingPoints, bool skipTranslation) {
 
 	if (IsSavingToAnim) {
 		return;
@@ -1239,14 +1301,17 @@ void AMCController::SaveAnimation() {
 	AnimSaveState.FPS = FramesPerSecond;
 	AnimSaveState.SPF = 1.f / ((float)AnimSaveState.FPS);
 
-	IsSavingToAnim = true;
+	IsSavingToAnim = !skipTranslation;
+	if (skipTranslation) {
+		return;
+	}
 	if (!EditOffsetMode) {
 		AnimSaveState.WaitForAnimInstance = true;
 	}
 
 	AnimSaveState.Pawn->GetAnimInstance()->AdditionalOffsets = AdditionalOffsets;
 
-	bool isValid = PreprocessRecording();
+	bool isValid = PreprocessRecording(HaltingPoints);
 	if (!isValid) {
 		IsSavingToAnim = false;
 		return;
diff --git a/Source/MoCapPlugin/Public/MCController.h b/Source/MoCapPlugin/Public/MCController.h
index 64098b335aeead1ff9e20844e0e871634b51a776..c9aa65a06e4e63e00366c4213811654d45cd761d 100644
--- a/Source/MoCapPlugin/Public/MCController.h
+++ b/Source/MoCapPlugin/Public/MCController.h
@@ -79,7 +79,7 @@ public:
 	void SetMarker();
 
 	UFUNCTION(BlueprintCallable)
-	void SaveAnimation();
+	void SaveAnimationEditor();
 
 	UFUNCTION(BlueprintCallable)
 	void NextEditFrame();
@@ -96,9 +96,10 @@ protected:
 	void SaveToAnimMode();
 
 	void ScaleAnimDataInterval(int start, int end, float DeltaTime);
-	bool PreprocessRecording();
+	bool PreprocessRecording(const TArray<float>& HaltingPoints);
 	void InputNextFrame();
 
+	void SaveAnimation(const TArray<float>& HaltingPoints, bool skipTranslation = false);
 	void SaveAnimSnapshots();
 	UAnimSequence* SaveAsAnimSequence(const FSnapshotAnimations& Recording, const FString& AnimName, const FString& FolderName);
 	void SetBonesAnimationInAnimSeq(const FSnapshotAnimations& Recording, UAnimSequence* AnimSequence);
@@ -162,9 +163,15 @@ public:
 	UPROPERTY(EditAnywhere, meta = (DisplayName = "Frames per Second", Category = "MotionCapture Anim"))
 	int FramesPerSecond = 60;
 
+	UPROPERTY(EditAnywhere, meta = (DisplayName = "Gesture Do Holding", Category = "MotionCapture Anim"))
+	bool DoHolding = false;
+
 	UPROPERTY(EditAnywhere, meta = (DisplayName = "Gesture Hold Scale Excess Time", Category = "MotionCapture Anim"))
 	float GestureHoldExcessTime = 0.f;
 
+	UPROPERTY(EditAnywhere, meta = (DisplayName = "Gesture Hold Excess Easing Exponent", Category = "MotionCapture Anim"))
+	float GestureHoldExcessEasingExponent = 2.f;
+
 	UPROPERTY(EditAnywhere, meta = (DisplayName = "Nr of Leg Smoothing Iterations", Category = "MotionCapture Anim"))
 	int LegSmoothTimes = 5;