vertical decelerationRate for inertial touchPads (trackball/LsvPad/RsvPad)

This commit is contained in:
TrueZhuanjia committed 2025-12-12 23:28:19 +08:00
1 parent 41eadce89a
commit 4b001f9366
8 files changed
+105 -35

No files matched your search

@@ -406,7 +406,8 @@ static CGRect layoutViewBounds;
buttonState.yawFactor = widgetView.yawFactor; buttonState.yawFactor = widgetView.yawFactor;
buttonState.pitchFactor = widgetView.pitchFactor; buttonState.pitchFactor = widgetView.pitchFactor;
buttonState.rollFactor = widgetView.rollFactor; buttonState.rollFactor = widgetView.rollFactor;
buttonState.decelerationRate = widgetView.decelerationRate; buttonState.decelerationRateX = widgetView.decelerationRateX;
buttonState.decelerationRateY = widgetView.decelerationRateY;
buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset; buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset;
buttonState.widgetShape = widgetView.shape; buttonState.widgetShape = widgetView.shape;
buttonState.minStickOffset = widgetView.minStickOffset; buttonState.minStickOffset = widgetView.minStickOffset;
@@ -40,7 +40,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) CGFloat yawFactor; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat yawFactor; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat pitchFactor; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat pitchFactor; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat rollFactor; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat rollFactor; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat decelerationRate; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat decelerationRateX; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat decelerationRateY; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat stickIndicatorOffset; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat stickIndicatorOffset; // for OnScreenWidgetView
@property (nonatomic, assign) CGFloat minStickOffset; // for OnScreenWidgetView @property (nonatomic, assign) CGFloat minStickOffset; // for OnScreenWidgetView
@property NSString* widgetShape; // for OnScreenWidgetView @property NSString* widgetShape; // for OnScreenWidgetView
@@ -50,7 +50,8 @@
[encoder encodeFloat:self.yawFactor forKey:@"yawFactor"]; [encoder encodeFloat:self.yawFactor forKey:@"yawFactor"];
[encoder encodeFloat:self.pitchFactor forKey:@"pitchFactor"]; [encoder encodeFloat:self.pitchFactor forKey:@"pitchFactor"];
[encoder encodeFloat:self.rollFactor forKey:@"rollFactor"]; [encoder encodeFloat:self.rollFactor forKey:@"rollFactor"];
[encoder encodeFloat:self.decelerationRate forKey:@"decelerationRate"]; [encoder encodeFloat:self.decelerationRateX forKey:@"decelerationRateX"];
[encoder encodeFloat:self.decelerationRateY forKey:@"decelerationRateY"];
[encoder encodeFloat:self.stickIndicatorOffset forKey:@"stickIndicatorOffset"]; [encoder encodeFloat:self.stickIndicatorOffset forKey:@"stickIndicatorOffset"];
[encoder encodeFloat:self.oscLayerSizeFactor forKey:@"oscLayerSizeFactor"]; [encoder encodeFloat:self.oscLayerSizeFactor forKey:@"oscLayerSizeFactor"];
[encoder encodeFloat:self.backgroundAlpha forKey:@"backgroundAlpha"]; [encoder encodeFloat:self.backgroundAlpha forKey:@"backgroundAlpha"];
@@ -83,7 +84,8 @@
self.yawFactor = [decoder containsValueForKey:@"yawFactor"] ? [decoder decodeFloatForKey:@"yawFactor"] : 1.0; self.yawFactor = [decoder containsValueForKey:@"yawFactor"] ? [decoder decodeFloatForKey:@"yawFactor"] : 1.0;
self.pitchFactor = [decoder containsValueForKey:@"pitchFactor"] ? [decoder decodeFloatForKey:@"pitchFactor"] : 1.0; self.pitchFactor = [decoder containsValueForKey:@"pitchFactor"] ? [decoder decodeFloatForKey:@"pitchFactor"] : 1.0;
self.rollFactor = [decoder containsValueForKey:@"rollFactor"] ? [decoder decodeFloatForKey:@"rollFactor"] : 1.0; self.rollFactor = [decoder containsValueForKey:@"rollFactor"] ? [decoder decodeFloatForKey:@"rollFactor"] : 1.0;
self.decelerationRate = [decoder decodeFloatForKey:@"decelerationRate"]; self.decelerationRateX = [decoder containsValueForKey:@"decelerationRateX"] ? [decoder decodeFloatForKey:@"decelerationRateX"] : 0.5;
self.decelerationRateY = [decoder containsValueForKey:@"decelerationRateY"] ? [decoder decodeFloatForKey:@"decelerationRateY"] : 0.5;
self.stickIndicatorOffset = [decoder decodeFloatForKey:@"stickIndicatorOffset"]; self.stickIndicatorOffset = [decoder decodeFloatForKey:@"stickIndicatorOffset"];
self.oscLayerSizeFactor = [decoder decodeFloatForKey:@"oscLayerSizeFactor"]; self.oscLayerSizeFactor = [decoder decodeFloatForKey:@"oscLayerSizeFactor"];
self.backgroundAlpha = [decoder containsValueForKey:@"backgroundAlpha"] ? [decoder decodeFloatForKey:@"backgroundAlpha"] : 0.5; self.backgroundAlpha = [decoder containsValueForKey:@"backgroundAlpha"] ? [decoder decodeFloatForKey:@"backgroundAlpha"] : 0.5;
+7 -5
View File
@@ -7,13 +7,14 @@
// //
class InertialScroller { class InertialScroller {
public var decelerationRate: CGFloat public var decelerationRateX: CGFloat
public var decelerationRateY: CGFloat
public lazy var timer: SafeTimer? = { public lazy var timer: SafeTimer? = {
SafeTimer(interval: 1/displayLinkRate) { [weak self] in SafeTimer(interval: 1/displayLinkRate) { [weak self] in
guard let self = self, handler != nil else {return} guard let self = self, handler != nil else {return}
self.vector.dx = self.vector.dx * decelerationRate self.vector.dx = self.vector.dx * decelerationRateX
self.vector.dy = self.vector.dy * decelerationRate self.vector.dy = self.vector.dy * decelerationRateY
if abs(self.vector.dx) < self.timerSuspendThreshold && abs(self.vector.dy) < self.timerSuspendThreshold { if abs(self.vector.dx) < self.timerSuspendThreshold && abs(self.vector.dy) < self.timerSuspendThreshold {
self.timer?.pause() self.timer?.pause()
} }
@@ -27,7 +28,8 @@ class InertialScroller {
public var handler: (() -> Void)? public var handler: (() -> Void)?
init(decelerationRate: CGFloat = 0.93, displayLinkRate: CGFloat = 60, handler: (() -> Void)? = nil) { init(decelerationRate: CGFloat = 0.93, displayLinkRate: CGFloat = 60, handler: (() -> Void)? = nil) {
self.decelerationRate = decelerationRate self.decelerationRateX = decelerationRate
self.decelerationRateY = decelerationRate
self.displayLinkRate = displayLinkRate self.displayLinkRate = displayLinkRate
self.handler = handler self.handler = handler
} }
+11 -5
View File
@@ -215,7 +215,8 @@ import UIKit
// trackball // trackball
private var trackballVelocity: CGPoint = .zero private var trackballVelocity: CGPoint = .zero
private var trackballDecelerationTimer: Timer? private var trackballDecelerationTimer: Timer?
@objc public var decelerationRate: CGFloat = 0.93 @objc public var decelerationRateX: CGFloat = 0.5
@objc public var decelerationRateY: CGFloat = 0.5
private let trackballVelocityThreshold: CGFloat = 0.1 private let trackballVelocityThreshold: CGFloat = 0.1
@objc public var slideThreshold: CGFloat = 6.0 @objc public var slideThreshold: CGFloat = 6.0
@@ -408,7 +409,8 @@ import UIKit
@objc public func setupInertialScroller() { @objc public func setupInertialScroller() {
if self.hasInertia { if self.hasInertia {
self.inertialScroller = InertialScroller(decelerationRate: self.decelerationRate, displayLinkRate: CGFloat(self.tempSettings.framerate.intValue)) self.inertialScroller = InertialScroller(decelerationRate: self.decelerationRateX, displayLinkRate: CGFloat(self.tempSettings.framerate.intValue))
self.inertialScroller.decelerationRateY = self.decelerationRateY
} }
} }
@@ -2001,6 +2003,10 @@ import UIKit
touchesEnded(touches, with: event) touchesEnded(touches, with: event)
} }
private func inertiaEnabled() -> Bool {
return self.decelerationRateX > 0.50001 || self.decelerationRateY > 0.50001
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchBegan = false self.touchBegan = false
super.touchesEnded(touches, with: event) super.touchesEnded(touches, with: event)
@@ -2036,7 +2042,7 @@ import UIKit
self.clearRightStickTouchPadFlag() self.clearRightStickTouchPadFlag()
if widgetType == WidgetTypeEnum.touchPad {self.resetStickBallPositionAndHideIndicator()} if widgetType == WidgetTypeEnum.touchPad {self.resetStickBallPositionAndHideIndicator()}
case "LSVPAD": case "LSVPAD":
if self.decelerationRate > 0.50001 { if self.inertiaEnabled() {
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)} if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
if self.inertialScroller.handler == nil { if self.inertialScroller.handler == nil {
self.inertialScroller.handler = { self.inertialScroller.handler = {
@@ -2049,7 +2055,7 @@ import UIKit
} }
else {self.clearLeftStickTouchPadFlag()} else {self.clearLeftStickTouchPadFlag()}
case "RSVPAD": case "RSVPAD":
if self.decelerationRate > 0.50001 { if self.inertiaEnabled() {
if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)} if(!firstTouchMoved) {self.inertialScroller.vector = CGVector(dx: 0, dy: 0)}
if self.inertialScroller.handler == nil { if self.inertialScroller.handler == nil {
var synthesizedDeltaX:CGFloat = 0 var synthesizedDeltaX:CGFloat = 0
@@ -2076,7 +2082,7 @@ import UIKit
} }
else {self.clearRightStickTouchPadFlag()} else {self.clearRightStickTouchPadFlag()}
case "TRACKBALL": case "TRACKBALL":
if allSpawnedTouchesCount == 1, self.decelerationRate > 0 { if allSpawnedTouchesCount == 1, self.inertiaEnabled() {
if(mousePointerMoved){ if(mousePointerMoved){
self.startTrackballMomentum() self.startTrackballMomentum()
mousePointerMoved = false //reset flag mousePointerMoved = false //reset flag
+2 -1
View File
@@ -568,7 +568,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
widgetView.yawFactor = buttonState.yawFactor; widgetView.yawFactor = buttonState.yawFactor;
widgetView.pitchFactor = buttonState.pitchFactor; widgetView.pitchFactor = buttonState.pitchFactor;
widgetView.rollFactor = buttonState.rollFactor; widgetView.rollFactor = buttonState.rollFactor;
widgetView.decelerationRate = buttonState.decelerationRate; widgetView.decelerationRateX = buttonState.decelerationRateX;
widgetView.decelerationRateY = buttonState.decelerationRateY;
widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset;
widgetView.minStickOffset = buttonState.minStickOffset; widgetView.minStickOffset = buttonState.minStickOffset;
widgetView.buttonMode = buttonState.buttonMode; widgetView.buttonMode = buttonState.buttonMode;
+35 -12
View File
@@ -801,13 +801,13 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "透明度:%.2f" "value" : "透明度: %.2f"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "透明度:%.2f" "value" : "透明度: %.2f"
} }
} }
} }
@@ -1129,13 +1129,13 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "邊框寬度:%.2f" "value" : "邊框寬度: %.2f"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "邊框寬度:%.2f" "value" : "邊框寬度: %.2f"
} }
} }
} }
@@ -1711,13 +1711,36 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "減速率:%.3f " "value" : "減速率: %.3f "
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "減速率:%.3f " "value" : "減速率: %.3f "
}
}
}
},
"DecelerationRateY: %.3f " : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "减速率Y: %.3f "
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "減速率Y: %.3f "
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "減速率Y: %.3f "
} }
} }
} }
@@ -3042,13 +3065,13 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "指示器偏移:%.0f" "value" : "指示器偏移: %.0f"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "指示器偏移:%.0f" "value" : "指示器偏移: %.0f"
} }
} }
} }
@@ -5947,13 +5970,13 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "靈敏度X:%.2f" "value" : "靈敏度X: %.2f"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "靈敏度X:%.2f" "value" : "靈敏度X: %.2f"
} }
} }
} }
@@ -5970,13 +5993,13 @@
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "靈敏度Y:%.2f" "value" : "靈敏度Y: %.2f"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "靈敏度Y:%.2f" "value" : "靈敏度Y: %.2f"
} }
} }
} }
@@ -34,6 +34,12 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
BorderWidthSliderModeCount BorderWidthSliderModeCount
}; };
typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
decelerationRate2D,
decelerationRateY,
DecelerationRateSliderModeCount
};
@end @end
@@ -43,6 +49,7 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
OnScreenWidgetView* selectedWidgetView; OnScreenWidgetView* selectedWidgetView;
AlphaSliderMode alphaSliderMode; AlphaSliderMode alphaSliderMode;
BorderWidthSliderMode borderWidthSliderMode; BorderWidthSliderMode borderWidthSliderMode;
DecelerationRateSliderMode decelerationRateSliderMode;
CALayer* selectedControllerLayer; CALayer* selectedControllerLayer;
CGRect controllerLoadedBounds; CGRect controllerLoadedBounds;
bool widgetViewSelected; bool widgetViewSelected;
@@ -157,7 +164,8 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
widgetView.yawFactor = buttonState.yawFactor; widgetView.yawFactor = buttonState.yawFactor;
widgetView.pitchFactor = buttonState.pitchFactor; widgetView.pitchFactor = buttonState.pitchFactor;
widgetView.rollFactor = buttonState.rollFactor; widgetView.rollFactor = buttonState.rollFactor;
widgetView.decelerationRate = buttonState.decelerationRate; widgetView.decelerationRateX = buttonState.decelerationRateX;
widgetView.decelerationRateY = buttonState.decelerationRateY;
widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset; widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset;
widgetView.minStickOffset = buttonState.minStickOffset; widgetView.minStickOffset = buttonState.minStickOffset;
widgetView.buttonMode = buttonState.buttonMode; widgetView.buttonMode = buttonState.buttonMode;
@@ -353,7 +361,7 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
} }
} }
- (void)switchAlphaSlider:(UISwipeGestureRecognizer *)sender { - (void)switchAlphaSlider:(UITapGestureRecognizer *)sender {
if(!widgetViewSelected) return; if(!widgetViewSelected) return;
alphaSliderMode = (alphaSliderMode + 1) % AlphaSliderModeCount; alphaSliderMode = (alphaSliderMode + 1) % AlphaSliderModeCount;
[self loadWidgetAlphas]; [self loadWidgetAlphas];
@@ -381,7 +389,13 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
} }
} }
- (void)switchBorderWidthSlider:(UISwipeGestureRecognizer *)sender { - (void)switchDecelerationRateSlider:(UITapGestureRecognizer *)sender {
if(!widgetViewSelected) return;
decelerationRateSliderMode = (decelerationRateSliderMode + 1) % DecelerationRateSliderModeCount;
[self loadDecelerationRates];
}
- (void)switchBorderWidthSlider:(UITapGestureRecognizer *)sender {
if(!widgetViewSelected) return; if(!widgetViewSelected) return;
borderWidthSliderMode = (borderWidthSliderMode + 1) % BorderWidthSliderModeCount; borderWidthSliderMode = (borderWidthSliderMode + 1) % BorderWidthSliderModeCount;
OnScreenWidgetView.isTweakingHighlightSize = borderWidthSliderMode == hightlightSize; OnScreenWidgetView.isTweakingHighlightSize = borderWidthSliderMode == hightlightSize;
@@ -731,7 +745,8 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
newWidget.yawFactor = widget.yawFactor; newWidget.yawFactor = widget.yawFactor;
newWidget.pitchFactor = widget.pitchFactor; newWidget.pitchFactor = widget.pitchFactor;
newWidget.rollFactor = widget.rollFactor; newWidget.rollFactor = widget.rollFactor;
newWidget.decelerationRate = widget.decelerationRate; newWidget.decelerationRateX = widget.decelerationRateX;
newWidget.decelerationRateY = widget.decelerationRateY;
newWidget.stickIndicatorOffset = widget.stickIndicatorOffset; newWidget.stickIndicatorOffset = widget.stickIndicatorOffset;
newWidget.minStickOffset = widget.minStickOffset; newWidget.minStickOffset = widget.minStickOffset;
[newWidget setVibrationWithStyle:widget.vibrationStyle]; [newWidget setVibrationWithStyle:widget.vibrationStyle];
@@ -978,9 +993,9 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
[self autoFitLabel:self.autoTapLabel]; [self autoFitLabel:self.autoTapLabel];
self.decelerationRateStack.hidden = !selectedWidgetView.hasInertia; self.decelerationRateStack.hidden = !selectedWidgetView.hasInertia;
[self.decelerationRateSlider setValue:selectedWidgetView.decelerationRate]; [self.decelerationRateSlider setValue:selectedWidgetView.decelerationRateX];
[self autoFitLabel:self.decelerationRateLabel]; [self autoFitLabel:self.decelerationRateLabel];
[self decelerationRateSliderMoved:self.decelerationRateSlider]; [self loadDecelerationRates];
self.mouseDownButtonStack.hidden = !selectedWidgetView.isMousePadWithButtonActions; self.mouseDownButtonStack.hidden = !selectedWidgetView.isMousePadWithButtonActions;
self.mouseButtonDownSelector.selectedSegmentIndex = selectedWidgetView.mouseButtonAction; self.mouseButtonDownSelector.selectedSegmentIndex = selectedWidgetView.mouseButtonAction;
@@ -1208,9 +1223,23 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
return; return;
} }
- (void)loadDecelerationRates {
self.decelerationRateSlider.value = decelerationRateSliderMode == decelerationRate2D ? selectedWidgetView.decelerationRateX : selectedWidgetView.decelerationRateY;
NSString* labelText = [LocalizationHelper localizedStringForKey:decelerationRateSliderMode == decelerationRate2D ? @"Deceleration Rate: %.3f " : @"DecelerationRateY: %.3f ", self.decelerationRateSlider.value];
[self.decelerationRateLabel setText: labelText];
}
- (void)decelerationRateSliderMoved:(UISlider* )sender{ - (void)decelerationRateSliderMoved:(UISlider* )sender{
[self.decelerationRateLabel setText:[LocalizationHelper localizedStringForKey:@"Deceleration Rate: %.3f ", sender.value]]; if(self->selectedWidgetView != nil && self->widgetViewSelected){
if(self->selectedWidgetView != nil && self->widgetViewSelected) self->selectedWidgetView.decelerationRate = sender.value; if(decelerationRateSliderMode == decelerationRate2D){
self->selectedWidgetView.decelerationRateX = sender.value;
self->selectedWidgetView.decelerationRateY = sender.value;
}
else{
self->selectedWidgetView.decelerationRateY = sender.value;
}
}
[self loadDecelerationRates];
return; return;
} }
@@ -1361,6 +1390,11 @@ typedef NS_ENUM(NSUInteger, BorderWidthSliderMode) {
self.rollFactorLabel.text = [LocalizationHelper localizedStringForKey:@"Roll Factor"]; self.rollFactorLabel.text = [LocalizationHelper localizedStringForKey:@"Roll Factor"];
self.rollFactorStack.hidden = YES; self.rollFactorStack.hidden = YES;
UITapGestureRecognizer *decelerationRateSliderTapGesture =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(switchDecelerationRateSlider:)];
[self.decelerationRateLabel addGestureRecognizer:decelerationRateSliderTapGesture];
self.decelerationRateLabel.userInteractionEnabled = true;
[self.decelerationRateSlider addTarget:self action:@selector(decelerationRateSliderMoved:) forControlEvents:(UIControlEventValueChanged)]; [self.decelerationRateSlider addTarget:self action:@selector(decelerationRateSliderMoved:) forControlEvents:(UIControlEventValueChanged)];
self.decelerationRateLabel.text = [LocalizationHelper localizedStringForKey:@"Deceleration Rate"]; self.decelerationRateLabel.text = [LocalizationHelper localizedStringForKey:@"Deceleration Rate"];
self.decelerationRateStack.hidden = YES; self.decelerationRateStack.hidden = YES;