From 679c0a2b4cc62b07929eedc8d78c6562ced242c4 Mon Sep 17 00:00:00 2001 From: TrueZhuanjia Date: Fri, 8 Aug 2025 12:57:59 +0800 Subject: [PATCH] normalize on-screen widget size --- VoidLink/Input/CustomOSC/OSCProfilesManager.m | 16 ++++-- VoidLink/Input/OnScreenWidgetView.swift | 49 ++++++++++++++++--- .../LayoutOnScreenControlsViewController.m | 18 +++++-- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/VoidLink/Input/CustomOSC/OSCProfilesManager.m b/VoidLink/Input/CustomOSC/OSCProfilesManager.m index 9a18105f..7aea9c96 100644 --- a/VoidLink/Input/CustomOSC/OSCProfilesManager.m +++ b/VoidLink/Input/CustomOSC/OSCProfilesManager.m @@ -363,8 +363,6 @@ static CGRect layoutViewBounds; else buttonState.vibrationStyle = UIImpactFeedbackStyleLight; // NSLog(@"oscLayerName: %@, opacity: %f, ", oscButtonLayer.name, buttonState.backgroundAlpha); - - // buttonState.oscLayerSizeFactor = oscButtonLayer.bounds; NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil]; @@ -376,8 +374,9 @@ static CGRect layoutViewBounds; CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.center]; OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:normalizedPosition]; buttonState.alias = widgetView.buttonLabel; - buttonState.widthFactor = widgetView.widthFactor; - buttonState.heightFactor = widgetView.heightFactor; + buttonState.widthFactor = [self normalizeSizeWidthFactor:widgetView]; + NSLog(@"logging widthFactor %f", buttonState.widthFactor); + buttonState.heightFactor = [self normalizeSizeHeightFactor:widgetView]; buttonState.backgroundAlpha = widgetView.backgroundAlpha; buttonState.borderWidth = widgetView.borderWidth; buttonState.vibrationStyle = widgetView.vibrationStyle; @@ -396,6 +395,15 @@ static CGRect layoutViewBounds; return buttonStatesEncoded; } +- (CGFloat)normalizeSizeWidthFactor:(OnScreenWidgetView* )widget{ + CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); + return widget.bounds.size.width/screenWidthInPoints * 10000; +} + +- (CGFloat)normalizeSizeHeightFactor:(OnScreenWidgetView* )widget{ + CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]); + return widget.bounds.size.height/screenWidthInPoints * 10000; +} #pragma mark - Queries diff --git a/VoidLink/Input/OnScreenWidgetView.swift b/VoidLink/Input/OnScreenWidgetView.swift index 48bf2aac..83820b4b 100644 --- a/VoidLink/Input/OnScreenWidgetView.swift +++ b/VoidLink/Input/OnScreenWidgetView.swift @@ -45,6 +45,10 @@ import UIKit @objc public var pressed: Bool @objc public var widthFactor: CGFloat = 1.0 @objc public var heightFactor: CGFloat = 1.0 + + @objc public var deNormalizedWidthFactor: CGFloat = 1.0 + @objc public var deNormalizedHeightFactor: CGFloat = 1.0 + @objc public var borderWidth: CGFloat = 0.0 @objc public var backgroundAlpha: CGFloat = 0.5 @objc public var vibrationStyle: Int = 6 @@ -319,7 +323,6 @@ import UIKit if self.widthFactor == 0 {self.widthFactor = 1.0} if self.heightFactor == 0 {self.heightFactor = 1.0} - /* NSLayoutConstraint.activate([ self.centerXAnchor.constraint(equalTo: self.superview!.leadingAnchor, constant: storedLocation.x), @@ -357,21 +360,46 @@ import UIKit } } + func nearestEven(_ value: CGFloat) -> CGFloat { + let rounded = round(value) + if Int(rounded) % 2 == 0 { + return rounded + } else { + let lowerEven = rounded - 1 + let upperEven = rounded + 1 + return abs(value - lowerEven) <= abs(value - upperEven) ? lowerEven : upperEven + } + } + + private func denormalizeSize(sizeFactor:CGFloat) -> CGFloat { + let screenWidthInPoints = UIScreen.main.bounds.width + // return CGFloat(Int(sizeFactor/10000*screenWidthInPoints/2)*2); + return nearestEven(sizeFactor/10000*screenWidthInPoints); + } + private func changeAndActivateContraints(){ + let isNormalizedSizeFactor = self.widthFactor > 6; + if self.shape == "round"{ // we'll make custom osc buttons round & smaller NSLayoutConstraint.activate([ - self.widthAnchor.constraint(equalToConstant: CGFloat(Int(60 * self.widthFactor / 2) * 2)), - self.heightAnchor.constraint(equalToConstant: CGFloat(Int(60 * self.widthFactor / 2) * 2)),]) + self.widthAnchor.constraint(equalToConstant: isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor) : CGFloat(Int(60 * self.widthFactor / 2) * 2)), + self.heightAnchor.constraint(equalToConstant: isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor) : CGFloat(Int(60 * self.widthFactor / 2) * 2)),]) + self.deNormalizedWidthFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor)/60 : self.widthFactor; + self.deNormalizedHeightFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor)/60 : self.widthFactor; } if self.shape == "square" { NSLayoutConstraint.activate([ - self.widthAnchor.constraint(equalToConstant: CGFloat(Int(70 * self.widthFactor / 2) * 2)), - self.heightAnchor.constraint(equalToConstant: CGFloat(Int(65 * self.heightFactor / 2) * 2)),]) + self.widthAnchor.constraint(equalToConstant: isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor) : CGFloat(Int(70 * self.widthFactor / 2) * 2)), + self.heightAnchor.constraint(equalToConstant: isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.heightFactor) : CGFloat(Int(65 * self.heightFactor / 2) * 2)),]) + self.deNormalizedWidthFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor)/70 : self.widthFactor; + self.deNormalizedHeightFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.heightFactor)/65 : self.heightFactor; } if self.shape == "largeSquare" { // override all shape strings NSLayoutConstraint.activate([ - self.widthAnchor.constraint(equalToConstant: CGFloat(Int(170 * self.widthFactor / 2) * 2)), - self.heightAnchor.constraint(equalToConstant: CGFloat(Int(150 * self.heightFactor / 2) * 2)),]) + self.widthAnchor.constraint(equalToConstant:isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor) : CGFloat(Int(170 * self.widthFactor / 2) * 2)), + self.heightAnchor.constraint(equalToConstant:isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.heightFactor) : CGFloat(Int(150 * self.heightFactor / 2) * 2)),]) + self.deNormalizedWidthFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.widthFactor)/170 : self.widthFactor; + self.deNormalizedHeightFactor = isNormalizedSizeFactor ? denormalizeSize(sizeFactor:self.heightFactor)/150 : self.heightFactor; } NSLayoutConstraint.activate([ @@ -379,6 +407,11 @@ import UIKit label.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10), label.centerXAnchor.constraint(equalTo: centerXAnchor), label.centerYAnchor.constraint(equalTo: centerYAnchor),]) + + if self.shape != "round"{ + let shortSideLen = min(self.layer.bounds.size.width, self.layer.bounds.size.height) + self.layer.cornerRadius = shortSideLen/2 < 16 ? shortSideLen/3.2 : 16 + } } private func setupView() { @@ -882,7 +915,7 @@ import UIKit private func setupButtonDownVisualEffectLayer() { self.buttonDownVisualEffectWidth = 8 if self.shape == "round" { - if widthFactor < 1.3 {self.buttonDownVisualEffectWidth = 15.3} // wider visual effect for osc buttons + if deNormalizedWidthFactor < 1.3 {self.buttonDownVisualEffectWidth = 15.3} // wider visual effect for osc buttons else {self.buttonDownVisualEffectWidth = 9} } diff --git a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m index 25a389ad..daf986fd 100644 --- a/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m +++ b/VoidLink/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m @@ -714,6 +714,13 @@ [self->selectedWidgetView.crossMarkLayer removeFromSuperlayer]; } +/* +- (CGFloat)denormalizeSizeFactor:(CGFloat)sizeFactor{ + bool isNormalizedSizeFactor = sizeFactor > 6; + return isNormalizedSizeFactor ? sizeFactor/10000*[UIScreen mainScreen].bounds.size.width +} + */ + - (void)widgetViewTapped: (NSNotification *)notification{ //self.undoButton.alpha = selectedWidgetView.layoutChanges.count>1 && !CGPointEqualToPoint(selectedWidgetView.layoutChanges.lastObject.CGPointValue, selectedWidgetView.initialCenter)? 1.0 : 0.3; @@ -738,8 +745,8 @@ [self.layoutOSC updateGuidelinesForOnScreenWidget:self->selectedWidgetView]; // shows guideline immediately when widget is tapped // setup slider values - [self.widgetSizeSlider setValue: self->selectedWidgetView.widthFactor]; - [self.widgetHeightSlider setValue: self->selectedWidgetView.heightFactor]; + [self.widgetSizeSlider setValue: self->selectedWidgetView.deNormalizedWidthFactor]; + [self.widgetHeightSlider setValue: self->selectedWidgetView.deNormalizedHeightFactor]; [self.widgetAlphaSlider setValue: self->selectedWidgetView.backgroundAlpha]; [self.widgetBorderWidthSlider setValue:self->selectedWidgetView.borderWidth]; @@ -772,10 +779,12 @@ [self->selectedWidgetView updateStickIndicator]; } [self autoFitLabel:self.widgetSizeLabel]; - [self.widgetSizeLabel setText:[LocalizationHelper localizedStringForKey:@"Size: %.2f", self->selectedWidgetView.widthFactor]]; + + + [self.widgetSizeLabel setText:[LocalizationHelper localizedStringForKey:@"Size: %.2f", self->selectedWidgetView.deNormalizedWidthFactor]]; [self autoFitLabel:self.widgetHeightLabel]; - [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", self->selectedWidgetView.heightFactor]]; + [self.widgetHeightLabel setText:[LocalizationHelper localizedStringForKey:@"Height: %.2f", self->selectedWidgetView.deNormalizedHeightFactor]]; [self autoFitLabel:self.widgetAlphaLabel]; [self.widgetAlphaLabel setText:[LocalizationHelper localizedStringForKey:@"Alpha: %.2f", self->selectedWidgetView.backgroundAlpha]]; @@ -797,6 +806,7 @@ } } + - (void)legacyOscLayerTapped: (NSNotification *)notification{ [self enableCommonWidgetTools]; CALayer* controllerLayer = (CALayer* )notification.object;