diff --git a/VoidLink/Base.lproj/iPad.storyboard b/VoidLink/Base.lproj/iPad.storyboard
index 3095c8bf..2d94ccce 100644
--- a/VoidLink/Base.lproj/iPad.storyboard
+++ b/VoidLink/Base.lproj/iPad.storyboard
@@ -1339,6 +1339,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1380,6 +1400,8 @@
+
+
@@ -2185,7 +2207,7 @@
-
+
@@ -2194,13 +2216,13 @@
-
+
-
+
-
+
diff --git a/VoidLink/Base.lproj/iPhone.storyboard b/VoidLink/Base.lproj/iPhone.storyboard
index 6c2b2fea..af94c953 100644
--- a/VoidLink/Base.lproj/iPhone.storyboard
+++ b/VoidLink/Base.lproj/iPhone.storyboard
@@ -2071,6 +2071,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2112,6 +2132,8 @@
+
+
@@ -2212,19 +2234,19 @@
-
+
-
+
-
+
-
+
diff --git a/VoidLink/Input/CustomOSC/OSCProfile.h b/VoidLink/Input/CustomOSC/OSCProfile.h
index d81a31f4..21036ba1 100644
--- a/VoidLink/Input/CustomOSC/OSCProfile.h
+++ b/VoidLink/Input/CustomOSC/OSCProfile.h
@@ -40,6 +40,7 @@ typedef NS_ENUM(NSInteger, MapGyroTo) {
@property (nonatomic, assign) CGFloat accelSensitivityX;
@property (nonatomic, assign) CGFloat accelSensitivityY;
@property (nonatomic, assign) CGFloat accelSensitivityZ;
+@property (nonatomic, assign) double gyroToStickMinOffset;
- (id) initWithName:(NSString*)name buttonStates:(NSMutableArray*)buttonStates isSelected:(BOOL)isSelected;
diff --git a/VoidLink/Input/CustomOSC/OSCProfile.m b/VoidLink/Input/CustomOSC/OSCProfile.m
index 937d7f26..249859bd 100644
--- a/VoidLink/Input/CustomOSC/OSCProfile.m
+++ b/VoidLink/Input/CustomOSC/OSCProfile.m
@@ -41,6 +41,7 @@
[encoder encodeFloat:self.accelSensitivityX forKey:@"accelSensitivityX"];
[encoder encodeFloat:self.accelSensitivityY forKey:@"accelSensitivityY"];
[encoder encodeFloat:self.accelSensitivityZ forKey:@"accelSensitivityZ"];
+ [encoder encodeDouble:self.gyroToStickMinOffset forKey:@"gyroToStickMinOffset"];
}
- (id) initWithCoder:(NSCoder*)decoder {
@@ -57,6 +58,7 @@
self.accelSensitivityX = [decoder containsValueForKey:@"accelSensitivityX"] ? [decoder decodeFloatForKey:@"accelSensitivityX"] : 1.0;
self.accelSensitivityY = [decoder containsValueForKey:@"accelSensitivityY"] ? [decoder decodeFloatForKey:@"accelSensitivityY"] : 1.0;
self.accelSensitivityZ = [decoder containsValueForKey:@"accelSensitivityZ"] ? [decoder decodeFloatForKey:@"accelSensitivityZ"] : 1.0;
+ self.gyroToStickMinOffset = [decoder containsValueForKey:@"gyroToStickMinOffset"] ? [decoder decodeDoubleForKey:@"gyroToStickMinOffset"] : 0;
}
return self;
@@ -76,6 +78,7 @@
copy.accelSensitivityX = self.accelSensitivityX;
copy.accelSensitivityY = self.accelSensitivityY;
copy.accelSensitivityZ = self.accelSensitivityZ;
+ copy.gyroToStickMinOffset = self.gyroToStickMinOffset;
return copy;
}
diff --git a/VoidLink/Input/MotionHandler.swift b/VoidLink/Input/MotionHandler.swift
index 0086b6ee..07266ceb 100644
--- a/VoidLink/Input/MotionHandler.swift
+++ b/VoidLink/Input/MotionHandler.swift
@@ -47,6 +47,7 @@ import CoreMotion
sharedInstance.sensitvityYaw = sharedInstance.oscProfile.gyroSensitivityYaw
sharedInstance.sensitvityPitch = sharedInstance.oscProfile.gyroSensitivityPitch
sharedInstance.sensitvityRoll = sharedInstance.oscProfile.gyroSensitivityRoll
+ sharedInstance.gyroToStickMinOffset = sharedInstance.oscProfile.gyroToStickMinOffset
return sharedInstance
}
@@ -77,6 +78,7 @@ import CoreMotion
@objc public var gyroBiasX: Double = 0
@objc public var gyroBiasY: Double = 0
@objc public var gyroBiasZ: Double = 0
+ @objc public var gyroToStickMinOffset:Double = 0
private var yawBias:Double = 0
private var pitchBias:Double = 0
private var rollBias:Double = 0
@@ -242,18 +244,24 @@ import CoreMotion
pitch = pitchSource*sensitvityPitch*30
LiSendMouseMoveEvent(Int16(yaw),Int16(pitch))
}
-
+
if oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick {
if oscProfile.yawPitchToRightStick {
yaw = rightStickTouchInputX + gyroInputToStickInput(input:yawSource*sensitvityYaw*10)
yaw = self.clampStickInput(input: yaw)
+ yaw = (yaw >= 0 ? 1.0 : -1.0) * gyroToStickMinOffset + (self.stickMaxOffset - gyroToStickMinOffset) * (yaw/self.stickMaxOffset)
+
pitch = rightStickTouchInputY - gyroInputToStickInput(input:pitchSource*sensitvityPitch*10)
pitch = self.clampStickInput(input: pitch)
+ pitch = (pitch >= 0 ? 1.0 : -1.0) * gyroToStickMinOffset + (self.stickMaxOffset - gyroToStickMinOffset) * (pitch/self.stickMaxOffset)
+
self.onScreenControls.sendRightStickTouchPadEvent(yaw, pitch)
}
if oscProfile.rollToLeftStick {
roll = leftStickTouchInputX + gyroInputToStickInput(input:rollSource*sensitvityRoll*10)
roll = self.clampStickInput(input: roll)
+ roll = (roll >= 0 ? 1.0 : -1.0) * gyroToStickMinOffset + (self.stickMaxOffset - gyroToStickMinOffset) * (roll/self.stickMaxOffset)
+
self.onScreenControls.sendLeftStickTouchPadEvent(roll, leftStickTouchInputY)
}
}
diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift
index c00bc7d6..4a1d067b 100644
--- a/VoidLink/Input/OnScreenWidgetView.swift
+++ b/VoidLink/Input/OnScreenWidgetView.swift
@@ -1191,12 +1191,13 @@ import UIKit
var targetX = self.touchInputToStickInput(input: inputX)
var targetY = -self.touchInputToStickInput(input: inputY)
// vertical input must be inverted
- targetX = (targetX >= 0 ? 1.0 : -1.0) * self.minStickOffset + (self.stickMaxOffset - self.minStickOffset) * (targetX/self.stickMaxOffset)
- targetY = (targetY >= 0 ? 1.0 : -1.0) * self.minStickOffset + (self.stickMaxOffset - self.minStickOffset) * (targetY/self.stickMaxOffset)
+
let mixRightStickInputToGyro = (oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick
&& oscProfile.yawPitchToRightStick)
if !mixRightStickInputToGyro || (self.mixInputDelegate?.gyroMixInputStarted() != true) {
+ targetX = (targetX >= 0 ? 1.0 : -1.0) * self.minStickOffset + (self.stickMaxOffset - self.minStickOffset) * (targetX/self.stickMaxOffset)
+ targetY = (targetY >= 0 ? 1.0 : -1.0) * self.minStickOffset + (self.stickMaxOffset - self.minStickOffset) * (targetY/self.stickMaxOffset)
self.onScreenControls.sendRightStickTouchPadEvent(targetX, targetY)
}
self.mixInputDelegate?.mixRightStickAndGyroInput(x: targetX, y: targetY)
diff --git a/VoidLink/MenuSectionView.m b/VoidLink/MenuSectionView.m
index d9046b79..833d97fb 100644
--- a/VoidLink/MenuSectionView.m
+++ b/VoidLink/MenuSectionView.m
@@ -278,7 +278,7 @@ static BOOL overridePersistedFoldState = YES;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL persistedFoldState = [defaults objectForKey:self.identifier] ? [defaults boolForKey:self.identifier] : YES;
- [self setExpanded: MenuSectionView.overridePersistedFoldState ? YES : persistedFoldState];
+ [self setExpanded: MenuSectionView.overridePersistedFoldState ? _expandable : persistedFoldState];
}
- (void)removeSubStackView:(UIStackView *)stackView {
diff --git a/VoidLink/ViewControllers/SettingsViewController.h b/VoidLink/ViewControllers/SettingsViewController.h
index 85fb5f2a..07abf8e2 100644
--- a/VoidLink/ViewControllers/SettingsViewController.h
+++ b/VoidLink/ViewControllers/SettingsViewController.h
@@ -163,6 +163,9 @@
@property (strong, nonatomic) IBOutlet UIStackView *rollSensitivityStack;
@property (strong, nonatomic) IBOutlet UISlider *rollSensitivitySlider;
+@property (strong, nonatomic) IBOutlet UIStackView *gyroToStickMinOffsetStack;
+@property (strong, nonatomic) IBOutlet UISlider *gyroToStickMinOffsetSlider;
+
@property (strong, nonatomic) IBOutlet UIStackView *testStack;
@property (nonatomic, strong) MicHandler *micHandler;
diff --git a/VoidLink/ViewControllers/SettingsViewController.m b/VoidLink/ViewControllers/SettingsViewController.m
index 76d75a00..1240548e 100644
--- a/VoidLink/ViewControllers/SettingsViewController.m
+++ b/VoidLink/ViewControllers/SettingsViewController.m
@@ -362,6 +362,8 @@ BOOL isCustomResolution(int resolutionSelected) {
[self pitchSensitivitySliderMoved:self.pitchSensitivitySlider];
[self.rollSensitivitySlider setValue:[self map_SliderValue_fromVelocFactor:oscProfile.gyroSensitivityRoll]];
[self rollSensitivitySliderMoved:self.rollSensitivitySlider];
+ [self.gyroToStickMinOffsetSlider setValue:(uint16_t)oscProfile.gyroToStickMinOffset];
+ [self gyroMinStickOffsetSliderMoved:self.gyroToStickMinOffsetSlider];
}
- (void)saveMotionControlConfigs{
@@ -375,7 +377,9 @@ BOOL isCustomResolution(int resolutionSelected) {
&& oscProfile.rollToLeftStick == self.rollToLeftStickSwitch.isOn
&& (int16_t)(oscProfile.gyroSensitivityYaw*100) == (int16_t)yawSensitivityPercent
&& (int16_t)(oscProfile.gyroSensitivityPitch*100) == (int16_t)pitchSensitivityPercent
- && (int16_t)(oscProfile.gyroSensitivityRoll*100) == (int16_t)rollSensitivityPercent);
+ && (int16_t)(oscProfile.gyroSensitivityRoll*100) == (int16_t)rollSensitivityPercent
+ && (int16_t)(oscProfile.gyroToStickMinOffset) == (int16_t)self.gyroToStickMinOffsetSlider.value);
+
if(!configNotChanged){
oscProfile.mapGyroTo = self.mapGyroToSelector.selectedSegmentIndex;
oscProfile.yawPitchToRightStick = self.yawPitchToRightStickSwitch.isOn;
@@ -383,6 +387,7 @@ BOOL isCustomResolution(int resolutionSelected) {
oscProfile.gyroSensitivityYaw = yawSensitivityPercent/100;
oscProfile.gyroSensitivityPitch = pitchSensitivityPercent/100;
oscProfile.gyroSensitivityRoll = rollSensitivityPercent/100;
+ oscProfile.gyroToStickMinOffset = (int16_t)self.gyroToStickMinOffsetSlider.value;
[oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
}
}
@@ -714,6 +719,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addDynamicLabelForStack:self.yawSensitivityStack];
[self addDynamicLabelForStack:self.pitchSensitivityStack];
[self addSetting:self.rollSensitivityStack ofId:@"rollSensitivityStack" withInfoTag:NO withDynamicLabel:YES to:motionControlSection];
+ [self addSetting:self.gyroToStickMinOffsetStack ofId:@"gyroToStickMinOffsetStack" withInfoTag:NO withDynamicLabel:YES to:motionControlSection];
[motionControlSection addToParentStack:_parentStack];
MenuSectionView *gesturesSection = [[MenuSectionView alloc] init];
@@ -1816,6 +1822,7 @@ BOOL isCustomResolution(int resolutionSelected) {
self->motionControlSection.expandable = [self isCustomOswEnabled];
+ [self->motionControlSection setExpanded:[self isCustomOswEnabled]];
__weak typeof(self) weakSelf = self;
self->motionControlSection.lockedSectionHandler = ^{
[CountdownAlertController showAlertIn:weakSelf
@@ -1841,6 +1848,8 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.yawSensitivitySlider addTarget:self action:@selector(yawSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
[self.pitchSensitivitySlider addTarget:self action:@selector(pitchSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
[self.rollSensitivitySlider addTarget:self action:@selector(rollSensitivitySliderMoved:) forControlEvents:UIControlEventValueChanged];
+
+ [self.gyroToStickMinOffsetSlider addTarget:self action:@selector(gyroMinStickOffsetSliderMoved:) forControlEvents:UIControlEventValueChanged];
//Motion control settings
@@ -2045,10 +2054,13 @@ BOOL isCustomResolution(int resolutionSelected) {
[self setHidden:false forStack:_yawPitchSensitivityStack];
[self setHidden:true forStack:_rollSensitivityStack];
}
+
+ [self setHidden:!mapGyroToControllerStickEnabled forStack:self.gyroToStickMinOffsetStack];
if(mapGyroToControllerStickEnabled){
[self yawPitchToRightStickSwitchFlipped:self.yawPitchToRightStickSwitch];
[self rollToLeftStickSwitchFlipped:self.rollToLeftStickSwitch];
}
+
if(sender.selectedSegmentIndex == driftCorrection){
[CountdownAlertController showAlertIn:self
@@ -2060,7 +2072,7 @@ BOOL isCustomResolution(int resolutionSelected) {
completion:^{
if(CountdownAlertController.actionCancelled){
[self.mapGyroToSelector setSelectedSegmentIndex:self->oscProfile.mapGyroTo];
- NSLog(@"actionCancelled");
+ [self mapGyroToChanged:self.mapGyroToSelector];
}
else{
MotionHandler* motionHandler = [MotionHandler sharedInstance];
@@ -2079,6 +2091,7 @@ BOOL isCustomResolution(int resolutionSelected) {
countdown:6
completion:^{
[self.mapGyroToSelector setSelectedSegmentIndex:self->oscProfile.mapGyroTo];
+ [self mapGyroToChanged:self.mapGyroToSelector];
}];
}
}];
@@ -2107,6 +2120,10 @@ BOOL isCustomResolution(int resolutionSelected) {
[self findDynamicLabelFromStack:_rollSensitivityStack].text = [NSString stringWithFormat:@" %d%% ", (int16_t)[self map_velocFactorDisplay_fromSliderValue:sender.value]];
}
+- (void)gyroMinStickOffsetSliderMoved:(UISlider* )sender{
+ [self findDynamicLabelFromStack:_gyroToStickMinOffsetStack].text = [NSString stringWithFormat:@" %d ", (int16_t)sender.value];
+}
+
- (void)invokeOscLayout{
// init CustomOSC stuff
/* sets a reference to the correct 'LayoutOnScreenControlsViewController' depending on whether the user is on an iPhone or iPad */
diff --git a/VoidLink/ViewControllers/StreamFrameViewController.m b/VoidLink/ViewControllers/StreamFrameViewController.m
index 73441199..57ad4a0c 100644
--- a/VoidLink/ViewControllers/StreamFrameViewController.m
+++ b/VoidLink/ViewControllers/StreamFrameViewController.m
@@ -436,7 +436,7 @@
_motionHandler = [MotionHandler sharedInstance];
_motionHandler.gyroBiasX = _settings.gyroBiasX.doubleValue;
_motionHandler.gyroBiasY = _settings.gyroBiasY.doubleValue;
- _motionHandler.gyroBiasZ = _settings.gyroBiasZ.doubleValue;
+ _motionHandler.gyroBiasZ = _settings.gyroBiasZ.doubleValue;
_streamView.onScreenControls.instanceReceiverDelegate = _motionHandler;
[_streamView.onScreenControls sendInstance];
diff --git a/VoidLink/mul.lproj/iPad.xcstrings b/VoidLink/mul.lproj/iPad.xcstrings
index ab379863..2022de41 100644
--- a/VoidLink/mul.lproj/iPad.xcstrings
+++ b/VoidLink/mul.lproj/iPad.xcstrings
@@ -2257,6 +2257,36 @@
}
}
},
+ "HqA-an-KEe.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Minimum Stick Offset\"; ObjectID = \"HqA-an-KEe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Minimum Stick Offset"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ }
+ }
+ },
"iel-xl-xd9.text" : {
"comment" : "Class = \"UILabel\"; text = \"Profile:\"; ObjectID = \"iel-xl-xd9\";",
"extractionState" : "extracted_with_value",
diff --git a/VoidLink/mul.lproj/iPhone.xcstrings b/VoidLink/mul.lproj/iPhone.xcstrings
index 08ee2268..71229c12 100644
--- a/VoidLink/mul.lproj/iPhone.xcstrings
+++ b/VoidLink/mul.lproj/iPhone.xcstrings
@@ -847,6 +847,36 @@
}
}
},
+ "52u-T9-1Hv.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Minimum Stick Offset\"; ObjectID = \"52u-T9-1Hv\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Minimum Stick Offset"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ },
+ "zh-Hant" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ },
+ "zh-HK" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "摇杆输出最小偏移量"
+ }
+ }
+ }
+ },
"53H-ST-OtY.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; 53H-ST-OtY.segmentTitles[0] = \"Balanced\"; ObjectID = \"53H-ST-OtY\";",
"extractionState" : "extracted_with_value",