- on screen button “folder” prototype
- overlapped buttons triggered at touch began - memory management fixes - reduce toolbox view & widget layout tool animation - fast widget profile loading - toolbox & widget profile selector quick dismiss
This commit is contained in:
1 parent
ab1d6bfa90
commit
8f8e86ab4f
45 files changed
+1765
-592
No files matched your search
@@ -726,11 +726,11 @@
|
|||||||
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
||||||
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */,
|
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */,
|
||||||
840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */,
|
840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */,
|
||||||
9819CC12254F107A008A7C8E /* RelativeTouchHandler.h */,
|
|
||||||
843CC7F42C1E778000BBC475 /* NativeTouchHandler.h */,
|
|
||||||
844CD0E82C7F847E004861A7 /* PureNativeTouchHandler.h */,
|
844CD0E82C7F847E004861A7 /* PureNativeTouchHandler.h */,
|
||||||
844CD0EA2C7F8500004861A7 /* PureNativeTouchHandler.m */,
|
844CD0EA2C7F8500004861A7 /* PureNativeTouchHandler.m */,
|
||||||
|
843CC7F42C1E778000BBC475 /* NativeTouchHandler.h */,
|
||||||
843CC7F52C1E7A1700BBC475 /* NativeTouchHandler.m */,
|
843CC7F52C1E7A1700BBC475 /* NativeTouchHandler.m */,
|
||||||
|
9819CC12254F107A008A7C8E /* RelativeTouchHandler.h */,
|
||||||
9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */,
|
9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */,
|
||||||
9819CC20254F180F008A7C8E /* AbsoluteTouchHandler.h */,
|
9819CC20254F180F008A7C8E /* AbsoluteTouchHandler.h */,
|
||||||
9819CC21254F180F008A7C8E /* AbsoluteTouchHandler.m */,
|
9819CC21254F180F008A7C8E /* AbsoluteTouchHandler.m */,
|
||||||
|
|||||||
@@ -1950,6 +1950,46 @@
|
|||||||
<constraint firstAttribute="height" constant="31" id="RRk-QS-MEj"/>
|
<constraint firstAttribute="height" constant="31" id="RRk-QS-MEj"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</stackView>
|
</stackView>
|
||||||
|
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="prr-Do-Nna">
|
||||||
|
<rect key="frame" x="3145" y="270" width="300.5" height="31"/>
|
||||||
|
<subviews>
|
||||||
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Double Tap Shorcut" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="v5f-j3-pEc" userLabel="uiLabel">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="150.5" height="31"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cw7-Jc-7bZ">
|
||||||
|
<rect key="frame" x="170.5" y="0.0" width="132" height="31"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="130" id="zQj-YX-sHL"/>
|
||||||
|
</constraints>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="31" id="BW8-EB-nuy"/>
|
||||||
|
</constraints>
|
||||||
|
</stackView>
|
||||||
|
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="jLJ-Eo-Zi6">
|
||||||
|
<rect key="frame" x="3145" y="307" width="358.5" height="31"/>
|
||||||
|
<subviews>
|
||||||
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pencil Pauses Native Touch" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hZw-pC-Qxm" userLabel="uiLabel">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="208.5" height="31"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pjf-Vi-3wE">
|
||||||
|
<rect key="frame" x="228.5" y="0.0" width="132" height="31"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="130" id="jfj-nX-rgt"/>
|
||||||
|
</constraints>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="31" id="pV0-m0-1pz"/>
|
||||||
|
</constraints>
|
||||||
|
</stackView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</view>
|
</view>
|
||||||
@@ -1987,6 +2027,8 @@
|
|||||||
<outlet property="customResolutionSwitch" destination="E5w-kK-dOo" id="hrt-v2-8dY"/>
|
<outlet property="customResolutionSwitch" destination="E5w-kK-dOo" id="hrt-v2-8dY"/>
|
||||||
<outlet property="delayLeftClickStack" destination="Xp7-7O-Ndt" id="CwB-Wy-beh"/>
|
<outlet property="delayLeftClickStack" destination="Xp7-7O-Ndt" id="CwB-Wy-beh"/>
|
||||||
<outlet property="delayLeftClickSwitch" destination="Haf-rg-zLB" id="FaA-3p-JDw"/>
|
<outlet property="delayLeftClickSwitch" destination="Haf-rg-zLB" id="FaA-3p-JDw"/>
|
||||||
|
<outlet property="doubleTapShortcutStack" destination="prr-Do-Nna" id="sK3-va-U5W"/>
|
||||||
|
<outlet property="doubleTapShortcutSwitch" destination="cw7-Jc-7bZ" id="bRy-9x-0Tl"/>
|
||||||
<outlet property="duckOtherAppStack" destination="gBG-8F-6F8" id="T9P-ys-pHB"/>
|
<outlet property="duckOtherAppStack" destination="gBG-8F-6F8" id="T9P-ys-pHB"/>
|
||||||
<outlet property="duckOtherAppSwitch" destination="YEv-1B-97I" id="o3Q-yt-74a"/>
|
<outlet property="duckOtherAppSwitch" destination="YEv-1B-97I" id="o3Q-yt-74a"/>
|
||||||
<outlet property="edgeSlidingSensitivitySlider" destination="41s-BD-8rZ" id="ytk-Y5-Alq"/>
|
<outlet property="edgeSlidingSensitivitySlider" destination="41s-BD-8rZ" id="ytk-Y5-Alq"/>
|
||||||
@@ -2049,6 +2091,8 @@
|
|||||||
<outlet property="optimizeGamesSwitch" destination="Sui-Ig-YxN" id="Lxu-si-ugy"/>
|
<outlet property="optimizeGamesSwitch" destination="Sui-Ig-YxN" id="Lxu-si-ugy"/>
|
||||||
<outlet property="passthroughGesturesStack" destination="wUP-2q-5vh" id="a4w-16-lLs"/>
|
<outlet property="passthroughGesturesStack" destination="wUP-2q-5vh" id="a4w-16-lLs"/>
|
||||||
<outlet property="passthroughGesturesSwitch" destination="eO1-kV-e9j" id="5r8-o4-t9J"/>
|
<outlet property="passthroughGesturesSwitch" destination="eO1-kV-e9j" id="5r8-o4-t9J"/>
|
||||||
|
<outlet property="pencilPausesNativeTouchStack" destination="jLJ-Eo-Zi6" id="a4V-Lp-xDG"/>
|
||||||
|
<outlet property="pencilPausesNativeTouchSwitch" destination="Pjf-Vi-3wE" id="L84-RY-6iV"/>
|
||||||
<outlet property="pencilTickIntervalSlider" destination="IOG-l4-gtQ" id="3Kb-uT-ILa"/>
|
<outlet property="pencilTickIntervalSlider" destination="IOG-l4-gtQ" id="3Kb-uT-ILa"/>
|
||||||
<outlet property="pencilTickIntervalStack" destination="O2s-9s-ABi" id="0kk-q4-ppy"/>
|
<outlet property="pencilTickIntervalStack" destination="O2s-9s-ABi" id="0kk-q4-ppy"/>
|
||||||
<outlet property="pencilTickSelector" destination="bVv-CW-kN8" id="Ymr-VI-Ilj"/>
|
<outlet property="pencilTickSelector" destination="bVv-CW-kN8" id="Ymr-VI-Ilj"/>
|
||||||
@@ -2423,7 +2467,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="z5Q-bW-WQ8" userLabel="widgetPanelStack" customClass="WidgetPanelStackView">
|
<stackView opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="z5Q-bW-WQ8" userLabel="widgetPanelStack" customClass="WidgetPanelStackView">
|
||||||
<rect key="frame" x="325" y="156" width="650" height="854"/>
|
<rect key="frame" x="325" y="156" width="650" height="890"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Profile:" textAlignment="center" lineBreakMode="tailTruncation" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iel-xl-xd9">
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Profile:" textAlignment="center" lineBreakMode="tailTruncation" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iel-xl-xd9">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="650" height="37"/>
|
<rect key="frame" x="0.0" y="0.0" width="650" height="37"/>
|
||||||
@@ -2825,6 +2869,55 @@
|
|||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
</stackView>
|
</stackView>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FEI-wQ-Q3w">
|
||||||
|
<rect key="frame" x="0.0" y="859" width="650" height="31"/>
|
||||||
|
<subviews>
|
||||||
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Collected widgets " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="WLg-7a-5wu" userLabel="uiLabel">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="130" height="31"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="130" id="MfE-jp-WQW"/>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<segmentedControl opaque="NO" alpha="0.76999998092651367" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="sch-0e-nfa">
|
||||||
|
<rect key="frame" x="130" y="0.0" width="180" height="32"/>
|
||||||
|
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="180" id="TbL-OE-jvg"/>
|
||||||
|
</constraints>
|
||||||
|
<segments>
|
||||||
|
<segment title="display"/>
|
||||||
|
<segment title="hide"/>
|
||||||
|
</segments>
|
||||||
|
<color key="tintColor" systemColor="systemGray3Color"/>
|
||||||
|
<color key="selectedSegmentTintColor" red="0.23087820410000001" green="0.4576539993" blue="0.51765710119999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
</segmentedControl>
|
||||||
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Reveal mode " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000298023224" translatesAutoresizingMaskIntoConstraints="NO" id="MyP-Aq-htW" userLabel="uiLabel">
|
||||||
|
<rect key="frame" x="310" y="0.0" width="130" height="31"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="130" id="6dc-EO-c30"/>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<segmentedControl opaque="NO" alpha="0.76999998092651367" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="Qr8-Df-7Zu" userLabel="revealModeSelector">
|
||||||
|
<rect key="frame" x="440" y="0.0" width="210" height="32"/>
|
||||||
|
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="180" id="jaU-fY-1Xa"/>
|
||||||
|
</constraints>
|
||||||
|
<segments>
|
||||||
|
<segment title="coexist"/>
|
||||||
|
<segment title="exclusive"/>
|
||||||
|
</segments>
|
||||||
|
<color key="tintColor" systemColor="systemGray3Color"/>
|
||||||
|
<color key="selectedSegmentTintColor" red="0.23087820410000001" green="0.4576539993" blue="0.51765710119999997" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
|
</segmentedControl>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="displayP3"/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -2852,6 +2945,8 @@
|
|||||||
<outlet property="buttonModeStack" destination="LGW-oJ-5Zf" id="Jn6-Mu-XYp"/>
|
<outlet property="buttonModeStack" destination="LGW-oJ-5Zf" id="Jn6-Mu-XYp"/>
|
||||||
<outlet property="chevronImageView" destination="iVZ-Fd-dY7" id="403-Nj-wRx"/>
|
<outlet property="chevronImageView" destination="iVZ-Fd-dY7" id="403-Nj-wRx"/>
|
||||||
<outlet property="chevronView" destination="hKp-ds-86I" id="Og9-aT-zNH"/>
|
<outlet property="chevronView" destination="hKp-ds-86I" id="Og9-aT-zNH"/>
|
||||||
|
<outlet property="collectedWidgetsSelector" destination="sch-0e-nfa" id="ApS-gt-9Wq"/>
|
||||||
|
<outlet property="collectedWidgetsStack" destination="FEI-wQ-Q3w" id="o17-RT-wJJ"/>
|
||||||
<outlet property="componentSizeLabel" destination="XMg-F0-m2y" id="pQ6-MN-dcV"/>
|
<outlet property="componentSizeLabel" destination="XMg-F0-m2y" id="pQ6-MN-dcV"/>
|
||||||
<outlet property="componentSizeSlider" destination="ewF-K6-Rkd" id="yVC-sP-VSe"/>
|
<outlet property="componentSizeSlider" destination="ewF-K6-Rkd" id="yVC-sP-VSe"/>
|
||||||
<outlet property="componentSizeStack" destination="WHh-JZ-wlT" id="6p9-Rd-Caq"/>
|
<outlet property="componentSizeStack" destination="WHh-JZ-wlT" id="6p9-Rd-Caq"/>
|
||||||
@@ -2870,6 +2965,7 @@
|
|||||||
<outlet property="pitchFactorLabel" destination="fq3-ie-8by" id="dpT-7M-rIg"/>
|
<outlet property="pitchFactorLabel" destination="fq3-ie-8by" id="dpT-7M-rIg"/>
|
||||||
<outlet property="pitchFactorSlider" destination="4NQ-cL-QH0" id="VxC-yb-L1u"/>
|
<outlet property="pitchFactorSlider" destination="4NQ-cL-QH0" id="VxC-yb-L1u"/>
|
||||||
<outlet property="pitchFactorStack" destination="JNt-eT-HCs" id="iHx-Nk-Oko"/>
|
<outlet property="pitchFactorStack" destination="JNt-eT-HCs" id="iHx-Nk-Oko"/>
|
||||||
|
<outlet property="revealModeSelector" destination="Qr8-Df-7Zu" id="cnM-SJ-iGS"/>
|
||||||
<outlet property="rollFactorLabel" destination="x9i-JN-FSn" id="Z6N-It-yAL"/>
|
<outlet property="rollFactorLabel" destination="x9i-JN-FSn" id="Z6N-It-yAL"/>
|
||||||
<outlet property="rollFactorSlider" destination="ELy-jP-cY6" id="6aX-c5-0po"/>
|
<outlet property="rollFactorSlider" destination="ELy-jP-cY6" id="6aX-c5-0po"/>
|
||||||
<outlet property="rollFactorStack" destination="zqk-Xa-Dku" id="PNE-l7-JwX"/>
|
<outlet property="rollFactorStack" destination="zqk-Xa-Dku" id="PNE-l7-JwX"/>
|
||||||
@@ -3010,7 +3106,7 @@
|
|||||||
<image name="tray.full.fill" catalog="system" width="128" height="88"/>
|
<image name="tray.full.fill" catalog="system" width="128" height="88"/>
|
||||||
<image name="video.and.waveform" catalog="system" width="128" height="94"/>
|
<image name="video.and.waveform" catalog="system" width="128" height="94"/>
|
||||||
<systemColor name="linkColor">
|
<systemColor name="linkColor">
|
||||||
<color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
<systemColor name="secondarySystemGroupedBackgroundColor">
|
<systemColor name="secondarySystemGroupedBackgroundColor">
|
||||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
@@ -3019,13 +3115,13 @@
|
|||||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
<systemColor name="systemBrownColor">
|
<systemColor name="systemBrownColor">
|
||||||
<color red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color red="0.67450980392156867" green="0.49803921568627452" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
<systemColor name="systemGray3Color">
|
<systemColor name="systemGray3Color">
|
||||||
<color red="0.78039215689999997" green="0.78039215689999997" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color red="0.7803921568627451" green="0.7803921568627451" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
<systemColor name="systemTealColor">
|
<systemColor name="systemTealColor">
|
||||||
<color red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color red="0.0" green="0.76470588235294112" blue="0.81568627450980391" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
self.address = host.address;
|
self.address = host.address;
|
||||||
|
|
||||||
NSSet *classes = [NSSet setWithObjects: [NSMutableSet class], nil];
|
NSSet *classes = [NSSet setWithObjects: [NSMutableSet class], [NSString class], nil];
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
self.activeAddressPool = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:host.activeAddressPool error:&error];
|
self.activeAddressPool = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:host.activeAddressPool error:&error];
|
||||||
if(self.activeAddressPool){
|
if(self.activeAddressPool){
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
static int mouseButtonForCursorMove = BUTTON_LEFT;
|
static int mouseButtonForCursorMove = BUTTON_LEFT;
|
||||||
|
|
||||||
@implementation AbsoluteTouchHandler {
|
@implementation AbsoluteTouchHandler {
|
||||||
StreamView* streamView;
|
__weak StreamView* streamView;
|
||||||
|
|
||||||
bool multiTouchesDetected;
|
bool multiTouchesDetected;
|
||||||
bool passthroughGestures;
|
bool passthroughGestures;
|
||||||
@@ -108,7 +108,6 @@ static int mouseButtonForCursorMove = BUTTON_LEFT;
|
|||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
rightButtonClicked = false;
|
rightButtonClicked = false;
|
||||||
|
|
||||||
|
|
||||||
if([UITouchUtil touchesIn:streamView from:event].count>=2){
|
if([UITouchUtil touchesIn:streamView from:event].count>=2){
|
||||||
multiTouchesDetected = true;
|
multiTouchesDetected = true;
|
||||||
[longPressTimer invalidate];
|
[longPressTimer invalidate];
|
||||||
|
|||||||
@@ -135,9 +135,22 @@ import UIKit
|
|||||||
"WIDGETTOOL",
|
"WIDGETTOOL",
|
||||||
"WIDGETPROFILES",
|
"WIDGETPROFILES",
|
||||||
"PROFILES",
|
"PROFILES",
|
||||||
|
"PICKPROFILE",
|
||||||
|
"PICKPRFL",
|
||||||
"SOFTKEYBOARD",
|
"SOFTKEYBOARD",
|
||||||
"ABSTCHDRAG",
|
"ABSTCHDRAG",
|
||||||
"PENCILHOVER"
|
"FOLDER",
|
||||||
|
"PRESSURECURVE",
|
||||||
|
"PENCILHOVER",
|
||||||
|
"BRUSH",
|
||||||
|
"ERASER",
|
||||||
|
"NOSINGLETOUCH"
|
||||||
|
]
|
||||||
|
@objc public static let pencilProButtonCmds: [String] = [
|
||||||
|
"PENCILHOVER",
|
||||||
|
"BRUSH",
|
||||||
|
"ERASER",
|
||||||
|
"NOSINGLETOUCH"
|
||||||
]
|
]
|
||||||
@objc public static let motionControlButtonCmds: [String] = ["GYRO","GYROPAUSE","ACCEL","MOTION"]
|
@objc public static let motionControlButtonCmds: [String] = ["GYRO","GYROPAUSE","ACCEL","MOTION"]
|
||||||
|
|
||||||
@@ -146,6 +159,8 @@ import UIKit
|
|||||||
@objc public static let keyboardButtonMappings: [String: Int16] = [
|
@objc public static let keyboardButtonMappings: [String: Int16] = [
|
||||||
// Windows Key Codes
|
// Windows Key Codes
|
||||||
"NULL": 0xFF,
|
"NULL": 0xFF,
|
||||||
|
"BRUSH": 0xFF,
|
||||||
|
"ERASER": 0xFF,
|
||||||
"CTRL": 0x11, // VK_CONTROL
|
"CTRL": 0x11, // VK_CONTROL
|
||||||
"SHIFT": 0x10, // VK_SHIFT
|
"SHIFT": 0x10, // VK_SHIFT
|
||||||
"ALT": 0x12, // VK_MENU
|
"ALT": 0x12, // VK_MENU
|
||||||
@@ -431,7 +446,8 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extractKeyStrings from keyboardCMDString
|
// extractKeyStrings from keyboardCMDString
|
||||||
@objc public func extractKeyStringsFromComboCommand(from input: String) -> [String]? {
|
@objc public func extractKeyStrings(from keyboardCmd: String) -> [String]? {
|
||||||
|
let keyboardCmd = keyboardCmd.uppercased()
|
||||||
let keys = CommandManager.keyboardButtonMappings.keys.joined(separator: "|")
|
let keys = CommandManager.keyboardButtonMappings.keys.joined(separator: "|")
|
||||||
let pattern = "^(?:(\(keys))(?:\\+(\(keys))*)*)$"
|
let pattern = "^(?:(\(keys))(?:\\+(\(keys))*)*)$"
|
||||||
|
|
||||||
@@ -439,14 +455,14 @@ import UIKit
|
|||||||
print("Failed to create regex")
|
print("Failed to create regex")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
let range = NSRange(location: 0, length: input.utf16.count)
|
let range = NSRange(location: 0, length: keyboardCmd.utf16.count)
|
||||||
guard let match = regex.firstMatch(in: input, options: [], range: range) else {
|
guard let match = regex.firstMatch(in: keyboardCmd, options: [], range: range) else {
|
||||||
print("No match found for input: \(input)")
|
print("No match found for input: \(keyboardCmd)")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// print("Regex matched for input: \(input)")
|
// print("Regex matched for input: \(input)")
|
||||||
|
|
||||||
let matchedString = (input as NSString).substring(with: match.range(at: 0))
|
let matchedString = (keyboardCmd as NSString).substring(with: match.range(at: 0))
|
||||||
let keyStrings = matchedString.split(separator: "+").map { String($0) }
|
let keyStrings = matchedString.split(separator: "+").map { String($0) }
|
||||||
|
|
||||||
guard !keyStrings.isEmpty else {
|
guard !keyStrings.isEmpty else {
|
||||||
@@ -479,7 +495,8 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
//super combo key button strings
|
//super combo key button strings
|
||||||
@objc public func extractSinglCmdStringsFromComboKeys(from input: String) -> [String]? {
|
@objc public func extractCmdStrings(from input: String) -> [String]? {
|
||||||
|
let input = input.uppercased()
|
||||||
let combinedStrings = [CommandManager.keyboardButtonMappings.keys.map { $0 as String },
|
let combinedStrings = [CommandManager.keyboardButtonMappings.keys.map { $0 as String },
|
||||||
CommandManager.oscButtonMappings.keys.map { $0 as String },
|
CommandManager.oscButtonMappings.keys.map { $0 as String },
|
||||||
CommandManager.mouseButtonMappings.keys.map { $0 as String },
|
CommandManager.mouseButtonMappings.keys.map { $0 as String },
|
||||||
@@ -535,7 +552,7 @@ import UIKit
|
|||||||
@objc public func addCommand(_ command: RemoteCommand) -> Bool {
|
@objc public func addCommand(_ command: RemoteCommand) -> Bool {
|
||||||
command.cmdString = command.cmdString.uppercased() // convert all letters to upper case
|
command.cmdString = command.cmdString.uppercased() // convert all letters to upper case
|
||||||
if(command.alias.trimmingCharacters(in: .whitespacesAndNewlines).count == 0) {command.alias = command.cmdString} // copy cmd string as alias when alias is empty
|
if(command.alias.trimmingCharacters(in: .whitespacesAndNewlines).count == 0) {command.alias = command.cmdString} // copy cmd string as alias when alias is empty
|
||||||
let keyStrings = extractKeyStringsFromComboCommand(from: command.cmdString)
|
let keyStrings = extractKeyStrings(from: command.cmdString)
|
||||||
if (keyStrings == nil) {return false} // in case of non-keyboard command strings, return false
|
if (keyStrings == nil) {return false} // in case of non-keyboard command strings, return false
|
||||||
commands.append(command)
|
commands.append(command)
|
||||||
saveCommands()
|
saveCommands()
|
||||||
@@ -581,8 +598,9 @@ import UIKit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public func sendKeyComboCommand(keyboardCmdStrings: [String], delay: TimeInterval = 0.2, index: Int = 0) { // we need a large delay for WAN streaming
|
@objc public func sendKeyComboCommand(keyboardCmdStrings: [String]?, delay: TimeInterval = 0.2, index: Int = 0) { // we need a large delay for WAN streaming
|
||||||
// 如果已处理完所有按键,则开始释放按键
|
// 如果已处理完所有按键,则开始释放按键
|
||||||
|
guard let keyboardCmdStrings = keyboardCmdStrings else { return }
|
||||||
guard index < keyboardCmdStrings.count else {
|
guard index < keyboardCmdStrings.count else {
|
||||||
// 释放按键
|
// 释放按键
|
||||||
for keyStr in keyboardCmdStrings.reversed() { // 从后往前释放按键
|
for keyStr in keyboardCmdStrings.reversed() { // 从后往前释放按键
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
|
|
||||||
NSLock *_controllerStreamLock;
|
NSLock *_controllerStreamLock;
|
||||||
NSMutableDictionary *_voidControllers;
|
NSMutableDictionary *_voidControllers;
|
||||||
id<ControllerSupportDelegate> _delegate;
|
|
||||||
StreamConfiguration* _streamConfig;
|
StreamConfiguration* _streamConfig;
|
||||||
|
__weak id<ControllerSupportDelegate> _delegate;
|
||||||
|
|
||||||
float accumulatedDeltaX;
|
float accumulatedDeltaX;
|
||||||
float accumulatedDeltaY;
|
float accumulatedDeltaY;
|
||||||
@@ -75,8 +75,8 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
VoidController *_oscController;
|
VoidController *_oscController;
|
||||||
NSMutableSet* _activeGCControllers;
|
NSMutableSet* _activeGCControllers;
|
||||||
TemporarySettings* tempSettings;
|
TemporarySettings* tempSettings;
|
||||||
OSCProfilesManager* oscProfileMan;
|
|
||||||
OSCProfile* oscProfile;
|
OSCProfile* oscProfile;
|
||||||
|
OSCProfilesManager* oscProfileMan;
|
||||||
|
|
||||||
#define EMULATING_SELECT 0x1
|
#define EMULATING_SELECT 0x1
|
||||||
#define EMULATING_SPECIAL 0x2
|
#define EMULATING_SPECIAL 0x2
|
||||||
@@ -98,7 +98,7 @@ static const double MOUSE_SPEED_DIVISOR = 1.25;
|
|||||||
bool _controllerGyroSwitchHoldPressed;
|
bool _controllerGyroSwitchHoldPressed;
|
||||||
ControllerGyroSwitchMode _gyroSwitchMode;
|
ControllerGyroSwitchMode _gyroSwitchMode;
|
||||||
|
|
||||||
MotionHandler* motionHandler;
|
__weak MotionHandler* motionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UPDATE_BUTTON_FLAG(controller, flag, pressed)
|
// UPDATE_BUTTON_FLAG(controller, flag, pressed)
|
||||||
@@ -1723,6 +1723,7 @@ double rc_expo(double x, double expo) {
|
|||||||
_oscController.playerIndex = 0;
|
_oscController.playerIndex = 0;
|
||||||
|
|
||||||
oscProfile = [oscProfileMan getSelectedProfile];
|
oscProfile = [oscProfileMan getSelectedProfile];
|
||||||
|
motionHandler = [MotionHandler sharedWithProfile:oscProfile];
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
tempSettings = [dataMan getSettings];
|
tempSettings = [dataMan getSettings];
|
||||||
|
|
||||||
@@ -1965,7 +1966,6 @@ double rc_expo(double x, double expo) {
|
|||||||
_controllerMouseEnabledFlag = false;
|
_controllerMouseEnabledFlag = false;
|
||||||
|
|
||||||
_gyroEnabledFlag = false;
|
_gyroEnabledFlag = false;
|
||||||
motionHandler = [MotionHandler sharedInstance];
|
|
||||||
oscProfileMan = [OSCProfilesManager sharedManager:CGRectZero];
|
oscProfileMan = [OSCProfilesManager sharedManager:CGRectZero];
|
||||||
|
|
||||||
[self updateCommonConfig:streamConfig];
|
[self updateCommonConfig:streamConfig];
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property UIView* _view;
|
@property UIView* _view;
|
||||||
@property NSMutableArray *layoutChanges;
|
@property NSMutableArray *layoutChanges;
|
||||||
@property CALayer *layerBeingDragged;
|
@property CALayer *layerBeingDragged;
|
||||||
@property UIViewController *layoutToolVC;
|
@property (nonatomic, weak) UIViewController *layoutToolVC;
|
||||||
|
|
||||||
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport
|
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport
|
||||||
streamConfig:(StreamConfiguration*)streamConfig oscLevel:(int)oscLevel;
|
streamConfig:(StreamConfiguration*)streamConfig oscLevel:(int)oscLevel;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
layoutChanges = [[NSMutableArray alloc] init]; // will contain OSC button layout changes the user has made for this profile
|
layoutChanges = [[NSMutableArray alloc] init]; // will contain OSC button layout changes the user has made for this profile
|
||||||
|
|
||||||
[self drawButtons];
|
// [self drawButtons];
|
||||||
[self drawGuidelines]; // add the blue guidelines that appear when button is being tapped and dragged
|
[self drawGuidelines]; // add the blue guidelines that appear when button is being tapped and dragged
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -55,27 +55,31 @@
|
|||||||
/**
|
/**
|
||||||
* This method overrides the superclass's drawButtons method. The purpose of this method is to create a dPad parent layer, and add the four dPad buttons to it so that the user can drag the entire dPad around, directional buttons and all, as one unit as is the expected behavior. Note that we do not want the four dPad buttons to be child layers of a CALayer parent layer on the game stream view since the touch logic implemented for the four dPad buttons on the game stream view is written assuming the dPad buttons are not children of another parent CALayer
|
* This method overrides the superclass's drawButtons method. The purpose of this method is to create a dPad parent layer, and add the four dPad buttons to it so that the user can drag the entire dPad around, directional buttons and all, as one unit as is the expected behavior. Note that we do not want the four dPad buttons to be child layers of a CALayer parent layer on the game stream view since the touch logic implemented for the four dPad buttons on the game stream view is written assuming the dPad buttons are not children of another parent CALayer
|
||||||
*/
|
*/
|
||||||
- (void) drawButtons {
|
- (void) drawButtons:(OSCProfile* )profile {
|
||||||
[super setDPadCenter]; // Set custom position for D-Pad here
|
// [super regenLayerPool];
|
||||||
[super setAnalogStickPositions]; // Set custom position for analog sticks here
|
[super setDPadCenter:profile]; // Set custom position for D-Pad here
|
||||||
|
[super setAnalogStickPositions:profile]; // Set custom position for analog sticks here
|
||||||
[super drawBumpers];
|
[super drawBumpers];
|
||||||
[super drawButtons];
|
[super drawButtons:profile];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
UIImage* downButtonImage = [UIImage imageNamed:@"DownButton"];
|
UIImage* downButtonImage = [UIImage imageNamed:@"DownButton"];
|
||||||
UIImage* rightButtonImage = [UIImage imageNamed:@"RightButton"];
|
UIImage* rightButtonImage = [UIImage imageNamed:@"RightButton"];
|
||||||
UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
||||||
UIImage* leftButtonImage = [UIImage imageNamed:@"LeftButton"];
|
UIImage* leftButtonImage = [UIImage imageNamed:@"LeftButton"];
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// create dPad background layer
|
// create dPad background layer
|
||||||
self._dPadBackground = [CALayer layer];
|
if([self.OSCButtonLayerPool containsObject:self._upButton]){
|
||||||
|
[self.OSCButtonLayerPool addObject:self._dPadBackground];
|
||||||
self._dPadBackground.name = @"dPad";
|
self._dPadBackground.name = @"dPad";
|
||||||
self._dPadBackground.frame = CGRectMake(self.D_PAD_CENTER_X,
|
self._dPadBackground.frame = CGRectMake(self.D_PAD_CENTER_X,
|
||||||
self.D_PAD_CENTER_Y,
|
self.D_PAD_CENTER_Y,
|
||||||
self._leftButton.frame.size.width * 2 + BUTTON_DIST,
|
self._leftButton.frame.size.width * 2 + BUTTON_DIST,
|
||||||
self._leftButton.frame.size.width * 2 + BUTTON_DIST);
|
self._leftButton.frame.size.width * 2 + BUTTON_DIST);
|
||||||
self._dPadBackground.position = CGPointMake(self.D_PAD_CENTER_X, self.D_PAD_CENTER_Y); // since dPadBackground's dimensions have change after settings its width and height you need to reset its position again here
|
self._dPadBackground.position = CGPointMake(self.D_PAD_CENTER_X, self.D_PAD_CENTER_Y); // since dPadBackground's dimensions have change after settings its width and height you need to reset its position again here
|
||||||
[self.OSCButtonLayers addObject:self._dPadBackground];
|
[self.OSCButtonLayerPool addObject:self._dPadBackground];
|
||||||
[_view.layer addSublayer:self._dPadBackground];
|
[_view.layer addSublayer:self._dPadBackground];
|
||||||
|
|
||||||
// add dPad buttons to parent layer
|
// add dPad buttons to parent layer
|
||||||
@@ -83,6 +87,12 @@
|
|||||||
[self._dPadBackground addSublayer:self._rightButton];
|
[self._dPadBackground addSublayer:self._rightButton];
|
||||||
[self._dPadBackground addSublayer:self._upButton];
|
[self._dPadBackground addSublayer:self._upButton];
|
||||||
[self._dPadBackground addSublayer:self._leftButton];
|
[self._dPadBackground addSublayer:self._leftButton];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"layer name ttttttttttt============================");
|
||||||
|
for(CALayer* buttonLayer in self.OSCButtonLayerPool){
|
||||||
|
NSLog(@"layer name %@", buttonLayer.name);
|
||||||
|
}
|
||||||
|
|
||||||
[self resizeControllerLayerWith:self._dPadBackground and:_dPadSizeFactor];
|
[self resizeControllerLayerWith:self._dPadBackground and:_dPadSizeFactor];
|
||||||
|
|
||||||
@@ -128,7 +138,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
horizontalGuideline.backgroundColor = [UIColor blueColor]; // change horizontal guideline back to blue if it doesn't line up with one of the on screen buttons
|
horizontalGuideline.backgroundColor = [UIColor blueColor]; // change horizontal guideline back to blue if it doesn't line up with one of the on screen buttons
|
||||||
for (CALayer *button in self.OSCButtonLayers) { // horizontal guideline position check
|
for (CALayer *button in self.OSCButtonLayerPool) { // horizontal guideline position check
|
||||||
if ((layerBeingDragged != button) && !button.isHidden) {
|
if ((layerBeingDragged != button) && !button.isHidden) {
|
||||||
if ((horizontalGuideline.center.y < button.position.y + 1) &&
|
if ((horizontalGuideline.center.y < button.position.y + 1) &&
|
||||||
(horizontalGuideline.center.y > button.position.y - 1)) {
|
(horizontalGuideline.center.y > button.position.y - 1)) {
|
||||||
@@ -147,7 +157,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
verticalGuideline.backgroundColor = [UIColor blueColor]; // change vertical guideline back to blue if it doesn't line up with one of the on screen buttons
|
verticalGuideline.backgroundColor = [UIColor blueColor]; // change vertical guideline back to blue if it doesn't line up with one of the on screen buttons
|
||||||
for (CALayer *button in self.OSCButtonLayers) { // vertical guideline position check
|
for (CALayer *button in self.OSCButtonLayerPool) { // vertical guideline position check
|
||||||
if ((layerBeingDragged != button) && !button.isHidden) {
|
if ((layerBeingDragged != button) && !button.isHidden) {
|
||||||
if ((verticalGuideline.center.x < button.position.x + 1) &&
|
if ((verticalGuideline.center.x < button.position.x + 1) &&
|
||||||
(verticalGuideline.center.x > button.position.x - 1)) {
|
(verticalGuideline.center.x > button.position.x - 1)) {
|
||||||
@@ -177,7 +187,7 @@
|
|||||||
-Change vertical guideline color to yellow if its x-position is almost equal to that of one of the buttons on screen.
|
-Change vertical guideline color to yellow if its x-position is almost equal to that of one of the buttons on screen.
|
||||||
*/
|
*/
|
||||||
horizontalGuideline.backgroundColor = [UIColor blueColor]; // change horizontal guideline back to blue if it doesn't line up with one of the on screen buttons
|
horizontalGuideline.backgroundColor = [UIColor blueColor]; // change horizontal guideline back to blue if it doesn't line up with one of the on screen buttons
|
||||||
for (CALayer *button in self.OSCButtonLayers) { // horizontal guideline position check
|
for (CALayer *button in self.OSCButtonLayerPool) { // horizontal guideline position check
|
||||||
if ((layerBeingDragged != button) && !button.isHidden) {
|
if ((layerBeingDragged != button) && !button.isHidden) {
|
||||||
if ((horizontalGuideline.center.y < button.position.y + 1) &&
|
if ((horizontalGuideline.center.y < button.position.y + 1) &&
|
||||||
(horizontalGuideline.center.y > button.position.y - 1)) {
|
(horizontalGuideline.center.y > button.position.y - 1)) {
|
||||||
@@ -196,7 +206,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
verticalGuideline.backgroundColor = [UIColor blueColor]; // change vertical guideline back to blue if it doesn't line up with one of the on screen buttons
|
verticalGuideline.backgroundColor = [UIColor blueColor]; // change vertical guideline back to blue if it doesn't line up with one of the on screen buttons
|
||||||
for (CALayer *button in self.OSCButtonLayers) { // vertical guideline position check
|
for (CALayer *button in self.OSCButtonLayerPool) { // vertical guideline position check
|
||||||
if ((layerBeingDragged != button) && !button.isHidden) {
|
if ((layerBeingDragged != button) && !button.isHidden) {
|
||||||
if ((verticalGuideline.center.x < button.position.x + 1) &&
|
if ((verticalGuideline.center.x < button.position.x + 1) &&
|
||||||
(verticalGuideline.center.x > button.position.x - 1)) {
|
(verticalGuideline.center.x > button.position.x - 1)) {
|
||||||
@@ -233,7 +243,7 @@
|
|||||||
|
|
||||||
/* returns reference to button layer object given the button's name*/
|
/* returns reference to button layer object given the button's name*/
|
||||||
- (CALayer*)controllerLayerFromName: (NSString*)name {
|
- (CALayer*)controllerLayerFromName: (NSString*)name {
|
||||||
for (CALayer *buttonLayer in self.OSCButtonLayers) {
|
for (CALayer *buttonLayer in self.OSCButtonLayerPool) {
|
||||||
|
|
||||||
if ([buttonLayer.name isEqualToString:name]) {
|
if ([buttonLayer.name isEqualToString:name]) {
|
||||||
return buttonLayer;
|
return buttonLayer;
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ typedef NS_ENUM(NSInteger, MapGyroTo) {
|
|||||||
@property (nonatomic, assign) int controllerGyroSwitchToggle;
|
@property (nonatomic, assign) int controllerGyroSwitchToggle;
|
||||||
@property NSArray<NSNumber *> *pressureCurvePoints;
|
@property NSArray<NSNumber *> *pressureCurvePoints;
|
||||||
@property (nonatomic, assign) bool pressureCurveEnabled;
|
@property (nonatomic, assign) bool pressureCurveEnabled;
|
||||||
|
@property (nonatomic, assign) bool doubleTapShorcutEnabled;
|
||||||
|
@property NSString *brushShortcut;
|
||||||
|
@property NSString *eraserShortcut;
|
||||||
|
@property (nonatomic, assign) bool pencilPausesNativeTouch;
|
||||||
|
|
||||||
|
|
||||||
- (id) initWithName:(NSString*)name buttonStates:(NSMutableArray*)buttonStates isSelected:(BOOL)isSelected;
|
- (id) initWithName:(NSString*)name buttonStates:(NSMutableArray*)buttonStates isSelected:(BOOL)isSelected;
|
||||||
|
|
||||||
|
|||||||
@@ -51,11 +51,20 @@
|
|||||||
[encoder encodeInt:self.controllerGyroSwitchToggle forKey:@"controllerGyroSwitchToggle"];
|
[encoder encodeInt:self.controllerGyroSwitchToggle forKey:@"controllerGyroSwitchToggle"];
|
||||||
[encoder encodeObject:self.pressureCurvePoints forKey:@"pressureCurvePoints"];
|
[encoder encodeObject:self.pressureCurvePoints forKey:@"pressureCurvePoints"];
|
||||||
[encoder encodeBool:self.pressureCurveEnabled forKey:@"pressureCurveEnabled"];
|
[encoder encodeBool:self.pressureCurveEnabled forKey:@"pressureCurveEnabled"];
|
||||||
|
[encoder encodeBool:self.doubleTapShorcutEnabled forKey:@"doubleTapShorcutEnabled"];
|
||||||
|
[encoder encodeObject:self.brushShortcut forKey:@"brushShortcut"];
|
||||||
|
[encoder encodeObject:self.eraserShortcut forKey:@"eraserShortcut"];
|
||||||
|
[encoder encodeBool:self.pencilPausesNativeTouch forKey:@"pencilPausesNativeTouch"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithCoder:(NSCoder*)decoder {
|
- (id) initWithCoder:(NSCoder*)decoder {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
self.name = [decoder decodeObjectForKey:@"name"];
|
self.name =
|
||||||
|
[decoder decodeObjectOfClasses:
|
||||||
|
[NSSet setWithObjects:
|
||||||
|
[NSString class],
|
||||||
|
nil]
|
||||||
|
forKey:@"name"];
|
||||||
self.buttonStatesEncoded =
|
self.buttonStatesEncoded =
|
||||||
[decoder decodeObjectOfClasses:
|
[decoder decodeObjectOfClasses:
|
||||||
[NSSet setWithObjects:
|
[NSSet setWithObjects:
|
||||||
@@ -92,6 +101,27 @@
|
|||||||
forKey:@"pressureCurvePoints"]
|
forKey:@"pressureCurvePoints"]
|
||||||
: @[@0.0, @0.0, @1.0, @1.0];
|
: @[@0.0, @0.0, @1.0, @1.0];
|
||||||
self.pressureCurveEnabled = [decoder containsValueForKey:@"pressureCurveEnabled"] ? [decoder decodeBoolForKey:@"pressureCurveEnabled"] : false;
|
self.pressureCurveEnabled = [decoder containsValueForKey:@"pressureCurveEnabled"] ? [decoder decodeBoolForKey:@"pressureCurveEnabled"] : false;
|
||||||
|
|
||||||
|
self.doubleTapShorcutEnabled = [decoder containsValueForKey:@"doubleTapShorcutEnabled"] ? [decoder decodeBoolForKey:@"doubleTapShorcutEnabled"] : false;
|
||||||
|
self.brushShortcut =
|
||||||
|
[decoder containsValueForKey:@"brushShortcut"]
|
||||||
|
? [decoder decodeObjectOfClasses:
|
||||||
|
[NSSet setWithObjects:
|
||||||
|
[NSString class],
|
||||||
|
nil]
|
||||||
|
forKey:@"brushShortcut"]
|
||||||
|
: @"";
|
||||||
|
|
||||||
|
self.eraserShortcut =
|
||||||
|
[decoder containsValueForKey:@"eraserShortcut"]
|
||||||
|
? [decoder decodeObjectOfClasses:
|
||||||
|
[NSSet setWithObjects:
|
||||||
|
[NSString class],
|
||||||
|
nil]
|
||||||
|
forKey:@"eraserShortcut"]
|
||||||
|
: @"";
|
||||||
|
|
||||||
|
self.pencilPausesNativeTouch = [decoder containsValueForKey:@"pencilPausesNativeTouch"] ? [decoder decodeBoolForKey:@"pencilPausesNativeTouch"] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -121,6 +151,10 @@
|
|||||||
copy.controllerGyroSwitchToggle = self.controllerGyroSwitchToggle;
|
copy.controllerGyroSwitchToggle = self.controllerGyroSwitchToggle;
|
||||||
copy.pressureCurvePoints = [[NSMutableArray alloc] initWithArray:self.pressureCurvePoints copyItems:YES];
|
copy.pressureCurvePoints = [[NSMutableArray alloc] initWithArray:self.pressureCurvePoints copyItems:YES];
|
||||||
copy.pressureCurveEnabled = self.pressureCurveEnabled;
|
copy.pressureCurveEnabled = self.pressureCurveEnabled;
|
||||||
|
copy.doubleTapShorcutEnabled = self.doubleTapShorcutEnabled;
|
||||||
|
copy.brushShortcut = [self.brushShortcut mutableCopy]; // NSString → NSMutableString
|
||||||
|
copy.eraserShortcut = [self.eraserShortcut mutableCopy]; // NSString → NSMutableString
|
||||||
|
copy.pencilPausesNativeTouch = self.pencilPausesNativeTouch;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,7 +207,6 @@ static CGRect layoutViewBounds;
|
|||||||
#pragma mark - Getters
|
#pragma mark - Getters
|
||||||
|
|
||||||
- (NSMutableArray *) getAllProfiles {
|
- (NSMutableArray *) getAllProfiles {
|
||||||
|
|
||||||
NSData *profilesArrayEncoded = [[NSUserDefaults standardUserDefaults] objectForKey: @"OSCProfiles"]; // Get the encoded array of encoded OSC profiles from persistent storage
|
NSData *profilesArrayEncoded = [[NSUserDefaults standardUserDefaults] objectForKey: @"OSCProfiles"]; // Get the encoded array of encoded OSC profiles from persistent storage
|
||||||
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
|
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
|
||||||
|
|
||||||
@@ -226,6 +225,7 @@ static CGRect layoutViewBounds;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (OSCProfile *) getSelectedProfile {
|
- (OSCProfile *) getSelectedProfile {
|
||||||
|
NSLog(@"getAllProfiles test %f", CACurrentMediaTime());
|
||||||
NSMutableArray *profiles = [self getAllProfiles];
|
NSMutableArray *profiles = [self getAllProfiles];
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
|
|
||||||
@@ -363,6 +363,8 @@ static CGRect layoutViewBounds;
|
|||||||
|
|
||||||
// save on-screen game controller buttons & sticks as buttonstate:
|
// save on-screen game controller buttons & sticks as buttonstate:
|
||||||
for (CALayer *oscButtonLayer in oscButtonLayers) {
|
for (CALayer *oscButtonLayer in oscButtonLayers) {
|
||||||
|
if(oscButtonLayer.isHidden) continue;
|
||||||
|
|
||||||
CGPoint normalizedPosition = [self normalizeWidgetPosition:oscButtonLayer.position];
|
CGPoint normalizedPosition = [self normalizeWidgetPosition:oscButtonLayer.position];
|
||||||
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:LegacyOnScreenControls andPosition:normalizedPosition];
|
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:LegacyOnScreenControls andPosition:normalizedPosition];
|
||||||
// add hidden attr here
|
// add hidden attr here
|
||||||
@@ -390,7 +392,7 @@ static CGRect layoutViewBounds;
|
|||||||
CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.center];
|
CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.center];
|
||||||
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:normalizedPosition];
|
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:normalizedPosition];
|
||||||
buttonState.alias = widgetView.widgetLabel;
|
buttonState.alias = widgetView.widgetLabel;
|
||||||
buttonState.identifier = widgetView.identifier;
|
buttonState.sequence = widgetView.sequence;
|
||||||
buttonState.widthFactor = [self normalizeSizeWidthFactorWith:widgetView];
|
buttonState.widthFactor = [self normalizeSizeWidthFactorWith:widgetView];
|
||||||
buttonState.heightFactor = [self normalizeSizeHeightFactorWith:widgetView];
|
buttonState.heightFactor = [self normalizeSizeHeightFactorWith:widgetView];
|
||||||
buttonState.componentSizeFactor = [self normalizeComponentSizeFactorWith:widgetView];
|
buttonState.componentSizeFactor = [self normalizeComponentSizeFactorWith:widgetView];
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@property NSString *name;
|
@property NSString *name;
|
||||||
@property NSString *alias;
|
@property NSString *alias;
|
||||||
@property NSString *identifier;
|
@property (nonatomic, assign) BOOL folded;
|
||||||
|
@property (nonatomic, assign) uint8_t revealMode;
|
||||||
|
@property (nonatomic, assign) int16_t sequence;
|
||||||
|
@property NSMutableSet *sequenceSet;
|
||||||
@property CGPoint position;
|
@property CGPoint position;
|
||||||
@property (nonatomic, assign) BOOL isHidden;
|
@property (nonatomic, assign) BOOL isHidden;
|
||||||
@property (nonatomic, assign) uint8_t buttonMode;
|
@property (nonatomic, assign) uint8_t buttonMode;
|
||||||
@@ -86,6 +89,11 @@ typedef NS_ENUM(NSInteger, ButtonMode) {
|
|||||||
movable
|
movable
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, RevealMode) {
|
||||||
|
coexist,
|
||||||
|
exclusive
|
||||||
|
};
|
||||||
|
|
||||||
- (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position;
|
- (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position;
|
||||||
|
|
||||||
+ (BOOL) supportsSecureCoding;
|
+ (BOOL) supportsSecureCoding;
|
||||||
|
|||||||
@@ -32,7 +32,10 @@
|
|||||||
|
|
||||||
- (void) encodeWithCoder:(NSCoder*)encoder {
|
- (void) encodeWithCoder:(NSCoder*)encoder {
|
||||||
[encoder encodeObject:self.name forKey:@"name"];
|
[encoder encodeObject:self.name forKey:@"name"];
|
||||||
[encoder encodeObject:([self.identifier isEqualToString:@""]||!self.identifier) ? [UUIDHelper newUUID] : self.identifier forKey:@"identifier"];
|
[encoder encodeBool:self.folded forKey:@"folded"];
|
||||||
|
[encoder encodeInt32:self.revealMode forKey:@"revealMode"];
|
||||||
|
[encoder encodeInt32:self.sequence forKey:@"sequence"];
|
||||||
|
[encoder encodeObject:self.sequenceSet forKey:@"sequenceSet"];
|
||||||
[encoder encodeObject:self.alias forKey:@"alias"];
|
[encoder encodeObject:self.alias forKey:@"alias"];
|
||||||
[encoder encodeInt:self.widgetType forKey:@"buttonType"]; // keep original key
|
[encoder encodeInt:self.widgetType forKey:@"buttonType"]; // keep original key
|
||||||
[encoder encodeInt:self.sizeReference forKey:@"sizeReference"];
|
[encoder encodeInt:self.sizeReference forKey:@"sizeReference"];
|
||||||
@@ -69,7 +72,10 @@
|
|||||||
- (id) initWithCoder:(NSCoder*)decoder {
|
- (id) initWithCoder:(NSCoder*)decoder {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
self.name = [decoder decodeObjectForKey:@"name"];
|
self.name = [decoder decodeObjectForKey:@"name"];
|
||||||
self.identifier = [decoder containsValueForKey:@"identifier"] ? [decoder decodeObjectForKey:@"identifier"] : [UUIDHelper newUUID];
|
self.folded = [decoder containsValueForKey:@"folded"] ? [decoder decodeBoolForKey:@"folded"] : false;
|
||||||
|
self.revealMode = [decoder containsValueForKey:@"revealMode"] ? [decoder decodeInt32ForKey:@"revealMode"] : exclusive;
|
||||||
|
self.sequence = [decoder containsValueForKey:@"sequence"] ? [decoder decodeInt32ForKey:@"sequence"] : -1;
|
||||||
|
self.sequenceSet = [decoder containsValueForKey:@"sequenceSet"] ? [decoder decodeObjectForKey:@"sequenceSet"] : [NSSet set];
|
||||||
self.alias = [decoder decodeObjectForKey:@"alias"];
|
self.alias = [decoder decodeObjectForKey:@"alias"];
|
||||||
self.widgetType = [decoder decodeIntForKey:@"buttonType"];
|
self.widgetType = [decoder decodeIntForKey:@"buttonType"];
|
||||||
self.sizeReference = [decoder containsValueForKey:@"sizeReference"] ? [decoder decodeIntForKey:@"sizeReference"] : longSide;
|
self.sizeReference = [decoder containsValueForKey:@"sizeReference"] ? [decoder decodeIntForKey:@"sizeReference"] : longSide;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import CoreMotion
|
|||||||
func gyroMixInputStarted() -> Bool
|
func gyroMixInputStarted() -> Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc class MotionHandler: NSObject, OscInstanceReceiverDelegate, OnScreenWidgetStickMixedInputDelegate{
|
@objc class MotionHandler: NSObject, OnScreenWidgetStickMixedInputDelegate{
|
||||||
public func mixOnScreenRightStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
public func mixOnScreenRightStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
||||||
rightStickTouchInputX = x
|
rightStickTouchInputX = x
|
||||||
rightStickTouchInputY = y
|
rightStickTouchInputY = y
|
||||||
@@ -28,48 +28,46 @@ import CoreMotion
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc public func mixPhysicalRightStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
@objc public func mixPhysicalRightStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
||||||
rightStickPhysicalInputX = oscProfile.synthesizePhysicalStick ? x : 0
|
rightStickPhysicalInputX = synthesizePhysicalStick ? x : 0
|
||||||
rightStickPhysicalInputY = oscProfile.synthesizePhysicalStick ? y : 0
|
rightStickPhysicalInputY = synthesizePhysicalStick ? y : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public func mixPhysicalLeftStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
@objc public func mixPhysicalLeftStickAndGyroInput(x: CGFloat, y: CGFloat) {
|
||||||
// rollIntegral = 0
|
// rollIntegral = 0
|
||||||
leftStickPhysicalInputX = oscProfile.synthesizePhysicalStick ? x : 0
|
leftStickPhysicalInputX = synthesizePhysicalStick ? x : 0
|
||||||
leftStickPhysicalInputY = oscProfile.synthesizePhysicalStick ? y : 0
|
leftStickPhysicalInputY = synthesizePhysicalStick ? y : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public func gyroMixInputStarted() -> Bool {
|
public func gyroMixInputStarted() -> Bool {
|
||||||
return gyroIsWorking
|
return gyroIsWorking
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOnScreenControlsInstance(_ sender: Any!) {
|
private static let sharedInstance = MotionHandler()
|
||||||
if let controls = sender as? OnScreenControls {
|
|
||||||
self.onScreenControls = controls
|
|
||||||
print("ClassA received OnScreenControls instance: \(controls)")
|
|
||||||
} else {
|
|
||||||
print("ClassA received an unknown sender")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static let shared = MotionHandler()
|
@objc class func shared(profile: OSCProfile?) -> MotionHandler {
|
||||||
|
let sharedInstance = MotionHandler.sharedInstance
|
||||||
@objc class func sharedInstance() -> MotionHandler {
|
guard let profile = profile else { return sharedInstance }
|
||||||
let sharedInstance = MotionHandler.shared
|
sharedInstance.mapGyroTo = profile.mapGyroTo
|
||||||
sharedInstance.oscProfile = sharedInstance.oscProfileMan.getSelectedProfile()
|
sharedInstance.synthesizePhysicalStick = profile.synthesizePhysicalStick
|
||||||
sharedInstance.sensitvityYaw = sharedInstance.oscProfile.gyroSensitivityYaw
|
sharedInstance.rollToLeftStick = profile.rollToLeftStick
|
||||||
sharedInstance.sensitvityPitch = sharedInstance.oscProfile.gyroSensitivityPitch
|
sharedInstance.yawPitchToRightStick = profile.yawPitchToRightStick
|
||||||
sharedInstance.sensitvityRoll = sharedInstance.oscProfile.gyroSensitivityRoll
|
sharedInstance.sensitvityYaw = profile.gyroSensitivityYaw
|
||||||
sharedInstance.gyroToStickMinOffset = sharedInstance.oscProfile.gyroToStickMinOffset
|
sharedInstance.sensitvityPitch = profile.gyroSensitivityPitch
|
||||||
|
sharedInstance.sensitvityRoll = profile.gyroSensitivityRoll
|
||||||
|
sharedInstance.gyroToStickMinOffset = profile.gyroToStickMinOffset
|
||||||
|
sharedInstance.onScreenControls = OnScreenControls.shared()
|
||||||
return sharedInstance
|
return sharedInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
private var oscProfileMan: OSCProfilesManager
|
|
||||||
private var oscProfile: OSCProfile
|
|
||||||
|
|
||||||
@objc public var gyroControlStarted: Bool = false
|
@objc public var gyroControlStarted: Bool = false
|
||||||
private var gyroIsWorking: Bool = false
|
private var gyroIsWorking: Bool = false
|
||||||
private var accelControlStarted: Bool = false
|
private var accelControlStarted: Bool = false
|
||||||
private let motionManager = CMMotionManager()
|
private let motionManager = CMMotionManager()
|
||||||
|
|
||||||
|
private var synthesizePhysicalStick:Bool = false
|
||||||
|
private var mapGyroTo:MapGyroTo = .mapGyroToControllerStick
|
||||||
|
private var rollToLeftStick:Bool = false
|
||||||
|
private var yawPitchToRightStick:Bool = false
|
||||||
public var sensitvityYaw:CGFloat = 1.0
|
public var sensitvityYaw:CGFloat = 1.0
|
||||||
public var sensitvityPitch:CGFloat = 1.0
|
public var sensitvityPitch:CGFloat = 1.0
|
||||||
public var sensitvityRoll:CGFloat = 1.0
|
public var sensitvityRoll:CGFloat = 1.0
|
||||||
@@ -82,7 +80,7 @@ import CoreMotion
|
|||||||
public var gyroStarter:Any?
|
public var gyroStarter:Any?
|
||||||
private var windowScene: Any?
|
private var windowScene: Any?
|
||||||
|
|
||||||
@objc public var onScreenControls: OnScreenControls = OnScreenControls.init()
|
@objc public var onScreenControls: OnScreenControls?
|
||||||
public let stickMaxOffset: CGFloat = 0x7FFE
|
public let stickMaxOffset: CGFloat = 0x7FFE
|
||||||
private var stickInputScale: CGFloat = 35
|
private var stickInputScale: CGFloat = 35
|
||||||
|
|
||||||
@@ -124,8 +122,7 @@ import CoreMotion
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc public override init() {
|
@objc public override init() {
|
||||||
self.oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
self.oscProfile = oscProfileMan.getSelectedProfile()
|
|
||||||
super.init()
|
super.init()
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
|
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
|
||||||
@@ -295,14 +292,16 @@ import CoreMotion
|
|||||||
|
|
||||||
gyroIsWorking = true
|
gyroIsWorking = true
|
||||||
|
|
||||||
if oscProfile.mapGyroTo == MapGyroTo.mapGyroToMouse {
|
if mapGyroTo == MapGyroTo.mapGyroToMouse {
|
||||||
yaw = yawSource*sensitvityYaw*widgetYawFactor*30
|
yaw = yawSource*sensitvityYaw*widgetYawFactor*30
|
||||||
pitch = pitchSource*sensitvityPitch*widgetPitchFactor*30
|
pitch = pitchSource*sensitvityPitch*widgetPitchFactor*30
|
||||||
LiSendMouseMoveEvent(Int16(yaw),Int16(pitch))
|
LiSendMouseMoveEvent(Int16(yaw),Int16(pitch))
|
||||||
}
|
}
|
||||||
|
|
||||||
if oscProfile.mapGyroTo == MapGyroTo.mapGyroToControllerStick {
|
//guard let onScreenControls = onScreenControls else { return }
|
||||||
if oscProfile.yawPitchToRightStick {
|
|
||||||
|
if mapGyroTo == MapGyroTo.mapGyroToControllerStick {
|
||||||
|
if yawPitchToRightStick {
|
||||||
gyroToStickOffset.dx = gyroInputToStickInput(input:yawSource*sensitvityYaw*widgetYawFactor*10)
|
gyroToStickOffset.dx = gyroInputToStickInput(input:yawSource*sensitvityYaw*widgetYawFactor*10)
|
||||||
yaw = rightStickTouchInputX + rightStickPhysicalInputX + gyroToStickOffset.dx
|
yaw = rightStickTouchInputX + rightStickPhysicalInputX + gyroToStickOffset.dx
|
||||||
yaw = self.clampStickInput(input: yaw)
|
yaw = self.clampStickInput(input: yaw)
|
||||||
@@ -313,9 +312,9 @@ import CoreMotion
|
|||||||
|
|
||||||
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: yaw, dy: pitch), minOffset: gyroToStickMinOffset)
|
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: yaw, dy: pitch), minOffset: gyroToStickMinOffset)
|
||||||
|
|
||||||
self.onScreenControls.sendRightStickTouchPadEvent(offsetVector.dx, offsetVector.dy)
|
onScreenControls?.sendRightStickTouchPadEvent(offsetVector.dx, offsetVector.dy)
|
||||||
}
|
}
|
||||||
if oscProfile.rollToLeftStick {
|
if rollToLeftStick {
|
||||||
roll = gyroInputToStickInput(input:rollSource*sensitvityRoll*widgetRollFactor*0.2)
|
roll = gyroInputToStickInput(input:rollSource*sensitvityRoll*widgetRollFactor*0.2)
|
||||||
rollIntegral = rollIntegral + roll
|
rollIntegral = rollIntegral + roll
|
||||||
|
|
||||||
@@ -324,24 +323,26 @@ import CoreMotion
|
|||||||
|
|
||||||
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: mixedLeftStickOffsetX, dy: mixedLeftStickOffsetY), minOffset: gyroToStickMinOffset)
|
let offsetVector = ControllerUtil.compensated(offsetVector: CGVector(dx: mixedLeftStickOffsetX, dy: mixedLeftStickOffsetY), minOffset: gyroToStickMinOffset)
|
||||||
|
|
||||||
self.onScreenControls.sendLeftStickTouchPadEvent(offsetVector.dx, offsetVector.dy)
|
onScreenControls?.sendLeftStickTouchPadEvent(offsetVector.dx, offsetVector.dy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func clearGyroInput(interruptNonGyroInput:Bool, resetLeftStick:Bool=false){
|
private func clearGyroInput(interruptNonGyroInput:Bool, resetLeftStick:Bool=false){
|
||||||
if oscProfile.yawPitchToRightStick{
|
// guard let onScreenControls = onScreenControls else { return }
|
||||||
self.onScreenControls.sendRightStickTouchPadEvent(rightStickPhysicalInputX+rightStickTouchInputX-yawBias, rightStickPhysicalInputY+rightStickTouchInputY-pitchBias)
|
|
||||||
|
if yawPitchToRightStick{
|
||||||
|
onScreenControls?.sendRightStickTouchPadEvent(rightStickPhysicalInputX+rightStickTouchInputX-yawBias, rightStickPhysicalInputY+rightStickTouchInputY-pitchBias)
|
||||||
}
|
}
|
||||||
if oscProfile.rollToLeftStick{
|
if rollToLeftStick{
|
||||||
if resetLeftStick {
|
if resetLeftStick {
|
||||||
rollIntegral = 0
|
rollIntegral = 0
|
||||||
self.onScreenControls.sendLeftStickTouchPadEvent(leftStickPhysicalInputX+leftStickTouchInputX-rollBias,leftStickPhysicalInputY+leftStickTouchInputY)
|
onScreenControls?.sendLeftStickTouchPadEvent(leftStickPhysicalInputX+leftStickTouchInputX-rollBias,leftStickPhysicalInputY+leftStickTouchInputY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(interruptNonGyroInput){
|
if(interruptNonGyroInput){
|
||||||
self.onScreenControls.clearLeftStickTouchPadFlag()
|
onScreenControls?.clearLeftStickTouchPadFlag()
|
||||||
self.onScreenControls.clearRightStickTouchPadFlag()
|
onScreenControls?.clearRightStickTouchPadFlag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, assign) NSMutableSet<UITouch *>* touchesCapturedByOnScreenButtons;
|
@property (nonatomic, assign) NSMutableSet<UITouch *>* touchesCapturedByOnScreenButtons;
|
||||||
|
|
||||||
- (id)initWithView:(StreamView* )view andSettings:(TemporarySettings*)settings;
|
- (id)initWithView:(StreamView* )view andSettings:(TemporarySettings*)settings;
|
||||||
|
- (void)setAllowSingleTouchEnabled:(BOOL)enabled;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,10 @@
|
|||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
|
|
||||||
@implementation NativeTouchHandler {
|
@implementation NativeTouchHandler {
|
||||||
StreamView* streamView;
|
|
||||||
TemporarySettings* currentSettings;
|
TemporarySettings* currentSettings;
|
||||||
|
__weak StreamView* streamView;
|
||||||
bool activateCoordSelector;
|
bool activateCoordSelector;
|
||||||
|
bool singleTouchDisabled;
|
||||||
CGFloat pointerVelocityDividerLocationByPoints;
|
CGFloat pointerVelocityDividerLocationByPoints;
|
||||||
|
|
||||||
bool asyncNativeTouch;
|
bool asyncNativeTouch;
|
||||||
@@ -187,10 +188,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType{
|
- (void)sendTouchEvent:(UITouch*)touch withTouchtype:(uint8_t)touchType withEvent:(UIEvent *)event{
|
||||||
//if(touchPointSpawnedAtUpperScreenEdge && touchType != LI_TOUCH_EVENT_UP) return; // we're done here. this touch event will not be sent to the remote PC. and this must be checked after coord selector finishes populating new relative coords, or the app will crash
|
//if(touchPointSpawnedAtUpperScreenEdge && touchType != LI_TOUCH_EVENT_UP) return; // we're done here. this touch event will not be sent to the remote PC. and this must be checked after coord selector finishes populating new relative coords, or the app will crash
|
||||||
if([blacklistedTouches containsObject:@((uintptr_t)touch)]) return;
|
if([blacklistedTouches containsObject:@((uintptr_t)touch)]) return;
|
||||||
|
|
||||||
|
if(singleTouchDisabled
|
||||||
|
&& [UITouchUtil touchesIn:streamView from:event].count != 2
|
||||||
|
&& touchType != LI_TOUCH_EVENT_UP) return;
|
||||||
|
|
||||||
|
if(PencilHandler.pencilPausesNativeTouch
|
||||||
|
&& PencilHandler.isDrawing
|
||||||
|
&& touchType != LI_TOUCH_EVENT_UP) return;
|
||||||
|
|
||||||
CGPoint targetCoords;
|
CGPoint targetCoords;
|
||||||
//NSLog(@"selecting coords: %d", touch.phase == UITouchPhaseMoved);
|
//NSLog(@"selecting coords: %d", touch.phase == UITouchPhaseMoved);
|
||||||
// NSLog(@"excluded count: %d", (uint32_t)[excludedPointerIds count]);
|
// NSLog(@"excluded count: %d", (uint32_t)[excludedPointerIds count]);
|
||||||
@@ -216,7 +225,7 @@
|
|||||||
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
||||||
[self handleTouchDown:touch]; //generate & populate pointerId
|
[self handleTouchDown:touch]; //generate & populate pointerId
|
||||||
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN withEvent:event];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
else{
|
else{
|
||||||
@@ -225,7 +234,7 @@
|
|||||||
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
||||||
[self handleTouchDown:touch]; //generate & populate pointerId
|
[self handleTouchDown:touch]; //generate & populate pointerId
|
||||||
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
if(self->activateCoordSelector) [self populatePointerObjIntoDict:touch];
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN];
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_DOWN withEvent:event];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,7 +244,7 @@
|
|||||||
for (UITouch* touch in touches){
|
for (UITouch* touch in touches){
|
||||||
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
if([OnScreenControls.touchesCapturedByOnScreenControls containsObject:touch]) continue;
|
||||||
if(self->activateCoordSelector) [self updatePointerObjInDict:touch];
|
if(self->activateCoordSelector) [self updatePointerObjInDict:touch];
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_MOVE];
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_MOVE withEvent:event];
|
||||||
[[self getPointerObjFromDict:touch] doesNeedResetCoords];
|
[[self getPointerObjFromDict:touch] doesNeedResetCoords];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -248,7 +257,7 @@
|
|||||||
[OnScreenControls.touchesCapturedByOnScreenControls removeObject:touch];
|
[OnScreenControls.touchesCapturedByOnScreenControls removeObject:touch];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP]; //send touch event before remove pointerId
|
[self sendTouchEvent:touch withTouchtype:LI_TOUCH_EVENT_UP withEvent:event]; //send touch event before remove pointerId
|
||||||
[self removePointerId:touch]; //then remove pointerId
|
[self removePointerId:touch]; //then remove pointerId
|
||||||
if(self->activateCoordSelector) [self removePointerObjFromDict:touch];
|
if(self->activateCoordSelector) [self removePointerObjFromDict:touch];
|
||||||
[self->blacklistedTouches removeObject:@((uintptr_t)touch)];
|
[self->blacklistedTouches removeObject:@((uintptr_t)touch)];
|
||||||
@@ -289,4 +298,8 @@
|
|||||||
return pointer.useRelativeCoords ? pointer.latestRelativePoint : pointer.latestPoint;
|
return pointer.useRelativeCoords ? pointer.latestRelativePoint : pointer.latestPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setAllowSingleTouchEnabled:(BOOL)enabled{
|
||||||
|
singleTouchDisabled = !enabled;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
|
|
||||||
+ (void)initContextWithView:(StreamView*)view andSettings:(TemporarySettings*)settings;
|
+ (void)initContextWithView:(StreamView*)view andSettings:(TemporarySettings*)settings;
|
||||||
|
+ (void)cleanUpContext;
|
||||||
|
|
||||||
- (bool)doesNeedResetCoords;
|
- (bool)doesNeedResetCoords;
|
||||||
- (void)updatePointerCoords:(UITouch *)touch;
|
- (void)updatePointerCoords:(UITouch *)touch;
|
||||||
|
|||||||
@@ -63,4 +63,8 @@ static StreamView* streamView;
|
|||||||
NSLog(@"stream wdith %f, stream height %f", streamViewWidth, streamViewHeight);
|
NSLog(@"stream wdith %f, stream height %f", streamViewWidth, streamViewHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)cleanUpContext {
|
||||||
|
streamView = nil;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -17,12 +17,7 @@
|
|||||||
|
|
||||||
@class ControllerSupport;
|
@class ControllerSupport;
|
||||||
@class StreamConfiguration;
|
@class StreamConfiguration;
|
||||||
|
@class LayoutOnScreenControls;
|
||||||
// sending self as an instance to OnScreenWidgetView or other related classes
|
|
||||||
@protocol OscInstanceReceiverDelegate <NSObject>
|
|
||||||
- (void)getOnScreenControlsInstance:(id)sender; // Renamed delegate method
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
static const float D_PAD_DIST = 10;
|
static const float D_PAD_DIST = 10;
|
||||||
static const float BUTTON_DIST = 20;
|
static const float BUTTON_DIST = 20;
|
||||||
@@ -52,11 +47,6 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@property (nonatomic, weak) id<OscInstanceReceiverDelegate> instanceReceiverDelegate; // Delegate property
|
|
||||||
- (void)sendInstance;
|
|
||||||
|
|
||||||
// @property (nonatomic, assign) CustomTapGestureRecognizer* mouseRightClickTapRecognizer; // this object will be passed to onscreencontrols class for areVirtualControllerTaps flag setting
|
// @property (nonatomic, assign) CustomTapGestureRecognizer* mouseRightClickTapRecognizer; // this object will be passed to onscreencontrols class for areVirtualControllerTaps flag setting
|
||||||
@property (nonatomic, assign) bool isLayingOut;
|
@property (nonatomic, assign) bool isLayingOut;
|
||||||
//@property (nonatomic) NSMutableSet<UITouch* >* touchesCapturedByOnScreenButtons;
|
//@property (nonatomic) NSMutableSet<UITouch* >* touchesCapturedByOnScreenButtons;
|
||||||
@@ -105,7 +95,7 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
|
|||||||
|
|
||||||
@property OnScreenControlsLevel _level;
|
@property OnScreenControlsLevel _level;
|
||||||
|
|
||||||
@property NSMutableArray *OSCButtonLayers;
|
@property NSMutableSet *OSCButtonLayerPool;
|
||||||
@property NSMutableDictionary* layerVibrationStyleDic;
|
@property NSMutableDictionary* layerVibrationStyleDic;
|
||||||
|
|
||||||
|
|
||||||
@@ -128,18 +118,19 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
|
|||||||
- (BOOL) handleTouchUpEvent:(NSSet*)touches;
|
- (BOOL) handleTouchUpEvent:(NSSet*)touches;
|
||||||
- (BOOL) handleTouchMovedEvent:(NSSet*)touches;
|
- (BOOL) handleTouchMovedEvent:(NSSet*)touches;
|
||||||
- (void) setLevel:(OnScreenControlsLevel)level;
|
- (void) setLevel:(OnScreenControlsLevel)level;
|
||||||
- (void) show;
|
- (void) showLegacyWidgetsWith:(OSCProfile* )profile;
|
||||||
|
- (void) regenLayerPool;
|
||||||
- (void) setupComplexControls;
|
- (void) setupComplexControls;
|
||||||
- (void) drawButtons;
|
- (void) drawButtons:(OSCProfile* _Nullable)profile;
|
||||||
- (void) drawBumpers;
|
- (void) drawBumpers;
|
||||||
- (void) updateControls;
|
- (void) updateLegacyWidgetsWith:(OSCProfile* _Nullable )profile;
|
||||||
- (OnScreenControlsLevel) getLevel;
|
- (OnScreenControlsLevel) getLevel;
|
||||||
- (void) setDPadCenter;
|
- (void) setDPadCenter:(OSCProfile *_Nonnull)profile;;
|
||||||
- (void) setAnalogStickPositions;
|
- (void) setAnalogStickPositions:(OSCProfile *_Nonnull)profile;
|
||||||
- (void) positionAndResizeSingleControllerLayers;
|
- (void) positionAndResizeSingleControllerLayers:(OSCProfile *_Nonnull)profile;
|
||||||
- (void) resizeControllerLayerWith:(CALayer*)layer and:(CGFloat)sizeFactor;
|
- (void) resizeControllerLayerWith:(CALayer*_Nonnull)layer and:(CGFloat)sizeFactor;
|
||||||
- (void) adjustControllerLayerOpacityWith:(CALayer*)layer and:(CGFloat)alpha;
|
- (void) adjustControllerLayerOpacityWith:(CALayer*_Nonnull)layer and:(CGFloat)alpha;
|
||||||
+ (CGFloat) getControllerLayerSizeFactor:(CALayer*)layer;
|
+ (CGFloat) getControllerLayerSizeFactor:(CALayer*_Nonnull)layer;
|
||||||
- (CGFloat) getControllerLayerOpacity:(CALayer*)layer;
|
- (CGFloat) getControllerLayerOpacity:(CALayer*_Nonnull)layer;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
+189
-106
@@ -10,6 +10,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "OnScreenControls.h"
|
#import "OnScreenControls.h"
|
||||||
|
#import "LayoutOnScreenControls.h"
|
||||||
#import "CustomTapGestureRecognizer.h"
|
#import "CustomTapGestureRecognizer.h"
|
||||||
#import "VoidController.h"
|
#import "VoidController.h"
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
@@ -105,7 +106,7 @@ static NSSet *validPositionButtonNames;
|
|||||||
@synthesize _l2Button;
|
@synthesize _l2Button;
|
||||||
@synthesize _l3Button;
|
@synthesize _l3Button;
|
||||||
@synthesize _level;
|
@synthesize _level;
|
||||||
@synthesize OSCButtonLayers;
|
@synthesize OSCButtonLayerPool;
|
||||||
@synthesize _dPadBackground;
|
@synthesize _dPadBackground;
|
||||||
|
|
||||||
static const float EDGE_WIDTH = .05;
|
static const float EDGE_WIDTH = .05;
|
||||||
@@ -203,16 +204,6 @@ static float L3_Y;
|
|||||||
[_controllerSupport updateFinished:_controller];
|
[_controllerSupport updateFinished:_controller];
|
||||||
}
|
}
|
||||||
|
|
||||||
// sending self as an instance to OnScreenWidgetView
|
|
||||||
- (void)sendInstance{
|
|
||||||
NSLog(@"OnScreenControls is sending its instance...");
|
|
||||||
if ([self.instanceReceiverDelegate respondsToSelector:@selector(getOnScreenControlsInstance:)]) {
|
|
||||||
[self.instanceReceiverDelegate getOnScreenControlsInstance:self];
|
|
||||||
} else {
|
|
||||||
NSLog(@"Delegate not set or does not respond to getOnScreenControlsInstance:");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport streamConfig:(StreamConfiguration*)streamConfig {
|
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport streamConfig:(StreamConfiguration*)streamConfig {
|
||||||
self = [self init];
|
self = [self init];
|
||||||
self.isLayingOut = false; // set false by default (play mode instead of layout mode)
|
self.isLayingOut = false; // set false by default (play mode instead of layout mode)
|
||||||
@@ -220,7 +211,7 @@ static float L3_Y;
|
|||||||
|
|
||||||
profilesManager = [OSCProfilesManager sharedManager:view.bounds];
|
profilesManager = [OSCProfilesManager sharedManager:view.bounds];
|
||||||
|
|
||||||
self.OSCButtonLayers = [[NSMutableArray alloc] init];
|
self.OSCButtonLayerPool = [[NSMutableSet alloc] init];
|
||||||
|
|
||||||
if (controllerSupport) {
|
if (controllerSupport) {
|
||||||
_controllerSupport = controllerSupport;
|
_controllerSupport = controllerSupport;
|
||||||
@@ -272,27 +263,9 @@ static float L3_Y;
|
|||||||
_rightStickBackground = [CALayer layer];
|
_rightStickBackground = [CALayer layer];
|
||||||
_leftStick = [CALayer layer];
|
_leftStick = [CALayer layer];
|
||||||
_rightStick = [CALayer layer];
|
_rightStick = [CALayer layer];
|
||||||
|
_dPadBackground = [CALayer layer];
|
||||||
|
|
||||||
[self.OSCButtonLayers addObject:_aButton];
|
[self regenLayerPool];
|
||||||
[self.OSCButtonLayers addObject:_bButton];
|
|
||||||
[self.OSCButtonLayers addObject:_xButton];
|
|
||||||
[self.OSCButtonLayers addObject:_yButton];
|
|
||||||
[self.OSCButtonLayers addObject:_startButton];
|
|
||||||
[self.OSCButtonLayers addObject:_selectButton];
|
|
||||||
[self.OSCButtonLayers addObject:_r1Button];
|
|
||||||
[self.OSCButtonLayers addObject:_r2Button];
|
|
||||||
[self.OSCButtonLayers addObject:_r3Button];
|
|
||||||
[self.OSCButtonLayers addObject:_l1Button];
|
|
||||||
[self.OSCButtonLayers addObject:_l2Button];
|
|
||||||
[self.OSCButtonLayers addObject:_l3Button];
|
|
||||||
[self.OSCButtonLayers addObject:_upButton];
|
|
||||||
[self.OSCButtonLayers addObject:_downButton];
|
|
||||||
[self.OSCButtonLayers addObject:_leftButton];
|
|
||||||
[self.OSCButtonLayers addObject:_rightButton];
|
|
||||||
[self.OSCButtonLayers addObject:_leftStickBackground];
|
|
||||||
[self.OSCButtonLayers addObject:_rightStickBackground];
|
|
||||||
[self.OSCButtonLayers addObject:_leftStick];
|
|
||||||
[self.OSCButtonLayers addObject:_rightStick];
|
|
||||||
|
|
||||||
/* Name button layers to allow us to more easily associate them with 'OnScreenButtonState' objects by comparing their name properties */
|
/* Name button layers to allow us to more easily associate them with 'OnScreenButtonState' objects by comparing their name properties */
|
||||||
_leftStickBackground.name = @"leftStickBackground";
|
_leftStickBackground.name = @"leftStickBackground";
|
||||||
@@ -315,6 +288,7 @@ static float L3_Y;
|
|||||||
_rightButton.name = @"rightButton";
|
_rightButton.name = @"rightButton";
|
||||||
_downButton.name = @"downButton";
|
_downButton.name = @"downButton";
|
||||||
_leftButton.name = @"leftButton";
|
_leftButton.name = @"leftButton";
|
||||||
|
_dPadBackground.name = @"dPad";
|
||||||
|
|
||||||
|
|
||||||
_standardRoundButtonBounds = standardRoundButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"AButton"].size.width, [UIImage imageNamed:@"AButton"].size.height);
|
_standardRoundButtonBounds = standardRoundButtonBounds = CGRectMake(0, 0, [UIImage imageNamed:@"AButton"].size.width, [UIImage imageNamed:@"AButton"].size.height);
|
||||||
@@ -327,13 +301,42 @@ static float L3_Y;
|
|||||||
_activeCustomOscButtonPositionDict = [[NSMutableDictionary alloc] init];
|
_activeCustomOscButtonPositionDict = [[NSMutableDictionary alloc] init];
|
||||||
touchesCapturedByOnScreenControls = [[NSMutableSet alloc] init];
|
touchesCapturedByOnScreenControls = [[NSMutableSet alloc] init];
|
||||||
|
|
||||||
|
if(![self isKindOfClass:[LayoutOnScreenControls class]]) OnScreenControls.shared = self;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) show {
|
- (void)regenLayerPool{
|
||||||
_visible = YES;
|
for(CALayer* layer in self.OSCButtonLayerPool){
|
||||||
|
[layer removeFromSuperlayer];
|
||||||
|
}
|
||||||
|
[self.OSCButtonLayerPool removeAllObjects];
|
||||||
|
[self.OSCButtonLayerPool addObject:_aButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_bButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_xButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_yButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_startButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_selectButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_r1Button];
|
||||||
|
[self.OSCButtonLayerPool addObject:_r2Button];
|
||||||
|
// [self.OSCButtonLayerPool addObject:_r3Button];
|
||||||
|
[self.OSCButtonLayerPool addObject:_l1Button];
|
||||||
|
[self.OSCButtonLayerPool addObject:_l2Button];
|
||||||
|
// [self.OSCButtonLayerPool addObject:_l3Button];
|
||||||
|
[self.OSCButtonLayerPool addObject:_upButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_downButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_leftButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_rightButton];
|
||||||
|
[self.OSCButtonLayerPool addObject:_leftStickBackground];
|
||||||
|
[self.OSCButtonLayerPool addObject:_rightStickBackground];
|
||||||
|
[self.OSCButtonLayerPool addObject:_leftStick];
|
||||||
|
[self.OSCButtonLayerPool addObject:_rightStick];
|
||||||
|
}
|
||||||
|
|
||||||
[self updateControls];
|
- (void) showLegacyWidgetsWith:(OSCProfile* )profile {
|
||||||
|
_visible = YES;
|
||||||
|
NSLog(@"show updateControls %f", CACurrentMediaTime());
|
||||||
|
[self updateLegacyWidgetsWith:profile];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setLevel:(OnScreenControlsLevel)level {
|
- (void) setLevel:(OnScreenControlsLevel)level {
|
||||||
@@ -342,7 +345,7 @@ static float L3_Y;
|
|||||||
// Only update controls if we're showing, otherwise
|
// Only update controls if we're showing, otherwise
|
||||||
// show will do it for us.
|
// show will do it for us.
|
||||||
if (_visible) {
|
if (_visible) {
|
||||||
[self updateControls];
|
[self updateLegacyWidgetsWith:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,13 +362,20 @@ static float L3_Y;
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) updateControls {
|
- (void) updateLegacyWidgetsWith:(OSCProfile* _Nullable)profile {
|
||||||
if(self._level == OnScreenControlsLevelCustom){
|
if(self._level == OnScreenControlsLevelCustom && profile){
|
||||||
// mark all OSC buttons that has valid coords of positions
|
// mark all OSC buttons that has valid coords of positions
|
||||||
validPositionButtonNames = [NSSet setWithObjects:
|
[self regenLayerPool];
|
||||||
|
[_activeCustomOscButtonPositionDict removeAllObjects]; //reset the Dict.
|
||||||
|
|
||||||
|
NSSet* persistedButtonNames = [NSSet setWithObjects:
|
||||||
@"l2Button",
|
@"l2Button",
|
||||||
@"l1Button",
|
@"l1Button",
|
||||||
@"dPad",
|
@"dPad",
|
||||||
|
@"upButton",
|
||||||
|
@"downButton",
|
||||||
|
@"leftButton",
|
||||||
|
@"rightButton",
|
||||||
@"selectButton",
|
@"selectButton",
|
||||||
@"leftStickBackground",
|
@"leftStickBackground",
|
||||||
@"rightStickBackground",
|
@"rightStickBackground",
|
||||||
@@ -378,15 +388,29 @@ static float L3_Y;
|
|||||||
@"startButton",
|
@"startButton",
|
||||||
nil];
|
nil];
|
||||||
|
|
||||||
|
NSSet* singleLayerButtons = [NSSet setWithObjects:
|
||||||
|
@"l2Button",
|
||||||
|
@"l1Button",
|
||||||
|
@"selectButton",
|
||||||
|
@"r2Button",
|
||||||
|
@"r1Button",
|
||||||
|
@"aButton",
|
||||||
|
@"bButton",
|
||||||
|
@"xButton",
|
||||||
|
@"yButton",
|
||||||
|
@"startButton",
|
||||||
|
nil];
|
||||||
|
|
||||||
// _activeCustomOscButtonPositionDict will be updated every time when the osc profile is reloaded
|
// _activeCustomOscButtonPositionDict will be updated every time when the osc profile is reloaded
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
// if(!profile) profile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
||||||
[_activeCustomOscButtonPositionDict removeAllObjects]; //reset the Dict.
|
|
||||||
// NSLog(@"_activeCustomOscButtonPositionDict update: STARTOVER");
|
// NSLog(@"_activeCustomOscButtonPositionDict update: STARTOVER");
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
for (NSData *buttonStateEncoded in profile.buttonStatesEncoded) {
|
||||||
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
|
if(!buttonState) continue;
|
||||||
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
||||||
[OnScreenControls.layerVibrationStyleDic setObject:@(buttonState.vibrationStyle) forKey:buttonState.name];
|
[OnScreenControls.layerVibrationStyleDic setObject:@(buttonState.vibrationStyle) forKey:buttonState.name];
|
||||||
if(!buttonState.isHidden && [validPositionButtonNames containsObject:buttonState.name] && (buttonState.widgetType == LegacyOnScreenControls || [profilesManager getIndexOfSelectedProfile] == 0 ) ){
|
if(!buttonState.isHidden && [persistedButtonNames containsObject:buttonState.name] && buttonState.widgetType == LegacyOnScreenControls){
|
||||||
[_activeCustomOscButtonPositionDict setObject:[NSValue valueWithCGPoint:buttonState.position] forKey:buttonState.name]; // we got a buttonname -> position dict here
|
[_activeCustomOscButtonPositionDict setObject:[NSValue valueWithCGPoint:buttonState.position] forKey:buttonState.name]; // we got a buttonname -> position dict here
|
||||||
// NSLog(@"_activeCustomOscButtonPositionDict update, button name:%@, position: %f, %f", buttonState.name, buttonState.position.x, buttonState.position.y);
|
// NSLog(@"_activeCustomOscButtonPositionDict update, button name:%@, position: %f, %f", buttonState.name, buttonState.position.x, buttonState.position.y);
|
||||||
}
|
}
|
||||||
@@ -410,6 +434,33 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//NSLog(@"_activeCustomOscButtonPositionDict update, active button number: %lu", (unsigned long)[_activeCustomOscButtonPositionDict count]);
|
//NSLog(@"_activeCustomOscButtonPositionDict update, active button number: %lu", (unsigned long)[_activeCustomOscButtonPositionDict count]);
|
||||||
|
NSSet* tempLayerPool = [self.OSCButtonLayerPool copy];
|
||||||
|
|
||||||
|
for (CALayer* button in tempLayerPool){
|
||||||
|
if([singleLayerButtons containsObject:button.name]
|
||||||
|
&& ![_activeCustomOscButtonPositionDict.allKeys containsObject:button.name]) [OSCButtonLayerPool removeObject:button];
|
||||||
|
if(![_activeCustomOscButtonPositionDict.allKeys containsObject:@"upButton"]){
|
||||||
|
[OSCButtonLayerPool removeObject:_dPadBackground];
|
||||||
|
[OSCButtonLayerPool removeObject:_upButton];
|
||||||
|
[OSCButtonLayerPool removeObject:_downButton];
|
||||||
|
[OSCButtonLayerPool removeObject:_leftButton];
|
||||||
|
[OSCButtonLayerPool removeObject:_rightButton];
|
||||||
|
}
|
||||||
|
if(![_activeCustomOscButtonPositionDict.allKeys containsObject:@"leftStickBackground"]){
|
||||||
|
[OSCButtonLayerPool removeObject:_leftStick];
|
||||||
|
[OSCButtonLayerPool removeObject:_leftStickBackground];
|
||||||
|
}
|
||||||
|
if(![_activeCustomOscButtonPositionDict.allKeys containsObject:@"rightStickBackground"]){
|
||||||
|
[OSCButtonLayerPool removeObject:_rightStick];
|
||||||
|
[OSCButtonLayerPool removeObject:_rightStickBackground];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"OSCButtonLayerPool count: %ld", OSCButtonLayerPool.count);
|
||||||
|
for(CALayer* layer in OSCButtonLayerPool){
|
||||||
|
NSLog(@"OSCButtonLayerPool name: %@", layer.name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// deal with simple & full mode configurations
|
// deal with simple & full mode configurations
|
||||||
@@ -472,13 +523,13 @@ static float L3_Y;
|
|||||||
[self hideBumpers];
|
[self hideBumpers];
|
||||||
[self hideSticks];
|
[self hideSticks];
|
||||||
[self drawStartSelect];
|
[self drawStartSelect];
|
||||||
[self drawButtons];
|
[self drawButtons:profile];
|
||||||
[self setOpacityForStandardControllerLayers];
|
[self setOpacityForStandardControllerLayers];
|
||||||
break;
|
break;
|
||||||
case OnScreenControlsLevelFull:
|
case OnScreenControlsLevelFull:
|
||||||
|
|
||||||
[self setupComplexControls];
|
[self setupComplexControls];
|
||||||
[self drawButtons];
|
[self drawButtons:profile];
|
||||||
[self drawStartSelect];
|
[self drawStartSelect];
|
||||||
[self drawBumpers];
|
[self drawBumpers];
|
||||||
[self drawTriggers];
|
[self drawTriggers];
|
||||||
@@ -489,15 +540,15 @@ static float L3_Y;
|
|||||||
case OnScreenControlsLevelCustom:
|
case OnScreenControlsLevelCustom:
|
||||||
|
|
||||||
[self setupComplexControls]; // Default postion for D-Pad set here
|
[self setupComplexControls]; // Default postion for D-Pad set here
|
||||||
[self setDPadCenter]; // Custom position for D-Pad set here
|
[self setDPadCenter:profile]; // Custom position for D-Pad set here
|
||||||
[self setAnalogStickPositions]; // Custom position for analog sticks set here
|
[self setAnalogStickPositions:profile]; // Custom position for analog sticks set here
|
||||||
[self drawButtons];
|
[self drawButtons:profile];
|
||||||
[self drawStartSelect];
|
[self drawStartSelect];
|
||||||
[self drawBumpers];
|
[self drawBumpers];
|
||||||
[self drawTriggers];
|
[self drawTriggers];
|
||||||
[self drawSticks];
|
[self drawSticks];
|
||||||
[self positionAndResizeSingleControllerLayers];
|
[self positionAndResizeSingleControllerLayers:profile];
|
||||||
[self setOpacityForCutsomControllerLayers];
|
[self setOpacityForCutsomControllerLayers:profile];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -506,9 +557,11 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// populate the controllerLayer.name -> Opacity dictionary... have to do this in order to make touchdown visual effect consistent
|
// populate the controllerLayer.name -> Opacity dictionary... have to do this in order to make touchdown visual effect consistent
|
||||||
for (CALayer* controllerLayer in self.OSCButtonLayers){
|
for (CALayer* controllerLayer in self.OSCButtonLayerPool){
|
||||||
[_originalControllerLayerOpacityDict setObject:@(controllerLayer.opacity) forKey:controllerLayer.name];
|
[_originalControllerLayerOpacityDict setObject:@(controllerLayer.opacity) forKey:controllerLayer.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self removeHiddenlayers];
|
||||||
}
|
}
|
||||||
|
|
||||||
// For GCExtendedGamepad controls we move start, select, L3, and R3 to the button
|
// For GCExtendedGamepad controls we move start, select, L3, and R3 to the button
|
||||||
@@ -635,7 +688,7 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) drawButtons {
|
- (void) drawButtons:(OSCProfile* )profile {
|
||||||
UIImage* aButtonImage = [UIImage imageNamed:@"AButton"];
|
UIImage* aButtonImage = [UIImage imageNamed:@"AButton"];
|
||||||
UIImage* aButtonHdImage = [UIImage imageNamed:@"AButtonHD"];
|
UIImage* aButtonHdImage = [UIImage imageNamed:@"AButtonHD"];
|
||||||
UIImage* bButtonImage = [UIImage imageNamed:@"BButton"];
|
UIImage* bButtonImage = [UIImage imageNamed:@"BButton"];
|
||||||
@@ -653,6 +706,7 @@ static float L3_Y;
|
|||||||
CGRect yButtonFrame = CGRectMake(BUTTON_CENTER_X - yButtonImage.size.width / 2, BUTTON_CENTER_Y - BUTTON_DIST - yButtonImage.size.height, yButtonImage.size.width, yButtonImage.size.height);
|
CGRect yButtonFrame = CGRectMake(BUTTON_CENTER_X - yButtonImage.size.width / 2, BUTTON_CENTER_Y - BUTTON_DIST - yButtonImage.size.height, yButtonImage.size.width, yButtonImage.size.height);
|
||||||
|
|
||||||
// create A button
|
// create A button
|
||||||
|
if([OSCButtonLayerPool containsObject:_aButton]){
|
||||||
_aButton.contents = (id) aButtonHdImage.CGImage;
|
_aButton.contents = (id) aButtonHdImage.CGImage;
|
||||||
// Set the filtering mode for smooth downscaling
|
// Set the filtering mode for smooth downscaling
|
||||||
_aButton.minificationFilter = kCAFilterLinear; // Smooth scaling down
|
_aButton.minificationFilter = kCAFilterLinear; // Smooth scaling down
|
||||||
@@ -665,21 +719,28 @@ static float L3_Y;
|
|||||||
|
|
||||||
_aButton.frame = _swapABXY ? bButtonFrame : aButtonFrame;
|
_aButton.frame = _swapABXY ? bButtonFrame : aButtonFrame;
|
||||||
[_view.layer addSublayer:_aButton]; // rendering OSC Button here
|
[_view.layer addSublayer:_aButton]; // rendering OSC Button here
|
||||||
|
}
|
||||||
|
|
||||||
// create B button
|
// create B button
|
||||||
|
if([OSCButtonLayerPool containsObject:_bButton]){
|
||||||
_bButton.frame = _swapABXY ? aButtonFrame : bButtonFrame;
|
_bButton.frame = _swapABXY ? aButtonFrame : bButtonFrame;
|
||||||
_bButton.contents = (id) bButtonHdImage.CGImage;
|
_bButton.contents = (id) bButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_bButton];
|
[_view.layer addSublayer:_bButton];
|
||||||
|
}
|
||||||
|
|
||||||
// create X Button
|
// create X Button
|
||||||
|
if([OSCButtonLayerPool containsObject:_xButton]){
|
||||||
_xButton.frame = _swapABXY ? yButtonFrame : xButtonFrame;
|
_xButton.frame = _swapABXY ? yButtonFrame : xButtonFrame;
|
||||||
_xButton.contents = (id) xButtonHdImage.CGImage;
|
_xButton.contents = (id) xButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_xButton];
|
[_view.layer addSublayer:_xButton];
|
||||||
|
}
|
||||||
|
|
||||||
// create Y Button
|
// create Y Button
|
||||||
|
if([OSCButtonLayerPool containsObject:_yButton]){
|
||||||
_yButton.frame = _swapABXY ? xButtonFrame : yButtonFrame;
|
_yButton.frame = _swapABXY ? xButtonFrame : yButtonFrame;
|
||||||
_yButton.contents = (id) yButtonHdImage.CGImage;
|
_yButton.contents = (id) yButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_yButton];
|
[_view.layer addSublayer:_yButton];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(self._level == OnScreenControlsLevelFull ||
|
if(self._level == OnScreenControlsLevelFull ||
|
||||||
@@ -687,16 +748,16 @@ static float L3_Y;
|
|||||||
_dPadSizeFactor = 1.0;
|
_dPadSizeFactor = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dPad buttons are resized HERE
|
||||||
|
// up button
|
||||||
|
// UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
||||||
|
if([_activeCustomOscButtonPositionDict.allKeys containsObject:@"dPad"]){
|
||||||
// Calculate the distances of each button from the shared center based on their transformed positions
|
// Calculate the distances of each button from the shared center based on their transformed positions
|
||||||
CGFloat newDPadDistFactor = 0.2/_dPadSizeFactor;
|
CGFloat newDPadDistFactor = 0.2/_dPadSizeFactor;
|
||||||
CGFloat newLongSideLength = standardLeftRightButtonBounds.size.width * _dPadSizeFactor;
|
CGFloat newLongSideLength = standardLeftRightButtonBounds.size.width * _dPadSizeFactor;
|
||||||
CGFloat newShortSideLength = standardLeftRightButtonBounds.size.height * _dPadSizeFactor;
|
CGFloat newShortSideLength = standardLeftRightButtonBounds.size.height * _dPadSizeFactor;
|
||||||
CGPoint sharedCenter = CGPointMake(D_PAD_CENTER_X, D_PAD_CENTER_Y); // this will anchor the center point of the dPad
|
CGPoint sharedCenter = CGPointMake(D_PAD_CENTER_X, D_PAD_CENTER_Y); // this will anchor the center point of the dPad
|
||||||
|
|
||||||
|
|
||||||
// dPad buttons are resized HERE
|
|
||||||
// up button
|
|
||||||
// UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
|
||||||
UIImage* upButtonHdImage = [UIImage imageNamed:@"UpButtonHD"];
|
UIImage* upButtonHdImage = [UIImage imageNamed:@"UpButtonHD"];
|
||||||
_upButton.contents = (id) upButtonHdImage.CGImage;
|
_upButton.contents = (id) upButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_upButton];
|
[_view.layer addSublayer:_upButton];
|
||||||
@@ -732,14 +793,13 @@ static float L3_Y;
|
|||||||
_rightButton.bounds = CGRectMake(0, 0, newLongSideLength, newShortSideLength);
|
_rightButton.bounds = CGRectMake(0, 0, newLongSideLength, newShortSideLength);
|
||||||
_rightButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
|
_rightButton.position = CGPointMake(sharedCenter.x, sharedCenter.y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets D-Pad position for class const var
|
* Sets D-Pad position for class const var
|
||||||
*/
|
*/
|
||||||
- (void) setDPadCenter {
|
- (void) setDPadCenter:(OSCProfile *)profile {
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
for (NSData *buttonStateEncoded in profile.buttonStatesEncoded) {
|
||||||
|
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
|
||||||
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
if ([buttonState.name isEqualToString:@"dPad"]) {
|
if ([buttonState.name isEqualToString:@"dPad"]) {
|
||||||
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
||||||
@@ -752,10 +812,8 @@ static float L3_Y;
|
|||||||
/**
|
/**
|
||||||
* Sets analog stick positions for class const var
|
* Sets analog stick positions for class const var
|
||||||
*/
|
*/
|
||||||
- (void) setAnalogStickPositions {
|
- (void) setAnalogStickPositions:(OSCProfile *)profile {
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile]; // returns the currently selected OSCProfile
|
for (NSData *buttonStateEncoded in profile.buttonStatesEncoded) {
|
||||||
|
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
|
||||||
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
||||||
if ([buttonState.name isEqualToString:@"leftStickBackground"]) {
|
if ([buttonState.name isEqualToString:@"leftStickBackground"]) {
|
||||||
@@ -775,16 +833,10 @@ static float L3_Y;
|
|||||||
|
|
||||||
# define LR2_Y_UP_OFFSET 8
|
# define LR2_Y_UP_OFFSET 8
|
||||||
# define LR1_Y_DOWN_OFFSET 3.5
|
# define LR1_Y_DOWN_OFFSET 3.5
|
||||||
- (void) positionAndResizeSingleControllerLayers {
|
- (void) positionAndResizeSingleControllerLayers:(OSCProfile *)profile {
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile];
|
for (NSData *buttonStateEncoded in profile.buttonStatesEncoded) {
|
||||||
bool defaultProfileSelected = [profilesManager getIndexOfSelectedProfile] == 0;
|
|
||||||
|
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
|
||||||
|
|
||||||
OnScreenButtonState *buttonStateDecoded = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState *buttonStateDecoded = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
|
for (CALayer *buttonLayer in self.OSCButtonLayerPool) { // iterate through each button layer on screen and position and hide/unhide each according to the instructions of its associated 'buttonState'
|
||||||
|
|
||||||
for (CALayer *buttonLayer in self.OSCButtonLayers) { // iterate through each button layer on screen and position and hide/unhide each according to the instructions of its associated 'buttonState'
|
|
||||||
if ([buttonLayer.name isEqualToString:buttonStateDecoded.name]) {
|
if ([buttonLayer.name isEqualToString:buttonStateDecoded.name]) {
|
||||||
if ([buttonLayer.name isEqualToString:@"upButton"] == NO &&
|
if ([buttonLayer.name isEqualToString:@"upButton"] == NO &&
|
||||||
[buttonLayer.name isEqualToString:@"rightButton"] == NO &&
|
[buttonLayer.name isEqualToString:@"rightButton"] == NO &&
|
||||||
@@ -795,10 +847,15 @@ static float L3_Y;
|
|||||||
buttonStateDecoded.position = [self denormalizeWidgetPosition:buttonStateDecoded.position];
|
buttonStateDecoded.position = [self denormalizeWidgetPosition:buttonStateDecoded.position];
|
||||||
buttonLayer.position = buttonStateDecoded.position;
|
buttonLayer.position = buttonStateDecoded.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonLayer.hidden = buttonStateDecoded.isHidden;
|
buttonLayer.hidden = buttonStateDecoded.isHidden;
|
||||||
|
if(buttonLayer.hidden){
|
||||||
|
[buttonLayer removeFromSuperlayer];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// adjust default layout for largerStickLR1
|
// adjust default layout for largerStickLR1
|
||||||
if(defaultProfileSelected && _largerStickLR1){
|
if(_largerStickLR1){
|
||||||
if([buttonLayer.name isEqualToString:@"l2Button"] || [buttonLayer.name isEqualToString:@"r2Button"]) buttonLayer.position = CGPointMake(buttonLayer.position.x, buttonLayer.position.y - LR2_Y_UP_OFFSET);
|
if([buttonLayer.name isEqualToString:@"l2Button"] || [buttonLayer.name isEqualToString:@"r2Button"]) buttonLayer.position = CGPointMake(buttonLayer.position.x, buttonLayer.position.y - LR2_Y_UP_OFFSET);
|
||||||
if([buttonLayer.name isEqualToString:@"l1Button"] || [buttonLayer.name isEqualToString:@"r1Button"]) buttonLayer.position = CGPointMake(buttonLayer.position.x, buttonLayer.position.y + LR1_Y_DOWN_OFFSET);
|
if([buttonLayer.name isEqualToString:@"l1Button"] || [buttonLayer.name isEqualToString:@"r1Button"]) buttonLayer.position = CGPointMake(buttonLayer.position.x, buttonLayer.position.y + LR1_Y_DOWN_OFFSET);
|
||||||
}
|
}
|
||||||
@@ -823,7 +880,7 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void) setOpacityForStandardControllerLayers {
|
- (void) setOpacityForStandardControllerLayers {
|
||||||
for(CALayer* oscLayer in self.OSCButtonLayers){
|
for(CALayer* oscLayer in self.OSCButtonLayerPool){
|
||||||
if(oscLayer == self._leftStick ||
|
if(oscLayer == self._leftStick ||
|
||||||
oscLayer == self._rightStick){
|
oscLayer == self._rightStick){
|
||||||
oscLayer.opacity = DEFAULT_STICK_OPACITY;
|
oscLayer.opacity = DEFAULT_STICK_OPACITY;
|
||||||
@@ -836,15 +893,10 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setOpacityForCutsomControllerLayers:(OSCProfile *)profile {
|
||||||
- (void) setOpacityForCutsomControllerLayers {
|
for (NSData *buttonStateEncoded in profile.buttonStatesEncoded) {
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile];
|
|
||||||
// bool defaultProfileSelected = [profilesManager getIndexOfSelectedProfile] == 0;
|
|
||||||
|
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
|
||||||
OnScreenButtonState* buttonStateDecoded = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState* buttonStateDecoded = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
|
for (CALayer *buttonLayer in self.OSCButtonLayerPool) { // iterate through each button layer on screen
|
||||||
for (CALayer *buttonLayer in self.OSCButtonLayers) { // iterate through each button layer on screen
|
|
||||||
// Here we deal with resizing single layer controllers only
|
// Here we deal with resizing single layer controllers only
|
||||||
if ([buttonLayer.name isEqualToString:buttonStateDecoded.name]) {
|
if ([buttonLayer.name isEqualToString:buttonStateDecoded.name]) {
|
||||||
if ([buttonLayer.name isEqualToString:@"l1Button"] ||
|
if ([buttonLayer.name isEqualToString:@"l1Button"] ||
|
||||||
@@ -875,123 +927,147 @@ static float L3_Y;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)removeHiddenlayers{
|
||||||
|
for (CALayer *buttonLayer in self.OSCButtonLayerPool) { // iterate through each button layer on screen
|
||||||
|
if(buttonLayer.isHidden || buttonLayer.opacity == 0) [buttonLayer removeFromSuperlayer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) drawStartSelect {
|
- (void) drawStartSelect {
|
||||||
// create Start button
|
// create Start button
|
||||||
|
if([OSCButtonLayerPool containsObject:_startButton]){
|
||||||
UIImage* startButtonImage = [UIImage imageNamed:@"StartButton"];
|
UIImage* startButtonImage = [UIImage imageNamed:@"StartButton"];
|
||||||
UIImage* startButtonHdImage = [UIImage imageNamed:@"StartButtonHD"];
|
UIImage* startButtonHdImage = [UIImage imageNamed:@"StartButtonHD"];
|
||||||
_startButton.frame = CGRectMake(START_X - startButtonImage.size.width / 2, START_Y - startButtonImage.size.height / 2, startButtonImage.size.width, startButtonImage.size.height);
|
_startButton.frame = CGRectMake(START_X - startButtonImage.size.width / 2, START_Y - startButtonImage.size.height / 2, startButtonImage.size.width, startButtonImage.size.height);
|
||||||
_startButton.contents = (id) startButtonHdImage.CGImage;
|
_startButton.contents = (id) startButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_startButton];
|
[_view.layer addSublayer:_startButton];
|
||||||
|
}
|
||||||
|
|
||||||
// create Select button
|
// create Select button
|
||||||
|
if([OSCButtonLayerPool containsObject:_selectButton]){
|
||||||
UIImage* selectButtonImage = [UIImage imageNamed:@"SelectButton"];
|
UIImage* selectButtonImage = [UIImage imageNamed:@"SelectButton"];
|
||||||
UIImage* selectHdButtonImage = [UIImage imageNamed:@"SelectButtonHD"];
|
UIImage* selectHdButtonImage = [UIImage imageNamed:@"SelectButtonHD"];
|
||||||
_selectButton.frame = CGRectMake(SELECT_X - selectButtonImage.size.width / 2, SELECT_Y - selectButtonImage.size.height / 2, selectButtonImage.size.width, selectButtonImage.size.height);
|
_selectButton.frame = CGRectMake(SELECT_X - selectButtonImage.size.width / 2, SELECT_Y - selectButtonImage.size.height / 2, selectButtonImage.size.width, selectButtonImage.size.height);
|
||||||
_selectButton.contents = (id) selectHdButtonImage.CGImage;
|
_selectButton.contents = (id) selectHdButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_selectButton];
|
[_view.layer addSublayer:_selectButton];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) drawBumpers {
|
- (void) drawBumpers {
|
||||||
// adjust layout for larger L2 & R2 button settings
|
// adjust layout for larger L2 & R2 button settings
|
||||||
if(_largerStickLR1) L1_Y = R1_Y = L1_Y + LR1_Y_DOWN_OFFSET;
|
if(_largerStickLR1) L1_Y = R1_Y = L1_Y + LR1_Y_DOWN_OFFSET;
|
||||||
|
|
||||||
// create L1 button
|
// create L1 button
|
||||||
|
if([OSCButtonLayerPool containsObject:_l1Button]){
|
||||||
UIImage* l1ButtonImage = [UIImage imageNamed:@"L1"];
|
UIImage* l1ButtonImage = [UIImage imageNamed:@"L1"];
|
||||||
UIImage* l1ButtonHdImage = [UIImage imageNamed:@"L1HD"];
|
UIImage* l1ButtonHdImage = [UIImage imageNamed:@"L1HD"];
|
||||||
_l1Button.frame = CGRectMake(L1_X - l1ButtonImage.size.width / 2, L1_Y - l1ButtonImage.size.height / 2, l1ButtonImage.size.width, l1ButtonImage.size.height);
|
_l1Button.frame = CGRectMake(L1_X - l1ButtonImage.size.width / 2, L1_Y - l1ButtonImage.size.height / 2, l1ButtonImage.size.width, l1ButtonImage.size.height);
|
||||||
_l1Button.contents = (id) l1ButtonHdImage.CGImage;
|
_l1Button.contents = (id) l1ButtonHdImage.CGImage;
|
||||||
|
if(_largerStickLR1){
|
||||||
|
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
|
||||||
|
_l1Button.bounds = CGRectMake(0, 0, l2ButtonImage.size.width, l2ButtonImage.size.height);
|
||||||
|
}
|
||||||
[_view.layer addSublayer:_l1Button];
|
[_view.layer addSublayer:_l1Button];
|
||||||
|
}
|
||||||
|
|
||||||
// create R1 button
|
// create R1 button
|
||||||
|
if([OSCButtonLayerPool containsObject:_r1Button]){
|
||||||
UIImage* r1ButtonImage = [UIImage imageNamed:@"R1"];
|
UIImage* r1ButtonImage = [UIImage imageNamed:@"R1"];
|
||||||
UIImage* r1ButtonHdImage = [UIImage imageNamed:@"R1HD"];
|
UIImage* r1ButtonHdImage = [UIImage imageNamed:@"R1HD"];
|
||||||
_r1Button.frame = CGRectMake(R1_X - r1ButtonImage.size.width / 2, R1_Y - r1ButtonImage.size.height / 2, r1ButtonImage.size.width, r1ButtonImage.size.height);
|
_r1Button.frame = CGRectMake(R1_X - r1ButtonImage.size.width / 2, R1_Y - r1ButtonImage.size.height / 2, r1ButtonImage.size.width, r1ButtonImage.size.height);
|
||||||
_r1Button.contents = (id) r1ButtonHdImage.CGImage;
|
_r1Button.contents = (id) r1ButtonHdImage.CGImage;
|
||||||
|
|
||||||
// make l1 r1 the same size as l2 r2
|
// make l1 r1 the same size as l2 r2
|
||||||
if(_largerStickLR1){
|
if(_largerStickLR1){
|
||||||
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
|
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
|
||||||
UIImage* l2ButtonHdImage = [UIImage imageNamed:@"L2HD"];
|
_r1Button.bounds = CGRectMake(0, 0, l2ButtonImage.size.width, l2ButtonImage.size.height);
|
||||||
_l1Button.bounds = _r1Button.bounds = CGRectMake(0, 0, l2ButtonImage.size.width, l2ButtonImage.size.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[_view.layer addSublayer:_r1Button];
|
[_view.layer addSublayer:_r1Button];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) drawTriggers {
|
- (void) drawTriggers {
|
||||||
// adjust layout for larger L2 & R2 button settings
|
// adjust layout for larger L2 & R2 button settings
|
||||||
if(_largerStickLR1) L2_Y = R2_Y = L2_Y - LR2_Y_UP_OFFSET;
|
if(_largerStickLR1) L2_Y = R2_Y = L2_Y - LR2_Y_UP_OFFSET;
|
||||||
|
|
||||||
// create L2 button
|
// create L2 button
|
||||||
|
if([OSCButtonLayerPool containsObject:_l2Button]){
|
||||||
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
|
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
|
||||||
UIImage* l2ButtonHdImage = [UIImage imageNamed:@"L2HD"];
|
UIImage* l2ButtonHdImage = [UIImage imageNamed:@"L2HD"];
|
||||||
_l2Button.frame = CGRectMake(L2_X - l2ButtonImage.size.width / 2, L2_Y - l2ButtonImage.size.height / 2, l2ButtonImage.size.width, l2ButtonImage.size.height);
|
_l2Button.frame = CGRectMake(L2_X - l2ButtonImage.size.width / 2, L2_Y - l2ButtonImage.size.height / 2, l2ButtonImage.size.width, l2ButtonImage.size.height);
|
||||||
_l2Button.contents = (id) l2ButtonHdImage.CGImage;
|
_l2Button.contents = (id) l2ButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_l2Button];
|
[_view.layer addSublayer:_l2Button];
|
||||||
|
}
|
||||||
|
|
||||||
// create R2 button
|
// create R2 button
|
||||||
|
if([OSCButtonLayerPool containsObject:_r2Button]){
|
||||||
UIImage* r2ButtonImage = [UIImage imageNamed:@"R2"];
|
UIImage* r2ButtonImage = [UIImage imageNamed:@"R2"];
|
||||||
UIImage* r2ButtonHdImage = [UIImage imageNamed:@"R2HD"];
|
UIImage* r2ButtonHdImage = [UIImage imageNamed:@"R2HD"];
|
||||||
_r2Button.frame = CGRectMake(R2_X - r2ButtonImage.size.width / 2, R2_Y - r2ButtonImage.size.height / 2, r2ButtonImage.size.width, r2ButtonImage.size.height);
|
_r2Button.frame = CGRectMake(R2_X - r2ButtonImage.size.width / 2, R2_Y - r2ButtonImage.size.height / 2, r2ButtonImage.size.width, r2ButtonImage.size.height);
|
||||||
_r2Button.contents = (id) r2ButtonHdImage.CGImage;
|
_r2Button.contents = (id) r2ButtonHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_r2Button];
|
[_view.layer addSublayer:_r2Button];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) drawSticks {
|
- (void) drawSticks {
|
||||||
// create left analog stick
|
// create left analog stick
|
||||||
UIImage* leftStickBgImage = [UIImage imageNamed:@"StickOuter"];
|
bool hasLeftStick = [_activeCustomOscButtonPositionDict.allKeys containsObject:@"leftStickBackground"];
|
||||||
UIImage* stickBgHdImage = [UIImage imageNamed:@"StickOuterHD"];
|
bool hasRightStick = [_activeCustomOscButtonPositionDict.allKeys containsObject:@"rightStickBackground"];
|
||||||
|
|
||||||
_leftStickBackground.frame = CGRectMake(LS_CENTER_X - leftStickBgImage.size.width / 2, LS_CENTER_Y - leftStickBgImage.size.height / 2, leftStickBgImage.size.width, leftStickBgImage.size.height);
|
if(!hasLeftStick && !hasRightStick) return;
|
||||||
|
|
||||||
|
UIImage* stickBgImage = [UIImage imageNamed:@"StickOuter"];
|
||||||
|
UIImage* stickBgHdImage = [UIImage imageNamed:@"StickOuterHD"];
|
||||||
|
UIImage* stickImage = [UIImage imageNamed:@"StickInner"];
|
||||||
|
UIImage* stickHdImage = [UIImage imageNamed:@"StickInnerHD"];
|
||||||
|
|
||||||
|
if(hasLeftStick){
|
||||||
|
_leftStickBackground.frame = CGRectMake(LS_CENTER_X - stickBgImage.size.width / 2, LS_CENTER_Y - stickBgImage.size.height / 2, stickBgImage.size.width, stickBgImage.size.height);
|
||||||
_leftStickBackground.contents = (id) stickBgHdImage.CGImage;
|
_leftStickBackground.contents = (id) stickBgHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_leftStickBackground];
|
[_view.layer addSublayer:_leftStickBackground];
|
||||||
|
|
||||||
UIImage* leftStickImage = [UIImage imageNamed:@"StickInner"];
|
_leftStick.frame = CGRectMake(LS_CENTER_X - stickImage.size.width / 2, LS_CENTER_Y - stickImage.size.height / 2, stickImage.size.width, stickImage.size.height);
|
||||||
UIImage* stickHdImage = [UIImage imageNamed:@"StickInnerHD"];
|
|
||||||
_leftStick.frame = CGRectMake(LS_CENTER_X - leftStickImage.size.width / 2, LS_CENTER_Y - leftStickImage.size.height / 2, leftStickImage.size.width, leftStickImage.size.height);
|
|
||||||
_leftStick.contents = (id) stickHdImage.CGImage;
|
_leftStick.contents = (id) stickHdImage.CGImage;
|
||||||
_leftStick.opacity = _leftStickOpacity; // make stick half transparent when it's idle
|
_leftStick.opacity = _leftStickOpacity; // make stick half transparent when it's idle
|
||||||
[_view.layer addSublayer:_leftStick];
|
[_view.layer addSublayer:_leftStick];
|
||||||
|
}
|
||||||
|
|
||||||
// create right analog stick
|
// create right analog stick
|
||||||
UIImage* rightStickBgImage = [UIImage imageNamed:@"StickOuter"];
|
if(hasRightStick){
|
||||||
_rightStickBackground.frame = CGRectMake(RS_CENTER_X - rightStickBgImage.size.width / 2, RS_CENTER_Y - rightStickBgImage.size.height / 2, rightStickBgImage.size.width, rightStickBgImage.size.height);
|
_rightStickBackground.frame = CGRectMake(RS_CENTER_X - stickBgImage.size.width / 2, RS_CENTER_Y - stickBgImage.size.height / 2, stickBgImage.size.width, stickBgImage.size.height);
|
||||||
_rightStickBackground.contents = (id) stickBgHdImage.CGImage;
|
_rightStickBackground.contents = (id) stickBgHdImage.CGImage;
|
||||||
[_view.layer addSublayer:_rightStickBackground];
|
[_view.layer addSublayer:_rightStickBackground];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UIImage* rightStickImage = [UIImage imageNamed:@"StickInner"];
|
_rightStick.frame = CGRectMake(RS_CENTER_X - stickImage.size.width / 2, RS_CENTER_Y - stickImage.size.height / 2, stickImage.size.width, stickImage.size.height);
|
||||||
_rightStick.frame = CGRectMake(RS_CENTER_X - rightStickImage.size.width / 2, RS_CENTER_Y - rightStickImage.size.height / 2, rightStickImage.size.width, rightStickImage.size.height);
|
|
||||||
|
|
||||||
_rightStick.contents = (id) stickHdImage.CGImage;
|
_rightStick.contents = (id) stickHdImage.CGImage;
|
||||||
_rightStick.opacity = _rightStickOpacity; // make stick half transparent when it's idle
|
_rightStick.opacity = _rightStickOpacity; // make stick half transparent when it's idle
|
||||||
[_view.layer addSublayer:_rightStick];
|
[_view.layer addSublayer:_rightStick];
|
||||||
|
}
|
||||||
|
|
||||||
// make stick larger
|
// make stick larger
|
||||||
if(_largerStickLR1){
|
if(_largerStickLR1){
|
||||||
// sticks are resized here by the sizefactor persisted in the osc profile.
|
// sticks are resized here by the sizefactor persisted in the osc profile.
|
||||||
RIGHT_STICK_INNER_SIZE = rightStickImage.size.width *1.33 * _rightStickSizeFactor;
|
RIGHT_STICK_INNER_SIZE = stickImage.size.width *1.33 * _rightStickSizeFactor;
|
||||||
RIGHT_STICK_OUTER_SIZE = rightStickBgImage.size.width *1.10 * _rightStickSizeFactor;
|
RIGHT_STICK_OUTER_SIZE = stickBgImage.size.width *1.10 * _rightStickSizeFactor;
|
||||||
_rightStick.bounds = CGRectMake(0, 0, RIGHT_STICK_INNER_SIZE, RIGHT_STICK_INNER_SIZE);
|
_rightStick.bounds = CGRectMake(0, 0, RIGHT_STICK_INNER_SIZE, RIGHT_STICK_INNER_SIZE);
|
||||||
_rightStickBackground.bounds = CGRectMake(0, 0, RIGHT_STICK_OUTER_SIZE, RIGHT_STICK_OUTER_SIZE);
|
_rightStickBackground.bounds = CGRectMake(0, 0, RIGHT_STICK_OUTER_SIZE, RIGHT_STICK_OUTER_SIZE);
|
||||||
|
|
||||||
LEFT_STICK_INNER_SIZE = rightStickImage.size.width *1.33 * _leftStickSizeFactor;
|
LEFT_STICK_INNER_SIZE = stickImage.size.width *1.33 * _leftStickSizeFactor;
|
||||||
LEFT_STICK_OUTER_SIZE = rightStickBgImage.size.width *1.10 * _leftStickSizeFactor;
|
LEFT_STICK_OUTER_SIZE = stickBgImage.size.width *1.10 * _leftStickSizeFactor;
|
||||||
_leftStick.bounds = CGRectMake(0, 0, LEFT_STICK_INNER_SIZE, LEFT_STICK_INNER_SIZE);
|
_leftStick.bounds = CGRectMake(0, 0, LEFT_STICK_INNER_SIZE, LEFT_STICK_INNER_SIZE);
|
||||||
_leftStickBackground.bounds = CGRectMake(0, 0, LEFT_STICK_OUTER_SIZE, LEFT_STICK_OUTER_SIZE);
|
_leftStickBackground.bounds = CGRectMake(0, 0, LEFT_STICK_OUTER_SIZE, LEFT_STICK_OUTER_SIZE);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// sticks are resized here by the sizefactor persisted in the osc profile.
|
// sticks are resized here by the sizefactor persisted in the osc profile.
|
||||||
RIGHT_STICK_INNER_SIZE = rightStickImage.size.width * _rightStickSizeFactor;
|
RIGHT_STICK_INNER_SIZE = stickImage.size.width * _rightStickSizeFactor;
|
||||||
RIGHT_STICK_OUTER_SIZE = rightStickBgImage.size.width * _rightStickSizeFactor;
|
RIGHT_STICK_OUTER_SIZE = stickBgImage.size.width * _rightStickSizeFactor;
|
||||||
_rightStick.bounds = CGRectMake(0, 0, RIGHT_STICK_INNER_SIZE, RIGHT_STICK_INNER_SIZE);
|
_rightStick.bounds = CGRectMake(0, 0, RIGHT_STICK_INNER_SIZE, RIGHT_STICK_INNER_SIZE);
|
||||||
_rightStickBackground.bounds = CGRectMake(0, 0, RIGHT_STICK_OUTER_SIZE, RIGHT_STICK_OUTER_SIZE);
|
_rightStickBackground.bounds = CGRectMake(0, 0, RIGHT_STICK_OUTER_SIZE, RIGHT_STICK_OUTER_SIZE);
|
||||||
|
|
||||||
LEFT_STICK_INNER_SIZE = rightStickImage.size.width * _leftStickSizeFactor;
|
LEFT_STICK_INNER_SIZE = stickImage.size.width * _leftStickSizeFactor;
|
||||||
LEFT_STICK_OUTER_SIZE = rightStickBgImage.size.width * _leftStickSizeFactor;
|
LEFT_STICK_OUTER_SIZE = stickBgImage.size.width * _leftStickSizeFactor;
|
||||||
_leftStick.bounds = CGRectMake(0, 0, LEFT_STICK_INNER_SIZE, LEFT_STICK_INNER_SIZE);
|
_leftStick.bounds = CGRectMake(0, 0, LEFT_STICK_INNER_SIZE, LEFT_STICK_INNER_SIZE);
|
||||||
_leftStickBackground.bounds = CGRectMake(0, 0, LEFT_STICK_OUTER_SIZE, LEFT_STICK_OUTER_SIZE);
|
_leftStickBackground.bounds = CGRectMake(0, 0, LEFT_STICK_OUTER_SIZE, LEFT_STICK_OUTER_SIZE);
|
||||||
}
|
}
|
||||||
@@ -1992,5 +2068,12 @@ static float L3_Y;
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc{
|
||||||
|
for(CALayer* layer in self.OSCButtonLayerPool){
|
||||||
|
[layer removeFromSuperlayer];
|
||||||
|
}
|
||||||
|
[self.OSCButtonLayerPool removeAllObjects];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -9,12 +9,13 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
@objc class PencilHandler: UIResponder {
|
@objc class PencilHandler: UIResponder, UIPencilInteractionDelegate {
|
||||||
@objc static var sharedInstance: PencilHandler?
|
@objc static var shared: PencilHandler?
|
||||||
|
|
||||||
/// 用来处理所有 touch 事件的宿主视图
|
/// 用来处理所有 touch 事件的宿主视图
|
||||||
weak var streamView: UIView?
|
weak var streamView: UIView?
|
||||||
// private var tickTimer: SafeTimer
|
// private var tickTimer: SafeTimer
|
||||||
|
private var pencilInteraction: Any?
|
||||||
private var streamAspectRatio: Float
|
private var streamAspectRatio: Float
|
||||||
private var tickInterval: TimeInterval
|
private var tickInterval: TimeInterval
|
||||||
private var manualTick: Bool
|
private var manualTick: Bool
|
||||||
@@ -22,6 +23,12 @@ import UIKit
|
|||||||
private var pressureCurveEnabled: Bool = false
|
private var pressureCurveEnabled: Bool = false
|
||||||
private var manualHoverFlag: Bool = false
|
private var manualHoverFlag: Bool = false
|
||||||
private var autoHoverFlag: Bool = false
|
private var autoHoverFlag: Bool = false
|
||||||
|
private(set) var pencilProEnabled: Bool = false
|
||||||
|
@objc static private(set) var isDrawing: Bool = false
|
||||||
|
@objc static private(set) var pencilPausesNativeTouch: Bool = false
|
||||||
|
|
||||||
|
// static private let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
|
static private var selectedProfile:OSCProfile?
|
||||||
|
|
||||||
private var pressureLUT = PressureCurveLUT(curve: PressureCurve())
|
private var pressureLUT = PressureCurveLUT(curve: PressureCurve())
|
||||||
|
|
||||||
@@ -33,22 +40,36 @@ import UIKit
|
|||||||
pencilTickEnabled = settings.pencilTickMode.intValue != PencilTickMode.PencilTickDisabled.rawValue
|
pencilTickEnabled = settings.pencilTickMode.intValue != PencilTickMode.PencilTickDisabled.rawValue
|
||||||
super.init()
|
super.init()
|
||||||
setupPressureLUT()
|
setupPressureLUT()
|
||||||
PencilHandler.sharedInstance = self
|
PencilHandler.shared = self
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setupPressureLUT(){
|
public func setupPressureLUT(){
|
||||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
let oscProfile = oscProfileMan.getSelectedProfile()
|
PencilHandler.selectedProfile = oscProfileMan.getSelectedProfile()
|
||||||
pressureCurveEnabled = oscProfile.pressureCurveEnabled
|
guard let selectedProfile = PencilHandler.selectedProfile else {return}
|
||||||
|
|
||||||
|
if selectedProfile.eraserShortcut != "" {
|
||||||
|
doubleTapShorcuts.append(selectedProfile.eraserShortcut)
|
||||||
|
}
|
||||||
|
if selectedProfile.brushShortcut != "" {
|
||||||
|
doubleTapShorcuts.append(selectedProfile.brushShortcut)
|
||||||
|
}
|
||||||
|
|
||||||
|
pressureCurveEnabled = selectedProfile.pressureCurveEnabled
|
||||||
|
|
||||||
if #available(iOS 15.0, *) {
|
if #available(iOS 15.0, *) {
|
||||||
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
||||||
self.pressureCurveEnabled = self.pressureCurveEnabled && info.valid
|
self.pressureCurveEnabled = self.pressureCurveEnabled && info.valid
|
||||||
self.pencilTickEnabled = self.pencilTickEnabled && info.valid
|
self.pencilTickEnabled = self.pencilTickEnabled && info.valid
|
||||||
|
self.pencilProEnabled = info.valid
|
||||||
|
PencilHandler.pencilPausesNativeTouch = selectedProfile.pencilPausesNativeTouch && info.valid
|
||||||
|
if info.valid {
|
||||||
|
self.setupPencilInteraction(view: self.streamView)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let persistedCurvePoints = PressureCurve.importCurvePoints(oscProfile.pressureCurvePoints)
|
let persistedCurvePoints = PressureCurve.importCurvePoints(selectedProfile.pressureCurvePoints)
|
||||||
let curve = PressureCurve()
|
let curve = PressureCurve()
|
||||||
curve.polylinePoints = persistedCurvePoints
|
curve.polylinePoints = persistedCurvePoints
|
||||||
curve.buildCurveSegments()
|
curve.buildCurveSegments()
|
||||||
@@ -61,6 +82,7 @@ import UIKit
|
|||||||
|
|
||||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
guard let event = event else { return }
|
guard let event = event else { return }
|
||||||
|
PencilHandler.isDrawing = true
|
||||||
for touch in touches {
|
for touch in touches {
|
||||||
let coalesced = event.coalescedTouches(for: touch) ?? []
|
let coalesced = event.coalescedTouches(for: touch) ?? []
|
||||||
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
|
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
|
||||||
@@ -189,13 +211,16 @@ import UIKit
|
|||||||
|
|
||||||
DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) {
|
DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) {
|
||||||
LiSendPenEvent(eventType, UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), targetForce, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
|
LiSendPenEvent(eventType, UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), targetForce, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
|
||||||
|
if eventType == UInt8(LI_TOUCH_EVENT_UP) {
|
||||||
|
PencilHandler.isDrawing = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dispatchMoment + tickMoment + delay
|
return dispatchMoment + tickMoment + delay
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public func switchPencilHoever(){
|
@objc public func switchPencilHover(){
|
||||||
manualHoverFlag = !manualHoverFlag
|
manualHoverFlag = !manualHoverFlag
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +232,145 @@ import UIKit
|
|||||||
manualHoverFlag = false
|
manualHoverFlag = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 12.1, *)
|
||||||
|
private func setupPencilInteraction(view:UIView?) {
|
||||||
|
let interaction = UIPencilInteraction()
|
||||||
|
guard let view else { return }
|
||||||
|
interaction.delegate = self
|
||||||
|
view.addInteraction(interaction)
|
||||||
|
pencilInteraction = interaction
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 12.1, *)
|
||||||
|
func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {
|
||||||
|
if !pencilProEnabled {return}
|
||||||
|
if doubleTapShorcuts.isEmpty {return}
|
||||||
|
let keyStrings = CommandManager.shared.extractKeyStrings(from: doubleTapShorcuts[shorcutIndex])
|
||||||
|
CommandManager.shared.sendKeyComboCommand(keyboardCmdStrings: keyStrings, delay: 0.1)
|
||||||
|
shorcutIndex = (shorcutIndex + 1) % doubleTapShorcuts.count
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 17.5, *)
|
||||||
|
func pencilInteraction(
|
||||||
|
_ interaction: UIPencilInteraction,
|
||||||
|
didReceiveSqueeze squeeze: UIPencilInteraction.Squeeze
|
||||||
|
) {
|
||||||
|
switch squeeze.phase {
|
||||||
|
case .began:
|
||||||
|
break
|
||||||
|
case .ended, .cancelled:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static private(set) var eraserShortcut:String = ""
|
||||||
|
@objc static private(set) var brushShortcut:String = ""
|
||||||
|
private var doubleTapShorcuts: Array<String> = []
|
||||||
|
private var shorcutIndex: Int = 0
|
||||||
|
|
||||||
|
@objc func replaceBrush(with shortcut:String){
|
||||||
|
if let i = doubleTapShorcuts.indices.last {
|
||||||
|
doubleTapShorcuts[i] = shortcut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func replaceEraser(with shortcut:String){
|
||||||
|
if let i = doubleTapShorcuts.indices.first {
|
||||||
|
doubleTapShorcuts[i] = shortcut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static public func enterDoubleTapShortcuts(in viewController: UIViewController){
|
||||||
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
|
selectedProfile = oscProfileMan.getSelectedProfile()
|
||||||
|
guard let selectedProfile = selectedProfile else {return}
|
||||||
|
|
||||||
|
let alert = UIAlertController(title: SwiftLocalizationHelper.localizedString(forKey: "Eraser Shortcut"),
|
||||||
|
message: SwiftLocalizationHelper.localizedString(forKey: "Enter eraser keyboard shortcut:"),
|
||||||
|
preferredStyle: .alert)
|
||||||
|
|
||||||
|
alert.addTextField { textField in
|
||||||
|
textField.placeholder = SwiftLocalizationHelper.localizedString(forKey:"Example: e, ctrl+e, alt+e ...")
|
||||||
|
textField.keyboardType = .asciiCapable
|
||||||
|
textField.autocorrectionType = .no
|
||||||
|
textField.spellCheckingType = .no
|
||||||
|
textField.text = selectedProfile.eraserShortcut
|
||||||
|
}
|
||||||
|
|
||||||
|
let okAction = UIAlertAction(title: SwiftLocalizationHelper.localizedString(forKey: "OK"), style: .default) { _ in
|
||||||
|
let keyboardShortcut = alert.textFields?[0].text ?? ""
|
||||||
|
let keyStrings = CommandManager.shared.extractKeyStrings(from: keyboardShortcut)
|
||||||
|
if keyStrings?.count ?? 0 > 0 || keyboardShortcut == "" {
|
||||||
|
eraserShortcut = keyboardShortcut
|
||||||
|
}
|
||||||
|
enterBrushShortcut(in: viewController)
|
||||||
|
}
|
||||||
|
|
||||||
|
let learnMoreAction = UIAlertAction(title: SwiftLocalizationHelper.localizedString(forKey: "Learn More"), style: .default) { _ in
|
||||||
|
if let url = URL(string: SwiftLocalizationHelper.localizedString(forKey: "pencilKeyboardCmdURL")) {
|
||||||
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.addAction(learnMoreAction)
|
||||||
|
alert.addAction(okAction)
|
||||||
|
|
||||||
|
viewController.present(alert, animated: true, completion: {
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc static public func enterBrushShortcut(in viewController: UIViewController){
|
||||||
|
|
||||||
|
let alert = UIAlertController(title: SwiftLocalizationHelper.localizedString(forKey: "Brush Shortcut"),
|
||||||
|
message: SwiftLocalizationHelper.localizedString(forKey: "Enter brush keyboard shortcut:"),
|
||||||
|
preferredStyle: .alert)
|
||||||
|
|
||||||
|
alert.addTextField { textField in
|
||||||
|
textField.placeholder = SwiftLocalizationHelper.localizedString(forKey:"Example: b, ctrl+b, alt+b ...")
|
||||||
|
textField.keyboardType = .asciiCapable
|
||||||
|
textField.autocorrectionType = .no
|
||||||
|
textField.spellCheckingType = .no
|
||||||
|
textField.text = selectedProfile?.brushShortcut
|
||||||
|
}
|
||||||
|
|
||||||
|
let okAction = UIAlertAction(title: SwiftLocalizationHelper.localizedString(forKey: "OK"), style: .default) { _ in
|
||||||
|
let keyboardShortcut = alert.textFields?[0].text ?? ""
|
||||||
|
let keyStrings = CommandManager.shared.extractKeyStrings(from: keyboardShortcut)
|
||||||
|
if keyStrings?.count ?? 0 > 0 || keyboardShortcut == "" {
|
||||||
|
brushShortcut = keyboardShortcut
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedProfile?.brushShortcut != brushShortcut
|
||||||
|
|| selectedProfile?.eraserShortcut != eraserShortcut {
|
||||||
|
guard let selectedProfile = selectedProfile else {return}
|
||||||
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
|
selectedProfile.brushShortcut = brushShortcut
|
||||||
|
selectedProfile.eraserShortcut = eraserShortcut
|
||||||
|
oscProfileMan.replaceSelectedProfile(with: selectedProfile, overwriteDefault: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let learnMoreAction = UIAlertAction(title: SwiftLocalizationHelper.localizedString(forKey: "Learn More"), style: .default) { _ in
|
||||||
|
if let url = URL(string: SwiftLocalizationHelper.localizedString(forKey: "pencilKeyboardCmdURL")) {
|
||||||
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.addAction(learnMoreAction)
|
||||||
|
alert.addAction(okAction)
|
||||||
|
|
||||||
|
viewController.present(alert, animated: true, completion: {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private func attachHoverLeave(normalizedLocation:CGPoint){
|
private func attachHoverLeave(normalizedLocation:CGPoint){
|
||||||
DispatchQueue.global().asyncAfter(deadline: .now()+0.0086) {
|
DispatchQueue.global().asyncAfter(deadline: .now()+0.0086) {
|
||||||
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, 0, 0)
|
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, 0, 0)
|
||||||
|
|||||||
@@ -675,7 +675,7 @@ class PressureCurveViewController: UIViewController {
|
|||||||
buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"),
|
buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"),
|
||||||
countdown: 0,
|
countdown: 0,
|
||||||
completion: {
|
completion: {
|
||||||
PencilHandler.sharedInstance?.setupPressureLUT()
|
PencilHandler.shared?.setupPressureLUT()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
#include <Limelight.h>
|
#include <Limelight.h>
|
||||||
|
|
||||||
@implementation PureNativeTouchHandler {
|
@implementation PureNativeTouchHandler {
|
||||||
StreamView* streamView;
|
|
||||||
TemporarySettings* currentSettings;
|
TemporarySettings* currentSettings;
|
||||||
|
__weak StreamView* streamView;
|
||||||
bool activateCoordSelector;
|
bool activateCoordSelector;
|
||||||
CGFloat pointerVelocityDividerLocationByPoints;
|
CGFloat pointerVelocityDividerLocationByPoints;
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
|
|||||||
UIGestureRecognizer* remoteLongPressRecognizer;
|
UIGestureRecognizer* remoteLongPressRecognizer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
StreamView* streamView;
|
__weak StreamView* streamView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings {
|
- (id)initWithView:(StreamView*)view andSettings:(TemporarySettings*)settings {
|
||||||
|
|||||||
@@ -34,13 +34,14 @@
|
|||||||
@interface StreamView : UIView <X1KitMouseDelegate, UITextFieldDelegate, UIPointerInteractionDelegate>
|
@interface StreamView : UIView <X1KitMouseDelegate, UITextFieldDelegate, UIPointerInteractionDelegate>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@property (assign, nonatomic) UIView* streamFrameTopLayerView;
|
@property (weak, nonatomic) UIView* streamFrameTopLayerView;
|
||||||
|
@property (weak, nonatomic) id<UserInteractionDelegate> interactionDelegate;
|
||||||
@property (assign, nonatomic) CGFloat streamAspectRatio;
|
@property (assign, nonatomic) CGFloat streamAspectRatio;
|
||||||
@property (assign, nonatomic) CGRect originalFrame;
|
@property (assign, nonatomic) CGRect originalFrame;
|
||||||
@property (assign, nonatomic) bool widgetToolOpened;
|
@property (assign, nonatomic) bool widgetToolOpened;
|
||||||
@property (strong, nonatomic) OnScreenControls* onScreenControls;
|
@property (strong, nonatomic) OnScreenControls* onScreenControls;
|
||||||
@property (weak, nonatomic) PencilHandler* pencilHandler;
|
@property (weak, nonatomic) PencilHandler* pencilHandler;
|
||||||
|
@property (weak, nonatomic) UIViewController* streamFrameVC;
|
||||||
|
|
||||||
- (void) setupStreamView:(ControllerSupport*)controllerSupport
|
- (void) setupStreamView:(ControllerSupport*)controllerSupport
|
||||||
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
|
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
|
||||||
@@ -48,7 +49,9 @@
|
|||||||
streamFrameTopLayerView:(UIView* )topLayerView
|
streamFrameTopLayerView:(UIView* )topLayerView
|
||||||
;
|
;
|
||||||
|
|
||||||
- (void) showOnScreenControls;
|
- (void)cleanUp;
|
||||||
|
|
||||||
|
- (void) reloadLegacyWidgets:(OSCProfile* )profile;
|
||||||
- (void) setOnScreenControls;
|
- (void) setOnScreenControls;
|
||||||
- (void) disableOnScreenControls;
|
- (void) disableOnScreenControls;
|
||||||
- (void) reloadOnScreenControlsRealtimeWith:(ControllerSupport*)controllerSupport
|
- (void) reloadOnScreenControlsRealtimeWith:(ControllerSupport*)controllerSupport
|
||||||
@@ -56,7 +59,7 @@
|
|||||||
- (void) reloadOnScreenControlsWith:(ControllerSupport*)controllerSupport
|
- (void) reloadOnScreenControlsWith:(ControllerSupport*)controllerSupport
|
||||||
andConfig:(StreamConfiguration*)streamConfig;
|
andConfig:(StreamConfiguration*)streamConfig;
|
||||||
- (void) clearOnScreenWidgets;
|
- (void) clearOnScreenWidgets;
|
||||||
- (void) reloadOnScreenWidgetViews;
|
- (void) reloadOnScreenWidgetViews:(bool)reload;
|
||||||
- (void) saveRelocatedWidgetViews;
|
- (void) saveRelocatedWidgetViews;
|
||||||
- (bool) isOnScreenWidgetEnabled;
|
- (bool) isOnScreenWidgetEnabled;
|
||||||
|
|
||||||
@@ -75,6 +78,7 @@
|
|||||||
|
|
||||||
- (void)enablePencilHover;
|
- (void)enablePencilHover;
|
||||||
- (void)disablePencilHover;
|
- (void)disablePencilHover;
|
||||||
|
- (void)setAllowSingleTouchEnabled:(BOOL)enabled;
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
- (void) updateCursorLocation:(CGPoint)location isMouse:(BOOL)isMouse;
|
- (void) updateCursorLocation:(CGPoint)location isMouse:(BOOL)isMouse;
|
||||||
|
|||||||
+132
-81
@@ -26,6 +26,7 @@
|
|||||||
#import "KeyboardInputField.h"
|
#import "KeyboardInputField.h"
|
||||||
#import "CustomTapGestureRecognizer.h"
|
#import "CustomTapGestureRecognizer.h"
|
||||||
#import "LocalizationHelper.h"
|
#import "LocalizationHelper.h"
|
||||||
|
#import "StreamFrameViewController.h"
|
||||||
|
|
||||||
|
|
||||||
static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||||
@@ -34,8 +35,6 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
Stream Video has been moved out of this class to _renderView in StreamFrameViewController.
|
Stream Video has been moved out of this class to _renderView in StreamFrameViewController.
|
||||||
*/
|
*/
|
||||||
@implementation StreamView {
|
@implementation StreamView {
|
||||||
UIView* streamFrameTopLayerView;
|
|
||||||
UIViewController* streamFrameVC;
|
|
||||||
|
|
||||||
TemporarySettings* settings;
|
TemporarySettings* settings;
|
||||||
|
|
||||||
@@ -59,7 +58,6 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
UIResponder* touchHandler;
|
UIResponder* touchHandler;
|
||||||
|
|
||||||
id<UserInteractionDelegate> interactionDelegate;
|
|
||||||
NSTimer* interactionTimer;
|
NSTimer* interactionTimer;
|
||||||
BOOL hasUserInteracted;
|
BOOL hasUserInteracted;
|
||||||
|
|
||||||
@@ -85,9 +83,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
streamFrameTopLayerView:(UIView* )topLayerView{
|
streamFrameTopLayerView:(UIView* )topLayerView{
|
||||||
self->comboKeyModifierFlags = (UIKeyModifierControl|UIKeyModifierAlternate|UIKeyModifierShift);
|
self->comboKeyModifierFlags = (UIKeyModifierControl|UIKeyModifierAlternate|UIKeyModifierShift);
|
||||||
|
|
||||||
self->streamFrameTopLayerView = topLayerView;
|
self->_streamFrameTopLayerView = topLayerView;
|
||||||
self.streamFrameTopLayerView = topLayerView; // this will be used as a read-only pointer for other class
|
self->_interactionDelegate = interactionDelegate;
|
||||||
self->interactionDelegate = interactionDelegate;
|
|
||||||
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
|
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
|
||||||
self.streamAspectRatio = self->streamAspectRatio;
|
self.streamAspectRatio = self->streamAspectRatio;
|
||||||
_widgetSizeTransition = keepWidgetSize;
|
_widgetSizeTransition = keepWidgetSize;
|
||||||
@@ -128,8 +125,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
||||||
#else
|
#else
|
||||||
|
|
||||||
PencilHandler.sharedInstance = [[PencilHandler alloc] initWithStreamView:self settings:settings];
|
PencilHandler.shared = [[PencilHandler alloc] initWithStreamView:self settings:settings];
|
||||||
_pencilHandler = PencilHandler.sharedInstance;
|
_pencilHandler = PencilHandler.shared;
|
||||||
|
|
||||||
// iOS uses touch Mode depending on user preference
|
// iOS uses touch Mode depending on user preference
|
||||||
|
|
||||||
@@ -160,8 +157,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we'll render on-screen controls on the toplayer too:
|
// we'll render on-screen controls on the toplayer too:
|
||||||
_onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig]; // don't delete, this is mandatory
|
_onScreenControls = [[OnScreenControls alloc] initWithView:self->_streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig]; // don't delete, this is mandatory
|
||||||
OnScreenControls.shared = _onScreenControls;
|
// OnScreenControls.shared = _onScreenControls;
|
||||||
/*
|
/*
|
||||||
// here we pass the tap recognizer to the onscreencontrols obj
|
// here we pass the tap recognizer to the onscreencontrols obj
|
||||||
if (settings.touchMode.intValue == RelativeTouch){
|
if (settings.touchMode.intValue == RelativeTouch){
|
||||||
@@ -400,7 +397,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
// Notify the delegate if this was a new user interaction
|
// Notify the delegate if this was a new user interaction
|
||||||
if (!timerAlreadyRunning) {
|
if (!timerAlreadyRunning) {
|
||||||
[interactionDelegate userInteractionBegan];
|
[_interactionDelegate userInteractionBegan];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +405,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
if (!hasUserInteracted) {
|
if (!hasUserInteracted) {
|
||||||
// User has finished touching the screen
|
// User has finished touching the screen
|
||||||
interactionTimer = nil;
|
interactionTimer = nil;
|
||||||
[interactionDelegate userInteractionEnded];
|
[_interactionDelegate userInteractionEnded];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// User is still touching the screen. Restart the timer.
|
// User is still touching the screen. Restart the timer.
|
||||||
@@ -416,9 +413,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) showOnScreenControls {
|
- (void) reloadLegacyWidgets:(OSCProfile* )profile {
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
if(!_widgetToolOpened) [_onScreenControls show];
|
if(!_widgetToolOpened) [_onScreenControls showLegacyWidgetsWith:profile];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,16 +443,17 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
- (void) reloadOnScreenControlsRealtimeWith:(ControllerSupport*)controllerSupport
|
- (void) reloadOnScreenControlsRealtimeWith:(ControllerSupport*)controllerSupport
|
||||||
andConfig:(StreamConfiguration*)streamConfig {
|
andConfig:(StreamConfiguration*)streamConfig {
|
||||||
[self reloadOnScreenControlsWith:controllerSupport andConfig:streamConfig];
|
[self reloadOnScreenControlsWith:controllerSupport andConfig:streamConfig];
|
||||||
if([self isOscEnabled]) [self showOnScreenControls];
|
/*
|
||||||
else [self disableOnScreenControls];
|
StreamFrameViewController* vc = (StreamFrameViewController* )_streamFrameVC;
|
||||||
|
if([self isOscEnabled]) [self reloadLegacyWidgets:nil];
|
||||||
|
else [self disableOnScreenControls];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void) reloadOnScreenControlsWith:(ControllerSupport*)controllerSupport
|
- (void) reloadOnScreenControlsWith:(ControllerSupport*)controllerSupport
|
||||||
andConfig:(StreamConfiguration*)streamConfig {
|
andConfig:(StreamConfiguration*)streamConfig {
|
||||||
|
|
||||||
// we'll render on-screen controllers on the toplayer too.
|
// we'll render on-screen controllers on the toplayer too.
|
||||||
_onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig];
|
_onScreenControls = [[OnScreenControls alloc] initWithView:self->_streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig];
|
||||||
/*
|
/*
|
||||||
// pass mouseRightClickTapRecognizer to onScreenControls obj here:
|
// pass mouseRightClickTapRecognizer to onScreenControls obj here:
|
||||||
if([self isOscEnabled]){
|
if([self isOscEnabled]){
|
||||||
@@ -469,7 +467,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
- (void) clearOnScreenWidgets{
|
- (void) clearOnScreenWidgets{
|
||||||
OnScreenWidgetView.isTweakingHighlight = false;
|
OnScreenWidgetView.isTweakingHighlight = false;
|
||||||
for (UIView *subview in self->streamFrameTopLayerView.subviews) {
|
for (UIView *subview in self->_streamFrameTopLayerView.subviews) {
|
||||||
// 检查子视图是否是特定类型的实例
|
// 检查子视图是否是特定类型的实例
|
||||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||||
// 如果是,就添加到将要被移除的数组中
|
// 如果是,就添加到将要被移除的数组中
|
||||||
@@ -480,8 +478,8 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
- (CGPoint)denormalizeWidgetPosition:(CGPoint)position {
|
- (CGPoint)denormalizeWidgetPosition:(CGPoint)position {
|
||||||
if(position.x < 1.0 && position.y < 1.0){
|
if(position.x < 1.0 && position.y < 1.0){
|
||||||
position.x = position.x * streamFrameTopLayerView.bounds.size.width;
|
position.x = position.x * _streamFrameTopLayerView.bounds.size.width;
|
||||||
position.y = position.y * streamFrameTopLayerView.bounds.size.height;
|
position.y = position.y * _streamFrameTopLayerView.bounds.size.height;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
NSLog(@"invalid coords");
|
NSLog(@"invalid coords");
|
||||||
@@ -498,23 +496,25 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
- (void)saveRelocatedWidgetViews{
|
- (void)saveRelocatedWidgetViews{
|
||||||
NSMutableDictionary* relocatedWidgetDict = [NSMutableDictionary dictionary];
|
NSMutableDictionary* relocatedWidgetDict = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
for(UIView* subview in self->streamFrameTopLayerView.subviews){
|
for(UIView* subview in self->_streamFrameTopLayerView.subviews){
|
||||||
if([subview isKindOfClass:[OnScreenWidgetView class]]){
|
if([subview isKindOfClass:[OnScreenWidgetView class]]){
|
||||||
OnScreenWidgetView* widget = (OnScreenWidgetView* )subview;
|
OnScreenWidgetView* widget = (OnScreenWidgetView* )subview;
|
||||||
if(widget.relocatedDuringStreaming) [relocatedWidgetDict setObject:widget forKey:widget.identifier];
|
if(widget.relocatedDuringStreaming) [relocatedWidgetDict setObject:widget forKey:@(widget.sequence)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSLog(@"relocatedWidgetDict.allKeys.count %d, %f", relocatedWidgetDict.allKeys.count, CACurrentMediaTime());
|
||||||
|
|
||||||
if(relocatedWidgetDict.allKeys.count == 0) return;
|
if(relocatedWidgetDict.allKeys.count == 0) return;
|
||||||
|
|
||||||
oscProfileMan = [OSCProfilesManager sharedManager:self->streamFrameTopLayerView.bounds];
|
oscProfileMan = [OSCProfilesManager sharedManager:self->_streamFrameTopLayerView.bounds];
|
||||||
OSCProfile *newProfile = [oscProfileMan getSelectedProfile];
|
OSCProfile *newProfile = [oscProfileMan getSelectedProfile];
|
||||||
|
|
||||||
for (NSInteger i = 0; i < newProfile.buttonStatesEncoded.count; i++) {
|
for (NSInteger i = 0; i < newProfile.buttonStatesEncoded.count; i++) {
|
||||||
NSData* buttonStateEncoded = newProfile.buttonStatesEncoded[i];
|
NSData* buttonStateEncoded = newProfile.buttonStatesEncoded[i];
|
||||||
OnScreenButtonState *newButtonState = [oscProfileMan unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState *newButtonState = [oscProfileMan unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
if([relocatedWidgetDict.allKeys containsObject:newButtonState.identifier]){
|
if([relocatedWidgetDict.allKeys containsObject:@(newButtonState.sequence)]){
|
||||||
OnScreenWidgetView* widget = [relocatedWidgetDict objectForKey:newButtonState.identifier];
|
OnScreenWidgetView* widget = [relocatedWidgetDict objectForKey:@(newButtonState.sequence)];
|
||||||
newButtonState.position = [oscProfileMan normalizeWidgetPosition:widget.center];
|
newButtonState.position = [oscProfileMan normalizeWidgetPosition:widget.center];
|
||||||
NSData *newButtonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:newButtonState requiringSecureCoding:YES error:nil];
|
NSData *newButtonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:newButtonState requiringSecureCoding:YES error:nil];
|
||||||
newProfile.buttonStatesEncoded[i] = newButtonStateEncoded;
|
newProfile.buttonStatesEncoded[i] = newButtonStateEncoded;
|
||||||
@@ -524,41 +524,48 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
[oscProfileMan replaceSelectedProfileWith:newProfile overwriteDefault:NO];
|
[oscProfileMan replaceSelectedProfileWith:newProfile overwriteDefault:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) reloadOnScreenWidgetViews{
|
- (void) reloadOnScreenWidgetViews:(bool)reload{
|
||||||
|
NSLog(@"reloadOnScreenWidgets in streamview %f", CACurrentMediaTime());
|
||||||
|
|
||||||
// NSLog(@"reload on screen keyboard buttons here");
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if(!self->oscProfileMan) self->oscProfileMan = [OSCProfilesManager sharedManager:self->_streamFrameTopLayerView.bounds];
|
||||||
// remove all keyboard widget views first
|
OSCProfile *oscProfile = [self->oscProfileMan getSelectedProfile]; //returns the currently selected OSCProfile
|
||||||
[self clearOnScreenWidgets];
|
MotionHandler* motionHandler = [MotionHandler sharedWithProfile:oscProfile];
|
||||||
|
|
||||||
// get streamFrameVC
|
// get streamFrameVC
|
||||||
if(!streamFrameVC) streamFrameVC = [self parentViewController];
|
if(!self->_streamFrameVC) self->_streamFrameVC = [self parentViewController];
|
||||||
|
|
||||||
// bool customOscEnabled = [self isOscEnabled] && settings.onscreenControls.intValue == OnScreenControlsLevelCustom;
|
// bool customOscEnabled = [self isOscEnabled] && settings.onscreenControls.intValue == OnScreenControlsLevelCustom;
|
||||||
|
|
||||||
if(![self isOnScreenWidgetEnabled]) return;
|
if(![self isOnScreenWidgetEnabled]) return;
|
||||||
|
|
||||||
OnScreenWidgetView.buttonVisualFeedbackEnabled = settings.buttonVisualFeedback;
|
OnScreenWidgetView.buttonVisualFeedbackEnabled = self->settings.buttonVisualFeedback;
|
||||||
|
|
||||||
if(!oscProfileMan) oscProfileMan = [OSCProfilesManager sharedManager:self->streamFrameTopLayerView.bounds];
|
bool hasLegacyWidget = false;
|
||||||
OSCProfile *oscProfile = [oscProfileMan getSelectedProfile]; //returns the currently selected OSCProfile
|
if(reload && !OnScreenWidgetView.editMode){
|
||||||
MotionHandler* motionHandler = [MotionHandler sharedInstance];
|
// remove all keyboard widget views first
|
||||||
|
[self clearOnScreenWidgets];
|
||||||
|
|
||||||
if(!OnScreenWidgetView.editMode){ // in edit mode, keyboard widget view will be updated within layoutool view controller.
|
bool sequenceGenerated = false;
|
||||||
|
bool hasMovableWidget = false;
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
for (NSInteger i = 0; i < oscProfile.buttonStatesEncoded.count; i++) {
|
||||||
OnScreenButtonState* buttonState = [oscProfileMan unarchiveButtonStateEncoded:buttonStateEncoded];
|
NSData* buttonStateEncoded = oscProfile.buttonStatesEncoded[i];
|
||||||
|
OnScreenButtonState* buttonState = [self->oscProfileMan unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
if(buttonState.widgetType == CustomOnScreenWidget){
|
if(buttonState.widgetType == CustomOnScreenWidget){
|
||||||
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView
|
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape profile:oscProfile]; //reconstruct widgetView
|
||||||
//--------------------------------------------------
|
|
||||||
_onScreenControls.instanceReceiverDelegate = widgetView; // connecting onScreenControls to OnScreenWidgetView, sending the active instance for touchPad stick control
|
|
||||||
[_onScreenControls sendInstance];
|
|
||||||
//--------------------------------------------------
|
|
||||||
|
|
||||||
widgetView.functionalButtonDelegate = (id<OnScreenFunctionalButtonDelegate>)streamFrameVC;
|
widgetView.functionalButtonDelegate = (id<OnScreenFunctionalButtonDelegate>)self->_streamFrameVC;
|
||||||
widgetView.motionHandler = motionHandler;
|
widgetView.motionHandler = motionHandler;
|
||||||
|
|
||||||
widgetView.identifier = buttonState.identifier;
|
widgetView.sequence = buttonState.sequence == -1 ? i : buttonState.sequence;
|
||||||
|
if(!sequenceGenerated) sequenceGenerated = buttonState.sequence == -1;
|
||||||
|
if(!hasMovableWidget) hasMovableWidget = buttonState.buttonMode == movable;
|
||||||
|
if(sequenceGenerated){
|
||||||
|
NSLog(@"widgetView.sequence %d %f", widgetView.sequence, CACurrentMediaTime());
|
||||||
|
buttonState.sequence = widgetView.sequence;
|
||||||
|
oscProfile.buttonStatesEncoded[i] = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||||
widgetView.widthFactor = buttonState.widthFactor;
|
widgetView.widthFactor = buttonState.widthFactor;
|
||||||
widgetView.heightFactor = buttonState.heightFactor;
|
widgetView.heightFactor = buttonState.heightFactor;
|
||||||
@@ -581,7 +588,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
widgetView.dWheelWalkModeThreshold = buttonState.walkModeThreshold;
|
widgetView.dWheelWalkModeThreshold = buttonState.walkModeThreshold;
|
||||||
widgetView.buttonMode = buttonState.buttonMode;
|
widgetView.buttonMode = buttonState.buttonMode;
|
||||||
// Add the widgetView to the view controller's view
|
// Add the widgetView to the view controller's view
|
||||||
[self->streamFrameTopLayerView addSubview:widgetView]; // add keyboard button to the stream frame view. must add it to the target view before setting location.
|
[self->_streamFrameTopLayerView addSubview:widgetView]; // add keyboard button to the stream frame view. must add it to the target view before setting location.
|
||||||
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
||||||
[widgetView setLocationWithPosition:buttonState.position];
|
[widgetView setLocationWithPosition:buttonState.position];
|
||||||
widgetView.sizeReference = [self getCurrentWidgetSizeReference];
|
widgetView.sizeReference = [self getCurrentWidgetSizeReference];
|
||||||
@@ -594,17 +601,22 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
[widgetView tweakBorderAlphaWithAlpha:buttonState.borderAlpha];
|
[widgetView tweakBorderAlphaWithAlpha:buttonState.borderAlpha];
|
||||||
[widgetView tweakHighlightAlphaWithAlpha:buttonState.highlightAlpha];
|
[widgetView tweakHighlightAlphaWithAlpha:buttonState.highlightAlpha];
|
||||||
[widgetView setupAutoTapTimer];
|
[widgetView setupAutoTapTimer];
|
||||||
[widgetView setupInertialScroller];
|
[widgetView setupInertialScrollerWithFps:self->settings.framerate.intValue];
|
||||||
}
|
}
|
||||||
|
else if(buttonState.widgetType == LegacyOnScreenControls) hasLegacyWidget = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sequenceGenerated && hasMovableWidget){
|
||||||
|
[self->oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t buttonIndex = 9999999;
|
uint64_t buttonIndex = 9999999;
|
||||||
UIView* deepestButton;
|
UIView* deepestButton;
|
||||||
for (UIView *subview in self->streamFrameTopLayerView.subviews) {
|
for (UIView *subview in self->_streamFrameTopLayerView.subviews) {
|
||||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||||
OnScreenWidgetView* widget = (OnScreenWidgetView* ) subview;
|
OnScreenWidgetView* widget = (OnScreenWidgetView* ) subview;
|
||||||
if(widget.widgetType == WidgetTypeEnumButton){
|
if(widget.widgetType == WidgetTypeEnumButton){
|
||||||
uint64_t index = [self->streamFrameTopLayerView.subviews indexOfObject:subview];
|
uint64_t index = [self->_streamFrameTopLayerView.subviews indexOfObject:subview];
|
||||||
if (index<buttonIndex){
|
if (index<buttonIndex){
|
||||||
buttonIndex = index;
|
buttonIndex = index;
|
||||||
deepestButton = subview;
|
deepestButton = subview;
|
||||||
@@ -612,19 +624,27 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!deepestButton) return;
|
if(deepestButton){
|
||||||
|
for (UIView *subview in self->_streamFrameTopLayerView.subviews) {
|
||||||
for (UIView *subview in self->streamFrameTopLayerView.subviews) {
|
|
||||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||||
OnScreenWidgetView* widget = (OnScreenWidgetView* ) subview;
|
OnScreenWidgetView* widget = (OnScreenWidgetView* ) subview;
|
||||||
if(widget.widgetType == WidgetTypeEnumTouchPad){
|
if(widget.widgetType == WidgetTypeEnumTouchPad){
|
||||||
[self->streamFrameTopLayerView insertSubview:subview belowSubview:deepestButton];
|
[self->_streamFrameTopLayerView insertSubview:subview belowSubview:deepestButton];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSLog(@"hasLegacyWidget %d %f", hasLegacyWidget, CACurrentMediaTime());
|
||||||
|
// legacy widgets
|
||||||
|
if(!OnScreenWidgetView.editMode && (hasLegacyWidget || !reload)){
|
||||||
|
if([self isOscEnabled]) [self reloadLegacyWidgets:oscProfile];
|
||||||
|
else [self disableOnScreenControls];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
- (OnScreenControlsLevel) getCurrentOscState {
|
- (OnScreenControlsLevel) getCurrentOscState {
|
||||||
if (_onScreenControls == nil) {
|
if (_onScreenControls == nil) {
|
||||||
return OnScreenControlsLevelOff;
|
return OnScreenControlsLevelOff;
|
||||||
@@ -787,13 +807,17 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
[touchHandler touchesBegan:touches withEvent:event];
|
[touchHandler touchesBegan:touches withEvent:event];
|
||||||
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
||||||
}
|
}
|
||||||
if (@available(iOS 13.4, *)) { // now only pencil events are restricted
|
NSMutableSet* pencilTouches = [NSMutableSet set];
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
if (touch.type == UITouchTypePencil) {
|
if (touch.type == UITouchTypePencil) {
|
||||||
[_pencilHandler touchesBegan:touches withEvent:event];
|
[pencilTouches addObject:touch];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NSMutableSet* nonPencilTouches;
|
||||||
|
if(pencilTouches.count>0){
|
||||||
|
[_pencilHandler touchesBegan:pencilTouches withEvent:event];
|
||||||
|
nonPencilTouches = [touches mutableCopy];
|
||||||
|
[nonPencilTouches minusSet:pencilTouches];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -809,11 +833,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
// Notify of user interaction and start expiration timer
|
// Notify of user interaction and start expiration timer
|
||||||
[self startInteractionTimer];
|
[self startInteractionTimer];
|
||||||
|
|
||||||
|
NSSet* targetTouches = nonPencilTouches ? nonPencilTouches : touches;
|
||||||
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
||||||
[self->_onScreenControls handleTouchDownEvent:touches];
|
[self->_onScreenControls handleTouchDownEvent:targetTouches];
|
||||||
[self->touchHandler touchesBegan:touches withEvent:event];
|
[self->touchHandler touchesBegan:targetTouches withEvent:event];
|
||||||
}
|
}
|
||||||
else if(![_onScreenControls handleTouchDownEvent:touches]) [touchHandler touchesBegan:touches withEvent:event];
|
else if(![_onScreenControls handleTouchDownEvent:targetTouches]) [touchHandler touchesBegan:targetTouches withEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIBarButtonItem *)createButtonWithImageNamed:(NSString *)imageName backgroundColor:(UIColor *)backgroundColor target:(id)target action:(SEL)action keyCode:(NSInteger)keyCode isToggleable:(BOOL)isToggleable {
|
- (UIBarButtonItem *)createButtonWithImageNamed:(NSString *)imageName backgroundColor:(UIColor *)backgroundColor target:(id)target action:(SEL)action keyCode:(NSInteger)keyCode isToggleable:(BOOL)isToggleable {
|
||||||
@@ -944,10 +969,10 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSMutableSet* pencilTouches = [NSMutableSet set];
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
if (touch.type == UITouchTypePencil) {
|
if (touch.type == UITouchTypePencil) {
|
||||||
[_pencilHandler touchesMoved:touches withEvent:event];
|
[pencilTouches addObject:touch];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (@available(iOS 13.4, *)) {
|
if (@available(iOS 13.4, *)) {
|
||||||
UITouch *touch = [touches anyObject];
|
UITouch *touch = [touches anyObject];
|
||||||
@@ -970,14 +995,21 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
NSMutableSet* nonPencilTouches;
|
||||||
|
if(pencilTouches.count>0){
|
||||||
|
[_pencilHandler touchesMoved:pencilTouches withEvent:event];
|
||||||
|
nonPencilTouches = [touches mutableCopy];
|
||||||
|
[nonPencilTouches minusSet:pencilTouches];
|
||||||
|
}
|
||||||
|
|
||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
|
|
||||||
|
NSSet* targetTouches = nonPencilTouches ? nonPencilTouches : touches;
|
||||||
if(self->settings.touchMode.intValue == NativeTouch || self->settings.touchMode.intValue == RelativeTouch){
|
if(self->settings.touchMode.intValue == NativeTouch || self->settings.touchMode.intValue == RelativeTouch){
|
||||||
[self->touchHandler touchesMoved:touches withEvent:event];
|
[self->touchHandler touchesMoved:targetTouches withEvent:event];
|
||||||
[self->_onScreenControls handleTouchMovedEvent:touches];
|
[self->_onScreenControls handleTouchMovedEvent:targetTouches];
|
||||||
}
|
}
|
||||||
else if(![self->_onScreenControls handleTouchMovedEvent:touches]) [self->touchHandler touchesMoved:touches withEvent:event];
|
else if(![self->_onScreenControls handleTouchMovedEvent:targetTouches]) [self->touchHandler touchesMoved:targetTouches withEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) handleKeyCombos:(UIPress*) press{
|
- (void) handleKeyCombos:(UIPress*) press{
|
||||||
@@ -986,19 +1018,19 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
switch (press.key.keyCode) {
|
switch (press.key.keyCode) {
|
||||||
case UIKeyboardHIDUsageKeyboardQ:
|
case UIKeyboardHIDUsageKeyboardQ:
|
||||||
[interactionDelegate streamExitRequested];
|
[_interactionDelegate streamExitRequested];
|
||||||
break;
|
break;
|
||||||
case UIKeyboardHIDUsageKeyboardS:
|
case UIKeyboardHIDUsageKeyboardS:
|
||||||
[interactionDelegate toggleStatsOverlay];
|
[_interactionDelegate toggleStatsOverlay];
|
||||||
break;
|
break;
|
||||||
case UIKeyboardHIDUsageKeyboardM:
|
case UIKeyboardHIDUsageKeyboardM:
|
||||||
[interactionDelegate toggleMouseCapture];
|
[_interactionDelegate toggleMouseCapture];
|
||||||
break;
|
break;
|
||||||
case UIKeyboardHIDUsageKeyboardC:
|
case UIKeyboardHIDUsageKeyboardC:
|
||||||
[interactionDelegate toggleMouseVisible];
|
[_interactionDelegate toggleMouseVisible];
|
||||||
break;
|
break;
|
||||||
case UIKeyboardHIDUsageKeyboardD:
|
case UIKeyboardHIDUsageKeyboardD:
|
||||||
[interactionDelegate disconnectAndQuitApp];
|
[_interactionDelegate disconnectAndQuitApp];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1052,18 +1084,22 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (@available(iOS 13.4, *)){ //now only pencil events are restricted
|
NSMutableSet* pencilTouches = [NSMutableSet set];
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
if (touch.type == UITouchTypePencil) {
|
if (touch.type == UITouchTypePencil) {
|
||||||
[_pencilHandler touchesEnded:touches withEvent:event];
|
[pencilTouches addObject:touch];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NSMutableSet* nonPencilTouches;
|
||||||
|
if(pencilTouches.count>0){
|
||||||
|
[_pencilHandler touchesEnded:pencilTouches withEvent:event];
|
||||||
|
nonPencilTouches = [touches mutableCopy];
|
||||||
|
[nonPencilTouches minusSet:pencilTouches];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
if ([self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
if ([self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
||||||
forTouches:touches
|
forTouches:nonPencilTouches ? nonPencilTouches : touches
|
||||||
withEvent:event]) {
|
withEvent:event]) {
|
||||||
// If it's a mouse event, we're done
|
// If it's a mouse event, we're done
|
||||||
return;
|
return;
|
||||||
@@ -1073,24 +1109,23 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
|
|
||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
|
|
||||||
|
NSSet* targetTouches = nonPencilTouches ? nonPencilTouches : touches;
|
||||||
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
||||||
[self->touchHandler touchesEnded:touches withEvent:event]; // when touches ended, must call the native touchhandler before onScreenControls, since the NSSet of touches captured by on screen button shall be updated later
|
[self->touchHandler touchesEnded:targetTouches withEvent:event]; // when touches ended, must call the native touchhandler before onScreenControls, since the NSSet of touches captured by on screen button shall be updated later
|
||||||
[self->_onScreenControls handleTouchUpEvent:touches];
|
[self->_onScreenControls handleTouchUpEvent:targetTouches];
|
||||||
}
|
}
|
||||||
else if(![_onScreenControls handleTouchUpEvent:touches]) [touchHandler touchesEnded:touches withEvent:event];
|
else if(![_onScreenControls handleTouchUpEvent:targetTouches]) [touchHandler touchesEnded:targetTouches withEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
[touchHandler touchesCancelled:touches withEvent:event];
|
[touchHandler touchesCancelled:touches withEvent:event];
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
if (settings.touchMode.intValue == NativeTouchOnly) return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
if (settings.touchMode.intValue == NativeTouchOnly) return; //This is a native touch oriented fork, in pure native touch mode, this call back method deals with native touch only.
|
||||||
if (@available(iOS 13.4, *)){ //now only pencil events are restricted
|
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
if (touch.type == UITouchTypePencil) {
|
if (touch.type == UITouchTypePencil) {
|
||||||
[self touchesEnded:touches withEvent:event];
|
[self touchesEnded:touches withEvent:event];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
[self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
[self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
||||||
forTouches:touches
|
forTouches:touches
|
||||||
@@ -1434,7 +1469,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)switchPencilHover{
|
- (void)switchPencilHover{
|
||||||
[_pencilHandler switchPencilHoever];
|
[_pencilHandler switchPencilHover];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)enablePencilHover{
|
- (void)enablePencilHover{
|
||||||
@@ -1445,6 +1480,22 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
[_pencilHandler disablePencilHover];
|
[_pencilHandler disablePencilHover];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setAllowSingleTouchEnabled:(BOOL)enabled{
|
||||||
|
if([touchHandler isKindOfClass:[NativeTouchHandler class]]){
|
||||||
|
NativeTouchHandler* handler = (NativeTouchHandler* )touchHandler;
|
||||||
|
[handler setAllowSingleTouchEnabled:enabled];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cleanUp{
|
||||||
|
[keyInputField resignFirstResponder];
|
||||||
|
keyInputField.delegate = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc{
|
||||||
|
NSLog(@"dealloc streamView %f", CACurrentMediaTime());
|
||||||
|
}
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
- (BOOL)isMultipleTouchEnabled {
|
- (BOOL)isMultipleTouchEnabled {
|
||||||
return YES;
|
return YES;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import UIKit
|
|||||||
@objc class UITouchUtil: NSObject {
|
@objc class UITouchUtil: NSObject {
|
||||||
@objc public static func touches(in view: UIView, from event: UIEvent?) -> Set<UITouch> {
|
@objc public static func touches(in view: UIView, from event: UIEvent?) -> Set<UITouch> {
|
||||||
guard (event?.allTouches) != nil else { return [] }
|
guard (event?.allTouches) != nil else { return [] }
|
||||||
return event?.allTouches?.filter({ $0.view == view }) ?? []
|
return event?.allTouches?.filter({ $0.view == view && $0.type == .direct}) ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public static func distance(between touch1: UITouch?, and touch2: UITouch?, in view: UIView?) -> CGFloat {
|
@objc public static func distance(between touch1: UITouch?, and touch2: UITouch?, in view: UIView?) -> CGFloat {
|
||||||
|
|||||||
@@ -1192,6 +1192,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Brush Shortcut" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔刷快捷键"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆刷快速鍵"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆刷快速鍵"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Calibrating..." : {
|
"Calibrating..." : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -2033,6 +2056,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"doubleTapShortcutStackTip" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Brush shortcut: %@\nEraser shortcut: %@"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔刷快捷键: %@\n橡皮擦快捷键: %@"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆刷快速鍵: %@\n橡皮擦快速鍵: %@"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆刷快速鍵: %@\n橡皮擦快速鍵: %@"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Down" : {
|
"Down" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -2281,6 +2333,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Enter brush keyboard shortcut:" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "输入笔刷快捷键:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "输入筆刷快速鍵:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "输入筆刷快速鍵:"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Enter Custom Resolution" : {
|
"Enter Custom Resolution" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -2304,6 +2379,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Enter eraser keyboard shortcut:" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "输入橡皮擦快捷键:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "輸入橡皮擦快速鍵:"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "輸入橡皮擦快速鍵:"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Enter IP address to add host manually" : {
|
"Enter IP address to add host manually" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -2402,6 +2500,75 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Eraser Shortcut" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "橡皮擦快捷键"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "橡皮擦快速鍵"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "橡皮擦快速鍵"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Example: b, ctrl+b, alt+b ..." : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: b, ctrl+b, alt+b …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: b, ctrl+b, alt+b …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: b, ctrl+b, alt+b …"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Example: e, ctrl+e, alt+e ..." : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: e, ctrl+e, alt+e …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: e, ctrl+e, alt+e …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "例如: e, ctrl+e, alt+e …"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Exit" : {
|
"Exit" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -4822,6 +4989,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pencilKeyboardCmdURL" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/ma82z70rdt6u99b4#32535f99"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "needs_review",
|
||||||
|
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/nm6l9yixu0idsybg#32535f99"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/nm6l9yixu0idsybg#32535f99"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/nm6l9yixu0idsybg#32535f99"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"PencilProPackDescription" : {
|
"PencilProPackDescription" : {
|
||||||
"extractionState" : "manual"
|
"extractionState" : "manual"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
- (void) stopStream
|
- (void) stopStream
|
||||||
{
|
{
|
||||||
[_connection terminate];
|
[_connection terminate];
|
||||||
|
_callbacks = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) launchApp:(HttpManager*)hMan receiveSessionUrl:(NSString**)sessionUrl {
|
- (BOOL) launchApp:(HttpManager*)hMan receiveSessionUrl:(NSString**)sessionUrl {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
|
|||||||
@implementation VideoDecoderRenderer {
|
@implementation VideoDecoderRenderer {
|
||||||
dispatch_queue_t _sq, _vtq;
|
dispatch_queue_t _sq, _vtq;
|
||||||
StreamView* _view;
|
StreamView* _view;
|
||||||
id<ConnectionCallbacks> _callbacks;
|
__weak id<ConnectionCallbacks> _callbacks;
|
||||||
float _streamAspectRatio;
|
float _streamAspectRatio;
|
||||||
|
|
||||||
AVSampleBufferDisplayLayer* _displayLayer;
|
AVSampleBufferDisplayLayer* _displayLayer;
|
||||||
|
|||||||
@@ -11,19 +11,26 @@ import Foundation
|
|||||||
import SVGKit
|
import SVGKit
|
||||||
|
|
||||||
@objc public class GraphicUtils: NSObject {
|
@objc public class GraphicUtils: NSObject {
|
||||||
@objc public class func makeCenteredSVGLayer(
|
@objc public class func makeSVGLayer(
|
||||||
from file: String,
|
from file: String,
|
||||||
in container: CALayer,
|
in container: CALayer,
|
||||||
|
at normalizedPosition: CGPoint = .zero,
|
||||||
targetSize: CGSize
|
targetSize: CGSize
|
||||||
) -> CALayer {
|
) -> CALayer {
|
||||||
|
|
||||||
guard let svg = SVGKImage(named: file) else {
|
guard let url = Bundle.main.url(forResource: file, withExtension: "svg"),
|
||||||
|
let data = try? Data(contentsOf: url) else {
|
||||||
|
return CALayer()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let svg = SVGKImage(data: data) else {
|
||||||
fatalError("Failed to load SVG \(file)")
|
fatalError("Failed to load SVG \(file)")
|
||||||
}
|
}
|
||||||
|
|
||||||
return _makeCenteredSVGLayer(
|
return _makeSVGLayer(
|
||||||
from: svg,
|
from: svg,
|
||||||
in: container,
|
in: container,
|
||||||
|
at: normalizedPosition,
|
||||||
targetSize: targetSize
|
targetSize: targetSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -33,16 +40,17 @@ import SVGKit
|
|||||||
in container: CALayer,
|
in container: CALayer,
|
||||||
targetSize: CGSize
|
targetSize: CGSize
|
||||||
) -> CALayer {
|
) -> CALayer {
|
||||||
return _makeCenteredSVGLayer(
|
return _makeSVGLayer(
|
||||||
from: svg,
|
from: svg,
|
||||||
in: container,
|
in: container,
|
||||||
targetSize: targetSize
|
targetSize: targetSize
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public class func _makeCenteredSVGLayer(
|
@objc public class func _makeSVGLayer(
|
||||||
from svg: SVGKImage,
|
from svg: SVGKImage,
|
||||||
in container: CALayer,
|
in container: CALayer,
|
||||||
|
at normalizedPosition: CGPoint = .zero,
|
||||||
targetSize: CGSize,
|
targetSize: CGSize,
|
||||||
getWrapperLayer: Bool = true
|
getWrapperLayer: Bool = true
|
||||||
) -> CALayer {
|
) -> CALayer {
|
||||||
@@ -65,13 +73,14 @@ import SVGKit
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let realPosition = (normalizedPosition == .zero
|
||||||
|
? CGPoint(x: container.bounds.midX,y: container.bounds.midY)
|
||||||
|
: CGPoint(x: container.bounds.width*normalizedPosition.x,y: container.bounds.height*normalizedPosition.y))
|
||||||
|
|
||||||
let wrapper = CALayer()
|
let wrapper = CALayer()
|
||||||
wrapper.bounds = CGRect(origin: .zero, size: unionRect.size)
|
wrapper.bounds = CGRect(origin: .zero, size: unionRect.size)
|
||||||
wrapper.anchorPoint = CGPoint(x: 0.5, y: 0.5)
|
wrapper.anchorPoint = CGPoint(x: 0.5, y: 0.5)
|
||||||
wrapper.position = CGPoint(
|
wrapper.position = realPosition
|
||||||
x: container.bounds.midX,
|
|
||||||
y: container.bounds.midY
|
|
||||||
)
|
|
||||||
|
|
||||||
let scale = min(
|
let scale = min(
|
||||||
targetSize.width / unionRect.width,
|
targetSize.width / unionRect.width,
|
||||||
|
|||||||
+4
-1
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@interface LayoutOnScreenControlsViewController : UIViewController <OnScreenWidgetGuidelineUpdateDelegate,UITextFieldDelegate>
|
@interface LayoutOnScreenControlsViewController : UIViewController <OnScreenWidgetGuidelineUpdateDelegate,UITextFieldDelegate>
|
||||||
- (void)profileRefresh;
|
- (void)profileRefresh;
|
||||||
- (void)reloadOnScreenWidgetViews;
|
- (void)reloadOnScreenWidgetViews;
|
||||||
- (void)presentProfilesTableView;
|
- (void)presentProfilesTableViewWithPickProfile:(bool)pickProfile;
|
||||||
|
|
||||||
@property LayoutOnScreenControls *layoutOSC; // object that contains a view which contains the on screen controller buttons that allows the user to drag and positions each button on the screen using touch
|
@property LayoutOnScreenControls *layoutOSC; // object that contains a view which contains the on screen controller buttons that allows the user to drag and positions each button on the screen using touch
|
||||||
@property (nonatomic) NSMutableSet* onScreenWidgetViews;
|
@property (nonatomic) NSMutableSet* onScreenWidgetViews;
|
||||||
@@ -129,6 +129,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (strong, nonatomic) IBOutlet UILabel *walkModeThresholdLabel;
|
@property (strong, nonatomic) IBOutlet UILabel *walkModeThresholdLabel;
|
||||||
@property (strong, nonatomic) IBOutlet UISlider *walkModeThresholdSlider;
|
@property (strong, nonatomic) IBOutlet UISlider *walkModeThresholdSlider;
|
||||||
|
|
||||||
|
@property (weak, nonatomic) IBOutlet UIStackView *collectedWidgetsStack;
|
||||||
|
@property (weak, nonatomic) IBOutlet UISegmentedControl *collectedWidgetsSelector;
|
||||||
|
@property (weak, nonatomic) IBOutlet UISegmentedControl *revealModeSelector;
|
||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UIStackView *widgetPanelStack;
|
@property (weak, nonatomic) IBOutlet UIStackView *widgetPanelStack;
|
||||||
|
|
||||||
|
|||||||
+100
-41
@@ -103,8 +103,8 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
return newPosition;
|
return newPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reloadLegacyOnScreenControls{
|
- (void)reloadLegacyOnScreenControls:(OSCProfile* )profile{
|
||||||
[self.layoutOSC updateControls]; // creates and saves a 'Default' OSC profile or loads the o//ne the user selected on the previous screen
|
[self.layoutOSC updateLegacyWidgetsWith:profile]; // creates and saves a 'Default' OSC profile or loads the o//ne the user selected on the previous screen
|
||||||
[self addInnerAnalogSticksToOuterAnalogLayers];
|
[self addInnerAnalogSticksToOuterAnalogLayers];
|
||||||
[self.layoutOSC.layoutChanges removeAllObjects]; // since a new OSC profile is being loaded, this will remove all previous layout changes made from the array
|
[self.layoutOSC.layoutChanges removeAllObjects]; // since a new OSC profile is being loaded, this will remove all previous layout changes made from the array
|
||||||
[self OSCLayoutChanged]; // fades the 'Undo Button' out
|
[self OSCLayoutChanged]; // fades the 'Undo Button' out
|
||||||
@@ -123,33 +123,40 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
else return longSide;
|
else return longSide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dummytest{
|
||||||
|
|
||||||
- (void)reloadOnScreenWidgetViews{
|
}
|
||||||
NSLog(@"reloadOnScreenWidgets %f", CACurrentMediaTime());
|
|
||||||
OnScreenWidgetView.isTweakingHighlight = false;
|
|
||||||
OnScreenWidgetView.editMode = true;
|
|
||||||
[self hideStickIndicators];
|
|
||||||
|
|
||||||
|
- (void)clearOnScreenWidgets{
|
||||||
for (UIView *subview in self.view.subviews) {
|
for (UIView *subview in self.view.subviews) {
|
||||||
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
if ([subview isKindOfClass:[OnScreenWidgetView class]]) {
|
||||||
[subview removeFromSuperview];
|
[subview removeFromSuperview];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.onScreenWidgetViews removeAllObjects];
|
[self.onScreenWidgetViews removeAllObjects];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)reloadOnScreenWidgetViews{
|
||||||
|
OnScreenWidgetView.isTweakingHighlight = false;
|
||||||
|
OnScreenWidgetView.editMode = true;
|
||||||
|
|
||||||
NSLog(@"reload os Key here");
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[self hideStickIndicators];
|
||||||
|
[self clearOnScreenWidgets];
|
||||||
|
|
||||||
|
int16_t sequence = -1;
|
||||||
|
|
||||||
// _activeCustomOscButtonPositionDict will be updated every time when the osc profile is reloaded
|
// _activeCustomOscButtonPositionDict will be updated every time when the osc profile is reloaded
|
||||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
OSCProfile *oscProfile = [self->profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
||||||
|
NSLog(@"reloadOnScreenWidgets %lu", oscProfile.buttonStatesEncoded.count);
|
||||||
|
bool hasLegacyWidget = false;
|
||||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
||||||
// OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil];
|
// OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil];
|
||||||
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
OnScreenButtonState* buttonState = [self->profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||||
|
NSLog(@"reloadOnScreenWidgets name %@", buttonState.name);
|
||||||
if(buttonState.widgetType == CustomOnScreenWidget){
|
if(buttonState.widgetType == CustomOnScreenWidget){
|
||||||
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView
|
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape profile:oscProfile]; //reconstruct widgetView
|
||||||
widgetView.identifier = buttonState.identifier;
|
widgetView.sequence = buttonState.sequence == -1 ? ++sequence : buttonState.sequence;
|
||||||
NSLog(@"cmd: %@, id: %@", buttonState.name, widgetView.identifier);
|
|
||||||
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||||
widgetView.widthFactor = buttonState.widthFactor;
|
widgetView.widthFactor = buttonState.widthFactor;
|
||||||
@@ -185,12 +192,25 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
[widgetView adjustBorderWithWidth:buttonState.borderWidth];
|
[widgetView adjustBorderWithWidth:buttonState.borderWidth];
|
||||||
[self.onScreenWidgetViews addObject:widgetView];
|
[self.onScreenWidgetViews addObject:widgetView];
|
||||||
}
|
}
|
||||||
|
else if(buttonState.widgetType == LegacyOnScreenControls) hasLegacyWidget = true;
|
||||||
}
|
}
|
||||||
|
NSLog(@"reloadOnScreenWidgets hasLegacyWidget %d %f", hasLegacyWidget, CACurrentMediaTime());
|
||||||
|
if(hasLegacyWidget) [self reloadLegacyOnScreenControls:oscProfile];
|
||||||
|
else{
|
||||||
|
for(CALayer* layer in self.layoutOSC.OSCButtonLayerPool){
|
||||||
|
[layer removeFromSuperlayer];
|
||||||
|
}
|
||||||
|
[self.layoutOSC.OSCButtonLayerPool removeAllObjects];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewDidLoad {
|
- (void) viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
profilesManager = [OSCProfilesManager sharedManager:self.view.bounds];
|
profilesManager = [OSCProfilesManager sharedManager:self.view.bounds];
|
||||||
|
NSLog(@"self.view.bounds %f, %f", self.view.bounds.size.width, self.view.bounds.size.height);
|
||||||
self.onScreenWidgetViews = [[NSMutableSet alloc] init]; // will be revised to read persisted data , somewhere else
|
self.onScreenWidgetViews = [[NSMutableSet alloc] init]; // will be revised to read persisted data , somewhere else
|
||||||
[OSCProfilesManager setOnScreenWidgetViewsSet:self.onScreenWidgetViews]; // pass the keyboard button dict to profiles manager
|
[OSCProfilesManager setOnScreenWidgetViewsSet:self.onScreenWidgetViews]; // pass the keyboard button dict to profiles manager
|
||||||
|
|
||||||
@@ -220,7 +240,6 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
self.layoutOSC._level = OnScreenControlsLevelCustom;
|
self.layoutOSC._level = OnScreenControlsLevelCustom;
|
||||||
self.layoutOSC.layoutToolVC = self;
|
self.layoutOSC.layoutToolVC = self;
|
||||||
//[self.layoutOSC show]; // draw on screen controls
|
//[self.layoutOSC show]; // draw on screen controls
|
||||||
[self.layoutOSC show]; // draw on screen controls
|
|
||||||
|
|
||||||
[self addInnerAnalogSticksToOuterAnalogLayers]; // allows inner and analog sticks to be dragged together around the screen together as one unit which is the expected behavior
|
[self addInnerAnalogSticksToOuterAnalogLayers]; // allows inner and analog sticks to be dragged together around the screen together as one unit which is the expected behavior
|
||||||
|
|
||||||
@@ -269,6 +288,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
widgetPanelStoredCenter = self.widgetPanelStack.center;
|
widgetPanelStoredCenter = self.widgetPanelStack.center;
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
[self profileRefresh];
|
[self profileRefresh];
|
||||||
|
[self setupWidgetPanel];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewWillAppear:(BOOL)animated{
|
- (void)viewWillAppear:(BOOL)animated{
|
||||||
@@ -285,7 +305,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(reloadOnScreenWidgetViews)
|
selector:@selector(dummytest)
|
||||||
name:@"OscLayoutProfileSelctedInTableView" // This is a special notification for reloading the on screen keyboard buttons. which can't be executed by _oscProfilesTableViewController.needToUpdateOscLayoutTVC code block, and has to be triggered by a notification
|
name:@"OscLayoutProfileSelctedInTableView" // This is a special notification for reloading the on screen keyboard buttons. which can't be executed by _oscProfilesTableViewController.needToUpdateOscLayoutTVC code block, and has to be triggered by a notification
|
||||||
object:nil];
|
object:nil];
|
||||||
|
|
||||||
@@ -324,8 +344,9 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
_oscProfilesTableViewController.layoutViewBounds = self.view.bounds;
|
_oscProfilesTableViewController.layoutViewBounds = self.view.bounds;
|
||||||
[OSCProfilesManager setLayoutViewBounds:self.view.bounds];
|
[OSCProfilesManager setLayoutViewBounds:self.view.bounds];
|
||||||
[OSCProfilesManager setOnScreenWidgetViewsSet:self.onScreenWidgetViews]; // pass the keyboard button dict to profiles manager
|
[OSCProfilesManager setOnScreenWidgetViewsSet:self.onScreenWidgetViews]; // pass the keyboard button dict to profiles manager
|
||||||
|
|
||||||
[self reloadOnScreenWidgetViews];
|
[self reloadOnScreenWidgetViews];
|
||||||
[self reloadLegacyOnScreenControls];
|
// [self reloadLegacyOnScreenControls];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)handleEnterBackground{
|
- (void)handleEnterBackground{
|
||||||
@@ -740,8 +761,8 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
NSString *widgetShape = [widgetInitParams[@"shape"] lowercaseString];
|
NSString *widgetShape = [widgetInitParams[@"shape"] lowercaseString];
|
||||||
|
|
||||||
widgetInitParams[@"cmdString"] = cmdString;
|
widgetInitParams[@"cmdString"] = cmdString;
|
||||||
bool noValidKeyboardString = [CommandManager.shared extractKeyStringsFromComboCommandFrom:cmdString] == nil; // this is a invalid string.
|
bool noValidKeyboardString = [CommandManager.shared extractKeyStringsFrom:cmdString] == nil; // this is a invalid string.
|
||||||
bool noValidSuperComboButtonString = [CommandManager.shared extractSinglCmdStringsFromComboKeysFrom:cmdString] == nil; // this is a invalid string.
|
bool noValidSuperComboButtonString = [CommandManager.shared extractCmdStringsFrom:cmdString] == nil; // this is a invalid string.
|
||||||
bool noValidMouseButtonString = ![CommandManager.mouseButtonMappings.allKeys containsObject:cmdString];
|
bool noValidMouseButtonString = ![CommandManager.mouseButtonMappings.allKeys containsObject:cmdString];
|
||||||
bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString];
|
bool noValidTouchPadString = ![CommandManager.touchPadCmds containsObject:cmdString];
|
||||||
bool noValidOscButtonString = ![CommandManager.oscButtonMappings.allKeys containsObject:cmdString];
|
bool noValidOscButtonString = ![CommandManager.oscButtonMappings.allKeys containsObject:cmdString];
|
||||||
@@ -765,8 +786,9 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
|
|
||||||
- (void) updateWidget:(OnScreenWidgetView* )widget byParams:(NSMutableDictionary* )widgetInitParams createNew:(bool)createNew{
|
- (void) updateWidget:(OnScreenWidgetView* )widget byParams:(NSMutableDictionary* )widgetInitParams createNew:(bool)createNew{
|
||||||
if(![self isWidgetParamsValid:widgetInitParams]) return;
|
if(![self isWidgetParamsValid:widgetInitParams]) return;
|
||||||
OnScreenWidgetView* newWidget = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"]]; //reconstruct widgetView
|
OSCProfile* profile = [[OSCProfilesManager sharedManager:CGRectZero] getSelectedProfile];
|
||||||
newWidget.identifier = createNew ? [UUIDHelper newUUID] : widget.identifier;
|
OnScreenWidgetView* newWidget = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"] profile:profile]; //reconstruct widgetView
|
||||||
|
newWidget.sequence = widget.sequence;
|
||||||
newWidget.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
newWidget.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||||
newWidget.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
newWidget.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||||
newWidget.widthFactor = widget.widthFactor;
|
newWidget.widthFactor = widget.widthFactor;
|
||||||
@@ -798,7 +820,10 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
[self.view insertSubview:newWidget belowSubview:self.widgetPanelStack];
|
[self.view insertSubview:newWidget belowSubview:self.widgetPanelStack];
|
||||||
[newWidget accessWidgetAttributes];
|
[newWidget accessWidgetAttributes];
|
||||||
|
|
||||||
if(createNew) [newWidget setLocationWithPosition:CGPointMake(90, 130)];
|
if(createNew){
|
||||||
|
[newWidget setLocationWithPosition:CGPointMake(90, 130)];
|
||||||
|
newWidget.sequence = [newWidget getAvailableSequence];
|
||||||
|
}
|
||||||
else [newWidget setLocationWithPosition:widget.center];
|
else [newWidget setLocationWithPosition:widget.center];
|
||||||
newWidget.sizeReference = widget.sizeReference;
|
newWidget.sizeReference = widget.sizeReference;
|
||||||
[newWidget resizeWidgetView]; // resize must be called after relocation
|
[newWidget resizeWidgetView]; // resize must be called after relocation
|
||||||
@@ -819,14 +844,17 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
- (void) createWidgetFromParams: (NSMutableDictionary*) widgetInitParams{
|
- (void) createWidgetFromParams: (NSMutableDictionary*) widgetInitParams{
|
||||||
if(![self isWidgetParamsValid:widgetInitParams]) return;
|
if(![self isWidgetParamsValid:widgetInitParams]) return;
|
||||||
//saving & present the keyboard button:
|
//saving & present the keyboard button:
|
||||||
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"]];
|
OSCProfile* profile = [[OSCProfilesManager sharedManager:CGRectZero] getSelectedProfile];
|
||||||
widgetView.identifier = [UUIDHelper newUUID];
|
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:widgetInitParams[@"cmdString"] buttonLabel:widgetInitParams[@"buttonLabel"] shape:widgetInitParams[@"shape"] profile:profile];
|
||||||
|
[self.view insertSubview:widgetView belowSubview:self.widgetPanelStack];
|
||||||
|
widgetView.hidden = true;
|
||||||
|
widgetView.sequence = [widgetView getAvailableSequence];
|
||||||
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
widgetView.guidelineDelegate = (id<OnScreenWidgetGuidelineUpdateDelegate>)self;
|
||||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||||
[self.onScreenWidgetViews addObject:widgetView];
|
[self.onScreenWidgetViews addObject:widgetView];
|
||||||
// Add the widgetView to the view controller's view
|
// Add the widgetView to the view controller's view
|
||||||
[self.view insertSubview:widgetView belowSubview:self.widgetPanelStack];
|
|
||||||
[widgetView setLocationWithPosition:CGPointMake(90, 130)];
|
[widgetView setLocationWithPosition:CGPointMake(90, 130)];
|
||||||
|
widgetView.hidden = false;
|
||||||
[widgetView resizeWidgetView];
|
[widgetView resizeWidgetView];
|
||||||
[widgetView setVibrationWithStyle:UIImpactFeedbackStyleLight];
|
[widgetView setVibrationWithStyle:UIImpactFeedbackStyleLight];
|
||||||
}
|
}
|
||||||
@@ -834,7 +862,6 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
|
|
||||||
/* show pop up notification that lets users choose to save the current OSC layout configuration as a profile they can load when they want. User can also choose to cancel out of this pop up */
|
/* show pop up notification that lets users choose to save the current OSC layout configuration as a profile they can load when they want. User can also choose to cancel out of this pop up */
|
||||||
- (IBAction) saveTapped:(id)sender {
|
- (IBAction) saveTapped:(id)sender {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
OSCProfile* targetProfile = [profilesManager getAllProfiles][0];
|
OSCProfile* targetProfile = [profilesManager getAllProfiles][0];
|
||||||
OSCProfile* currentProfile = [profilesManager getSelectedProfile];
|
OSCProfile* currentProfile = [profilesManager getSelectedProfile];
|
||||||
@@ -846,7 +873,7 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
[self clearSickInput];
|
[self clearSickInput];
|
||||||
[OSCProfilesManager setLayoutViewBounds:self.view.bounds];
|
[OSCProfilesManager setLayoutViewBounds:self.view.bounds];
|
||||||
|
|
||||||
if([self->profilesManager updateSelectedProfile:self.layoutOSC.OSCButtonLayers]){
|
if([self->profilesManager updateSelectedProfile:self.layoutOSC.OSCButtonLayerPool]){
|
||||||
UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Current profile updated successfully"] preferredStyle:UIAlertControllerStyleAlert];
|
UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Current profile updated successfully"] preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
}]];
|
}]];
|
||||||
@@ -904,7 +931,6 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
- (void)widgetViewTapped: (NSNotification *)notification{
|
- (void)widgetViewTapped: (NSNotification *)notification{
|
||||||
|
|
||||||
[self hideStickIndicators];
|
[self hideStickIndicators];
|
||||||
|
|
||||||
[self clearSickInput];
|
[self clearSickInput];
|
||||||
@@ -1064,8 +1090,16 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
self.buttonModeStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
|
self.buttonModeStack.hidden = selectedWidgetView.widgetType != WidgetTypeEnumButton;
|
||||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:0];
|
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:0];
|
||||||
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:1];
|
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton forSegmentAtIndex:1];
|
||||||
|
[self.buttonModeSelector setEnabled:!selectedWidgetView.isFuncationalButton
|
||||||
|
|| [selectedWidgetView.functionalButtonString containsString:@"ABSTCHDRAG"]
|
||||||
|
forSegmentAtIndex:3];
|
||||||
[self.buttonModeSelector setSelectedSegmentIndex:selectedWidgetView.buttonMode];
|
[self.buttonModeSelector setSelectedSegmentIndex:selectedWidgetView.buttonMode];
|
||||||
|
|
||||||
|
self.collectedWidgetsStack.hidden = !selectedWidgetView.isFolder;
|
||||||
|
[self.collectedWidgetsSelector setSelectedSegmentIndex:selectedWidgetView.folded ? 1 :0];
|
||||||
|
[self.revealModeSelector setSelectedSegmentIndex:selectedWidgetView.revealMode];
|
||||||
|
[OnScreenWidgetView setCollectionWithHidden:selectedWidgetView.folded for:selectedWidgetView];
|
||||||
|
|
||||||
[self autoFitStack:self.widgetPanelStack];
|
[self autoFitStack:self.widgetPanelStack];
|
||||||
|
|
||||||
if([self isIPhone]){
|
if([self isIPhone]){
|
||||||
@@ -1228,6 +1262,19 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)collectionHiddenChanged:(UISegmentedControl* )sender{
|
||||||
|
if(self->selectedWidgetView != nil && self->widgetViewSelected){
|
||||||
|
[OnScreenWidgetView setCollectionWithHidden:sender.selectedSegmentIndex==1 for:selectedWidgetView];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)revealModeChanged:(UISegmentedControl* )sender{
|
||||||
|
if(self->selectedWidgetView != nil && self->widgetViewSelected){
|
||||||
|
selectedWidgetView.revealMode = sender.selectedSegmentIndex;
|
||||||
|
[OnScreenWidgetView setCollectionWithHidden:selectedWidgetView.folded for:selectedWidgetView];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)vibrationStyleChanged:(UISegmentedControl* )sender{
|
- (void)vibrationStyleChanged:(UISegmentedControl* )sender{
|
||||||
bool vibraiontOn;
|
bool vibraiontOn;
|
||||||
if (@available(iOS 13.0, *)) {
|
if (@available(iOS 13.0, *)) {
|
||||||
@@ -1538,6 +1585,11 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
[self.buttonModeSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal];
|
[self.buttonModeSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal];
|
||||||
self.buttonModeStack.hidden = YES;
|
self.buttonModeStack.hidden = YES;
|
||||||
|
|
||||||
|
[self.collectedWidgetsSelector addTarget:self action:@selector(collectionHiddenChanged:) forControlEvents:(UIControlEventValueChanged)];
|
||||||
|
[self.collectedWidgetsSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal];
|
||||||
|
[self.revealModeSelector addTarget:self action:@selector(revealModeChanged:) forControlEvents:(UIControlEventValueChanged)];
|
||||||
|
[self.revealModeSelector setTitleTextAttributes:whiteFontAttributes forState:UIControlStateNormal];
|
||||||
|
self.collectedWidgetsStack.hidden = YES;
|
||||||
|
|
||||||
if([self isIPhone]){
|
if([self isIPhone]){
|
||||||
[self.vibrationStyleSelector addTarget:self action:@selector(vibrationStyleChanged:) forControlEvents:(UIControlEventValueChanged)];
|
[self.vibrationStyleSelector addTarget:self action:@selector(vibrationStyleChanged:) forControlEvents:(UIControlEventValueChanged)];
|
||||||
@@ -1637,8 +1689,9 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)handleProfileTablViewDismiss{
|
- (void)handleProfileTablViewDismiss{
|
||||||
[self profileRefresh];
|
|
||||||
if(_quickSwitchEnabled) [self dismissViewControllerAnimated:NO completion:nil];
|
if(_quickSwitchEnabled) [self dismissViewControllerAnimated:NO completion:nil];
|
||||||
|
else [self setupWidgetPanel];
|
||||||
|
// setup: current profile lable, button width slider, button height slider & button alpha slider
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Basically the same method as loadTapped, without parameter*/
|
/* Basically the same method as loadTapped, without parameter*/
|
||||||
@@ -1653,9 +1706,6 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
storyboard = [UIStoryboard storyboardWithName:@"iPad" bundle:nil];
|
storyboard = [UIStoryboard storyboardWithName:@"iPad" bundle:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup: current profile lable, button width slider, button height slider & button alpha slider
|
|
||||||
[self setupWidgetPanel];
|
|
||||||
|
|
||||||
//initialiaze _oscProfilesTableViewController
|
//initialiaze _oscProfilesTableViewController
|
||||||
self->_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"];
|
self->_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"];
|
||||||
|
|
||||||
@@ -1664,20 +1714,22 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
self->_oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC profile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
|
self->_oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC profile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
|
||||||
__strong typeof(weakSelf) strongSelf = weakSelf;
|
__strong typeof(weakSelf) strongSelf = weakSelf;
|
||||||
if (!strongSelf) return;
|
if (!strongSelf) return;
|
||||||
[weakSelf reloadLegacyOnScreenControls];
|
[weakSelf reloadOnScreenWidgetViews];
|
||||||
strongSelf->_oscProfilesTableViewController.currentOSCButtonLayers = weakSelf.layoutOSC.OSCButtonLayers; //pass updated OSCLayout to OSCProfileTableView again
|
strongSelf->_oscProfilesTableViewController.currentOSCButtonLayers = weakSelf.layoutOSC.OSCButtonLayerPool; //pass updated OSCLayout to OSCProfileTableView again
|
||||||
};
|
};
|
||||||
|
|
||||||
[self.oscProfilesTableViewController profileViewRefresh]; // execute this will make sure OSCLayout is updated from persisted profile, not any cache.
|
[self.oscProfilesTableViewController profileViewRefresh]; // execute this will make sure OSCLayout is updated from persisted profile, not any cache.
|
||||||
[self reloadOnScreenWidgetViews];
|
NSLog(@"profileRefresh %f", CACurrentMediaTime());
|
||||||
|
// [self reloadOnScreenWidgetViews];
|
||||||
|
|
||||||
// [self presentViewController:vc animated:YES completion:nil];
|
// [self presentViewController:vc animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) presentProfilesTableView{
|
- (void) presentProfilesTableViewWithPickProfile:(bool)pickProfile{
|
||||||
[self saveTapped:nil];
|
|
||||||
[self hideStickIndicators];
|
[self hideStickIndicators];
|
||||||
selectedWidgetView = nil;
|
selectedWidgetView = nil;
|
||||||
|
// if(pickProfile) [self clearOnScreenWidgets];
|
||||||
|
|
||||||
UIStoryboard *storyboard;
|
UIStoryboard *storyboard;
|
||||||
BOOL isIPhone = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone);
|
BOOL isIPhone = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone);
|
||||||
if (isIPhone) {
|
if (isIPhone) {
|
||||||
@@ -1692,21 +1744,24 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
|
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
_oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC ofile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the proffile and then hide/show and move each OSC button to their appropriate position
|
_oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC ofile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the proffile and then hide/show and move each OSC button to their appropriate position
|
||||||
[weakSelf reloadLegacyOnScreenControls];
|
if(!pickProfile || true) [weakSelf reloadOnScreenWidgetViews];
|
||||||
};
|
};
|
||||||
|
|
||||||
self.widgetPanelStack.hidden = YES;
|
self.widgetPanelStack.hidden = YES;
|
||||||
|
|
||||||
_oscProfilesTableViewController.currentOSCButtonLayers = self.layoutOSC.OSCButtonLayers;
|
_oscProfilesTableViewController.currentOSCButtonLayers = self.layoutOSC.OSCButtonLayerPool;
|
||||||
|
|
||||||
// _oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
|
// _oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
|
||||||
_oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
|
_oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;
|
||||||
[self presentViewController:_oscProfilesTableViewController animated:YES completion:nil];
|
// _oscProfilesTableViewController.modalPresentationStyle = UIModalPresentationPageSheet;
|
||||||
|
_oscProfilesTableViewController.pickProfileEnabled = pickProfile;
|
||||||
|
[self presentViewController:_oscProfilesTableViewController animated:NO completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Presents the view controller that lists all OSC profiles the user can choose from */
|
/* Presents the view controller that lists all OSC profiles the user can choose from */
|
||||||
- (IBAction) loadTapped:(id)sender {
|
- (IBAction) loadTapped:(id)sender {
|
||||||
[self presentProfilesTableView];
|
[self saveTapped:nil];
|
||||||
|
[self presentProfilesTableViewWithPickProfile:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1849,5 +1904,9 @@ typedef NS_ENUM(NSUInteger, DecelerationRateSliderMode) {
|
|||||||
widgetPanelMovedByTouch = false;
|
widgetPanelMovedByTouch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc{
|
||||||
|
NSLog(@"dealloc layoutToolVC %f ...", CACurrentMediaTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -29,9 +29,10 @@ typedef NS_ENUM(NSUInteger, FileOperation) {
|
|||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UITableView *tableView;
|
@property (weak, nonatomic) IBOutlet UITableView *tableView;
|
||||||
@property (nonatomic, copy) void (^needToUpdateOscLayoutTVC)(void);
|
@property (nonatomic, copy) void (^needToUpdateOscLayoutTVC)(void);
|
||||||
@property (nonatomic, assign) NSMutableArray *currentOSCButtonLayers;
|
@property (nonatomic, assign) NSMutableSet *currentOSCButtonLayers;
|
||||||
@property (nonatomic, assign) CGRect layoutViewBounds;
|
@property (nonatomic, assign) CGRect layoutViewBounds;
|
||||||
@property (weak, nonatomic) IBOutlet UINavigationBar *profileTableViewNavigationBar;
|
@property (weak, nonatomic) IBOutlet UINavigationBar *profileTableViewNavigationBar;
|
||||||
|
@property (nonatomic, assign) bool pickProfileEnabled;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
const double NAV_BAR_HEIGHT = 50;
|
const double NAV_BAR_HEIGHT = 50;
|
||||||
|
|
||||||
@interface OSCProfilesTableViewController ()
|
@interface OSCProfilesTableViewController () <UIGestureRecognizerDelegate>
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -42,9 +42,15 @@ const double NAV_BAR_HEIGHT = 50;
|
|||||||
return [self getCurrentOrientation]; // 90 Degree rotation not allowed in streaming or app view
|
return [self getCurrentOrientation]; // 90 Degree rotation not allowed in streaming or app view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
- (void) viewDidDisappear:(BOOL)animated{
|
- (void) viewDidDisappear:(BOOL)animated{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"OscLayoutTableViewCloseNotification" object:self]; // notify other view that oscLayoutManager is closing
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"OscLayoutTableViewCloseNotification" object:self]; // notify other view that oscLayoutManager is closing
|
||||||
[super viewDidDisappear:animated];
|
[super viewDidDisappear:animated];
|
||||||
|
}*/
|
||||||
|
|
||||||
|
- (void) viewWillDisappear:(BOOL)animated{
|
||||||
|
[super viewWillDisappear:animated];
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"OscLayoutTableViewCloseNotification" object:self]; // notify other view that oscLayoutManager is closing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,6 +94,17 @@ const double NAV_BAR_HEIGHT = 50;
|
|||||||
self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; // set background color & transparency
|
self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; // set background color & transparency
|
||||||
// self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2]; // set background color & transparency
|
// self.tableView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2]; // set background color & transparency
|
||||||
|
|
||||||
|
UITapGestureRecognizer *tap =
|
||||||
|
[[UITapGestureRecognizer alloc] initWithTarget:self
|
||||||
|
action:@selector(dismissSelf)];
|
||||||
|
tap.cancelsTouchesInView = NO;
|
||||||
|
tap.delegate = (id<UIGestureRecognizerDelegate>)self;
|
||||||
|
|
||||||
|
[self.view addGestureRecognizer:tap];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dismissSelf {
|
||||||
|
[self dismissViewControllerAnimated:NO completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) viewDidAppear:(BOOL)animated {
|
- (void) viewDidAppear:(BOOL)animated {
|
||||||
@@ -180,6 +197,7 @@ const double NAV_BAR_HEIGHT = 50;
|
|||||||
//[self dismissViewControllerAnimated:YES completion:nil];
|
//[self dismissViewControllerAnimated:YES completion:nil];
|
||||||
//[selfparentLayoutOSCViewController]
|
//[selfparentLayoutOSCViewController]
|
||||||
[self.tableView reloadData]; // table view will be refreshed by calling reloadData
|
[self.tableView reloadData]; // table view will be refreshed by calling reloadData
|
||||||
|
// if(_pickProfileEnabled) return;
|
||||||
if (self.needToUpdateOscLayoutTVC) { // tells the presenting view controller to lay out the on screen buttons according to the selected profile's instructions
|
if (self.needToUpdateOscLayoutTVC) { // tells the presenting view controller to lay out the on screen buttons according to the selected profile's instructions
|
||||||
self.needToUpdateOscLayoutTVC();
|
self.needToUpdateOscLayoutTVC();
|
||||||
}
|
}
|
||||||
@@ -215,7 +233,7 @@ const double NAV_BAR_HEIGHT = 50;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction) exitTapped:(id)sender {
|
- (IBAction) exitTapped:(id)sender {
|
||||||
[self dismissViewControllerAnimated:YES completion:nil];
|
[self dismissViewControllerAnimated:NO completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - UIDocumentPickerDelegate
|
#pragma mark - UIDocumentPickerDelegate
|
||||||
@@ -438,5 +456,13 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
|
|||||||
[self profileViewRefresh]; // update OSC layout when table view option is changed
|
[self profileViewRefresh]; // update OSC layout when table view option is changed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
||||||
|
shouldReceiveTouch:(UITouch *)touch {
|
||||||
|
if (_pickProfileEnabled && [touch.view isDescendantOfView:self.tableView]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(touch.view == self.view) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
UIView* menuSeparator;
|
UIView* menuSeparator;
|
||||||
UIView* snapshot;
|
UIView* snapshot;
|
||||||
SettingsViewController* settingsViewController;
|
SettingsViewController* settingsViewController;
|
||||||
StreamFrameViewController* streamFrameViewController;
|
__weak StreamFrameViewController* streamFrameViewController;
|
||||||
id navBarAppearanceStandard;
|
id navBarAppearanceStandard;
|
||||||
bool _viewJustAppeared;
|
bool _viewJustAppeared;
|
||||||
TemporaryApp * launchedApp;
|
TemporaryApp * launchedApp;
|
||||||
@@ -1257,6 +1257,7 @@ static NSMutableSet* hostList;
|
|||||||
streamFrameViewController.mainFrameViewcontroller = self;
|
streamFrameViewController.mainFrameViewcontroller = self;
|
||||||
streamFrameViewController.streamConfig = _streamConfig;
|
streamFrameViewController.streamConfig = _streamConfig;
|
||||||
}
|
}
|
||||||
|
NSLog(@"streamVC seque... %lu %f",(uintptr_t)streamFrameViewController , CACurrentMediaTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) showLoadingFrame:(void (^)(void))completion {
|
- (void) showLoadingFrame:(void (^)(void))completion {
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType)
|
|||||||
- (void)setRightViewController:(UIViewController *)rightViewController animated:(BOOL)animated;
|
- (void)setRightViewController:(UIViewController *)rightViewController animated:(BOOL)animated;
|
||||||
|
|
||||||
// Front view controller, can be nil on initialization but must be supplied by the time the view is loaded
|
// Front view controller, can be nil on initialization but must be supplied by the time the view is loaded
|
||||||
@property (nonatomic) UIViewController *frontViewController;
|
@property (nonatomic, weak) UIViewController *frontViewController;
|
||||||
- (void)setFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated;
|
- (void)setFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated;
|
||||||
|
|
||||||
// Sets the frontViewController using a default set of chained animations consisting on moving the
|
// Sets the frontViewController using a default set of chained animations consisting on moving the
|
||||||
|
|||||||
@@ -645,7 +645,7 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1
|
|||||||
UIView* _separatorLine;
|
UIView* _separatorLine;
|
||||||
NSMutableArray *_animationQueue;
|
NSMutableArray *_animationQueue;
|
||||||
BOOL _userInteractionStore;
|
BOOL _userInteractionStore;
|
||||||
UIViewController *_primaryViewController;
|
__weak UIViewController *_primaryViewController;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -256,7 +256,11 @@
|
|||||||
@property (strong, nonatomic) IBOutlet UIStackView *pencilTickIntervalStack;
|
@property (strong, nonatomic) IBOutlet UIStackView *pencilTickIntervalStack;
|
||||||
@property (strong, nonatomic) IBOutlet UISlider *pencilTickIntervalSlider;
|
@property (strong, nonatomic) IBOutlet UISlider *pencilTickIntervalSlider;
|
||||||
|
|
||||||
|
@property (weak, nonatomic) IBOutlet UIStackView *doubleTapShortcutStack;
|
||||||
|
@property (weak, nonatomic) IBOutlet UISwitch *doubleTapShortcutSwitch;
|
||||||
|
|
||||||
|
@property (weak, nonatomic) IBOutlet UIStackView *pencilPausesNativeTouchStack;
|
||||||
|
@property (weak, nonatomic) IBOutlet UISwitch *pencilPausesNativeTouchSwitch;
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||||
|
|||||||
@@ -393,6 +393,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self.synthPhysicalInputSwitch setOn:oscProfile.synthesizePhysicalStick];
|
[self.synthPhysicalInputSwitch setOn:oscProfile.synthesizePhysicalStick];
|
||||||
|
|
||||||
[self.pressureCurveSwitch setOn:oscProfile.pressureCurveEnabled];
|
[self.pressureCurveSwitch setOn:oscProfile.pressureCurveEnabled];
|
||||||
|
[self.doubleTapShortcutSwitch setOn:oscProfile.doubleTapShorcutEnabled];
|
||||||
|
[self.pencilPausesNativeTouchSwitch setOn:oscProfile.pencilPausesNativeTouch];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)saveGameProfileConfigs{
|
- (void)saveGameProfileConfigs{
|
||||||
@@ -414,6 +416,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
&& (int16_t)(oscProfile.physicalLeftStickMinOffset) == (int16_t)self.leftStickMinOffsetSlider.value
|
&& (int16_t)(oscProfile.physicalLeftStickMinOffset) == (int16_t)self.leftStickMinOffsetSlider.value
|
||||||
&& (int16_t)(oscProfile.physicalRightStickMinOffset) == (int16_t)self.rightStickMinOffsetSlider.value
|
&& (int16_t)(oscProfile.physicalRightStickMinOffset) == (int16_t)self.rightStickMinOffsetSlider.value
|
||||||
&& oscProfile.pressureCurveEnabled == self.pressureCurveSwitch.isOn
|
&& oscProfile.pressureCurveEnabled == self.pressureCurveSwitch.isOn
|
||||||
|
&& oscProfile.doubleTapShorcutEnabled == self.doubleTapShortcutSwitch.isOn
|
||||||
|
&& oscProfile.pencilPausesNativeTouch == self.pencilPausesNativeTouchSwitch.isOn
|
||||||
);
|
);
|
||||||
|
|
||||||
if(!configNotChanged){
|
if(!configNotChanged){
|
||||||
@@ -431,6 +435,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
oscProfile.physicalLeftStickMinOffset = (int16_t)self.leftStickMinOffsetSlider.value;
|
oscProfile.physicalLeftStickMinOffset = (int16_t)self.leftStickMinOffsetSlider.value;
|
||||||
oscProfile.physicalRightStickMinOffset = (int16_t)self.rightStickMinOffsetSlider.value;
|
oscProfile.physicalRightStickMinOffset = (int16_t)self.rightStickMinOffsetSlider.value;
|
||||||
oscProfile.pressureCurveEnabled = self.pressureCurveSwitch.isOn;
|
oscProfile.pressureCurveEnabled = self.pressureCurveSwitch.isOn;
|
||||||
|
oscProfile.doubleTapShorcutEnabled = self.doubleTapShortcutSwitch.isOn;
|
||||||
|
oscProfile.pencilPausesNativeTouch = self.pencilPausesNativeTouchSwitch.isOn;
|
||||||
[oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
|
[oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -866,6 +872,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self addSetting:self.pencilTickStack ofId:@"pencilTickStack" withInfoTag:YES withDynamicLabel:NO to:pencilSection];
|
[self addSetting:self.pencilTickStack ofId:@"pencilTickStack" withInfoTag:YES withDynamicLabel:NO to:pencilSection];
|
||||||
[self addSetting:self.pencilTickIntervalStack ofId:@"pencilTickIntervalStack" withInfoTag:NO withDynamicLabel:YES to:pencilSection];
|
[self addSetting:self.pencilTickIntervalStack ofId:@"pencilTickIntervalStack" withInfoTag:NO withDynamicLabel:YES to:pencilSection];
|
||||||
[self addSetting:self.pressureCurveStack ofId:@"pressureCurveStack" withInfoTag:NO withDynamicLabel:NO to:pencilSection];
|
[self addSetting:self.pressureCurveStack ofId:@"pressureCurveStack" withInfoTag:NO withDynamicLabel:NO to:pencilSection];
|
||||||
|
[self addSetting:self.doubleTapShortcutStack ofId:@"doubleTapShortcutStack" withInfoTag:YES withDynamicLabel:NO to:pencilSection];
|
||||||
|
[self addSetting:self.pencilPausesNativeTouchStack ofId:@"pencilPausesNativeTouchStack" withInfoTag:NO withDynamicLabel:NO to:pencilSection];
|
||||||
[pencilSection addToParentStack:_parentStack];
|
[pencilSection addToParentStack:_parentStack];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1473,6 +1481,15 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
showOnlineDocAction = false;
|
showOnlineDocAction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if([sender.superview.accessibilityIdentifier isEqualToString: @"doubleTapShortcutStack"]){
|
||||||
|
oscProfile = [oscProfileMan getSelectedProfile];
|
||||||
|
tipText = [LocalizationHelper localizedStringForKey:@"doubleTapShortcutStackTip"
|
||||||
|
, [oscProfile.brushShortcut isEqualToString:@""] ? [LocalizationHelper localizedStringForKey:@"Null"] : oscProfile.brushShortcut
|
||||||
|
, [oscProfile.eraserShortcut isEqualToString:@""] ? [LocalizationHelper localizedStringForKey:@"Null"] : oscProfile.eraserShortcut
|
||||||
|
];
|
||||||
|
showOnlineDocAction = false;
|
||||||
|
}
|
||||||
|
|
||||||
UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message:tipText preferredStyle:UIAlertControllerStyleAlert];
|
UIAlertController *tipsAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Tips"] message:tipText preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
|
||||||
@@ -2369,7 +2386,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self mapGyroToChanged:self.mapGyroToSelector];
|
[self mapGyroToChanged:self.mapGyroToSelector];
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
MotionHandler* motionHandler = [MotionHandler sharedInstance];
|
MotionHandler* motionHandler = [MotionHandler sharedWithProfile:nil];
|
||||||
[motionHandler calibrateGyroBiasWithDuration:5 completion:^{
|
[motionHandler calibrateGyroBiasWithDuration:5 completion:^{
|
||||||
Settings* currentSettings = [self->dataMan retrieveSettings];
|
Settings* currentSettings = [self->dataMan retrieveSettings];
|
||||||
currentSettings.gyroBiasX = [NSNumber numberWithDouble:motionHandler.gyroBiasX];
|
currentSettings.gyroBiasX = [NSNumber numberWithDouble:motionHandler.gyroBiasX];
|
||||||
@@ -3355,6 +3372,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
self.pencilTickSelector.selectedSegmentIndex = PencilTickDisabled;
|
self.pencilTickSelector.selectedSegmentIndex = PencilTickDisabled;
|
||||||
[self pencilTickModeChanged:self.pencilTickSelector];
|
[self pencilTickModeChanged:self.pencilTickSelector];
|
||||||
|
[self.doubleTapShortcutSwitch setOn:false];
|
||||||
|
[self.pencilPausesNativeTouchSwitch setOn:false];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3371,6 +3390,29 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)doubleTapShortcutSwitchFlipped:(UISwitch* )sender{
|
||||||
|
if(sender.isOn && !settingsViewJustLoaded){
|
||||||
|
if (@available(iOS 15.0, *)) {
|
||||||
|
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
|
||||||
|
if(info.valid) [PencilHandler enterDoubleTapShortcutsIn:self];
|
||||||
|
else {
|
||||||
|
[IAPManager inAppPurchaseActionWithViewController:self product:AddOnProductPencilProPack];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)pencilPausesNativeTouchSwitchFlipped:(UISwitch* )sender{
|
||||||
|
if(sender.isOn && !settingsViewJustLoaded){
|
||||||
|
if (@available(iOS 15.0, *)) {
|
||||||
|
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
|
||||||
|
if(!info.valid) [IAPManager inAppPurchaseActionWithViewController:self product:AddOnProductPencilProPack];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)loadPencilSettings:(TemporarySettings*) tempSettings{
|
- (void)loadPencilSettings:(TemporarySettings*) tempSettings{
|
||||||
if([self isIPad]){
|
if([self isIPad]){
|
||||||
self.pencilTickSelector.selectedSegmentIndex = tempSettings.pencilTickMode.intValue;
|
self.pencilTickSelector.selectedSegmentIndex = tempSettings.pencilTickMode.intValue;
|
||||||
@@ -3381,8 +3423,9 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self.pencilTickIntervalSlider addTarget:self action:@selector(pencilTickIntervalSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
[self.pencilTickIntervalSlider addTarget:self action:@selector(pencilTickIntervalSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||||
[self pencilTickIntervalSliderMoved:self.pencilTickIntervalSlider];
|
[self pencilTickIntervalSliderMoved:self.pencilTickIntervalSlider];
|
||||||
|
|
||||||
[self.pressureCurveSwitch setOn:true];
|
|
||||||
[self.pressureCurveSwitch addTarget:self action:@selector(pressureCurveSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
[self.pressureCurveSwitch addTarget:self action:@selector(pressureCurveSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
|
[self.doubleTapShortcutSwitch addTarget:self action:@selector(doubleTapShortcutSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
|
[self.pencilPausesNativeTouchSwitch addTarget:self action:@selector(pencilPausesNativeTouchSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,9 @@
|
|||||||
@property (nonatomic) StreamConfiguration* streamConfig;
|
@property (nonatomic) StreamConfiguration* streamConfig;
|
||||||
@property (nonatomic, strong) AVPictureInPictureController *pipController API_AVAILABLE(ios(9.0));
|
@property (nonatomic, strong) AVPictureInPictureController *pipController API_AVAILABLE(ios(9.0));
|
||||||
@property (nonatomic, strong) AVPictureInPictureControllerContentSource *pipContentSource API_AVAILABLE(ios(15.0)); // Needed for iOS 15+ layer-based PiP
|
@property (nonatomic, strong) AVPictureInPictureControllerContentSource *pipContentSource API_AVAILABLE(ios(15.0)); // Needed for iOS 15+ layer-based PiP
|
||||||
@property (nonatomic, assign) MainFrameViewController *mainFrameViewcontroller;
|
@property (nonatomic, weak) MainFrameViewController *mainFrameViewcontroller;
|
||||||
@property (nonatomic, assign) bool micStreamInitialized;
|
@property (nonatomic, assign) bool micStreamInitialized;
|
||||||
|
@property (nonatomic, assign) bool viewJustLoaded;
|
||||||
|
|
||||||
@property (nonatomic, strong) MetalViewController *metalViewController;
|
@property (nonatomic, strong) MetalViewController *metalViewController;
|
||||||
@property (nonatomic, strong) ImGuiRenderer *imguiView;
|
@property (nonatomic, strong) ImGuiRenderer *imguiView;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#import "VoidLink-Swift.h"
|
#import "VoidLink-Swift.h"
|
||||||
#import "OSCProfilesManager.h"
|
#import "OSCProfilesManager.h"
|
||||||
#import "ThemeManager.h"
|
#import "ThemeManager.h"
|
||||||
|
#import "NativeTouchPointer.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@@ -61,7 +62,6 @@
|
|||||||
StreamView *_streamView;
|
StreamView *_streamView;
|
||||||
UIScrollView *_scrollView;
|
UIScrollView *_scrollView;
|
||||||
BOOL _userIsInteracting;
|
BOOL _userIsInteracting;
|
||||||
bool viewJustLoaded;
|
|
||||||
bool viewIsBeingResized;
|
bool viewIsBeingResized;
|
||||||
bool previousOnScreenWidgetEnabled;
|
bool previousOnScreenWidgetEnabled;
|
||||||
CGSize _keyboardSize;
|
CGSize _keyboardSize;
|
||||||
@@ -378,7 +378,7 @@
|
|||||||
|
|
||||||
Connection.muteInBackground = _settings.muteInBackground;
|
Connection.muteInBackground = _settings.muteInBackground;
|
||||||
|
|
||||||
if(!viewJustLoaded) [_controllerSupport updateControllerSupport:self.streamConfig delegate:self];
|
if(!_viewJustLoaded) [_controllerSupport updateControllerSupport:self.streamConfig delegate:self];
|
||||||
// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
|
// reload controllerSupport obj, this is mandatory for OSC reload,especially when the stream view is launched without OSC
|
||||||
[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig streamFrameTopLayerView:self.view]; //reinitiate setupStreamView process.
|
[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig streamFrameTopLayerView:self.view]; //reinitiate setupStreamView process.
|
||||||
// we got self.view passed to streamView class as the topLayerView, will be useful in many cases
|
// we got self.view passed to streamView class as the topLayerView, will be useful in many cases
|
||||||
@@ -387,7 +387,8 @@
|
|||||||
|
|
||||||
bool onScreenWidgetSwitched = previousOnScreenWidgetEnabled != [_streamView isOnScreenWidgetEnabled];
|
bool onScreenWidgetSwitched = previousOnScreenWidgetEnabled != [_streamView isOnScreenWidgetEnabled];
|
||||||
bool needReload = onScreenWidgetSwitched && !previousOnScreenWidgetEnabled;
|
bool needReload = onScreenWidgetSwitched && !previousOnScreenWidgetEnabled;
|
||||||
if(viewJustLoaded||reloadOnscreenWidgets||needReload) [_streamView reloadOnScreenWidgetViews]; //reload keyboard buttons here. the keyboard widget view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering
|
[_streamView reloadOnScreenWidgetViews:_viewJustLoaded||reloadOnscreenWidgets||needReload]; //reload keyboard buttons here. the keyboard widget view will be added to the streamframe view instead streamview, the highest layer, which saves a lot of reengineering
|
||||||
|
|
||||||
if(onScreenWidgetSwitched && previousOnScreenWidgetEnabled) [_streamView clearOnScreenWidgets];
|
if(onScreenWidgetSwitched && previousOnScreenWidgetEnabled) [_streamView clearOnScreenWidgets];
|
||||||
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
|
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
|
||||||
|
|
||||||
@@ -444,14 +445,11 @@
|
|||||||
[self startDisplayLink];
|
[self startDisplayLink];
|
||||||
}
|
}
|
||||||
|
|
||||||
_motionHandler = [MotionHandler sharedInstance];
|
_motionHandler = [MotionHandler sharedWithProfile: nil];
|
||||||
_motionHandler.gyroBiasX = _settings.gyroBiasX.doubleValue;
|
_motionHandler.gyroBiasX = _settings.gyroBiasX.doubleValue;
|
||||||
_motionHandler.gyroBiasY = _settings.gyroBiasY.doubleValue;
|
_motionHandler.gyroBiasY = _settings.gyroBiasY.doubleValue;
|
||||||
_motionHandler.gyroBiasZ = _settings.gyroBiasZ.doubleValue;
|
_motionHandler.gyroBiasZ = _settings.gyroBiasZ.doubleValue;
|
||||||
|
|
||||||
_streamView.onScreenControls.instanceReceiverDelegate = _motionHandler;
|
|
||||||
[_streamView.onScreenControls sendInstance];
|
|
||||||
|
|
||||||
TouchPadGestureHandler.enablePinch = _settings.enablePinch;
|
TouchPadGestureHandler.enablePinch = _settings.enablePinch;
|
||||||
TouchPadGestureHandler.ctrlDownForPinch = _settings.ctrlDownForPinch;
|
TouchPadGestureHandler.ctrlDownForPinch = _settings.ctrlDownForPinch;
|
||||||
TouchPadGestureHandler.scrollSensitivity = _settings.scrollSensitivity.floatValue;
|
TouchPadGestureHandler.scrollSensitivity = _settings.scrollSensitivity.floatValue;
|
||||||
@@ -474,7 +472,7 @@
|
|||||||
- (void)viewDidAppear:(BOOL)animated
|
- (void)viewDidAppear:(BOOL)animated
|
||||||
{
|
{
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
viewJustLoaded = false;
|
_viewJustLoaded = false;
|
||||||
_deviceWindow = self.view.window;
|
_deviceWindow = self.view.window;
|
||||||
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
|
previousOnScreenWidgetEnabled = [_streamView isOnScreenWidgetEnabled];
|
||||||
if (@available(iOS 13.0, *)) {
|
if (@available(iOS 13.0, *)) {
|
||||||
@@ -500,6 +498,11 @@
|
|||||||
|
|
||||||
self->_streamView.originalFrame = self->_streamView.frame;
|
self->_streamView.originalFrame = self->_streamView.frame;
|
||||||
|
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
NSLog(@"pausing...");
|
||||||
|
nil;
|
||||||
|
});
|
||||||
|
|
||||||
// check to see if external screen is connected/disconnected
|
// check to see if external screen is connected/disconnected
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||||
@@ -583,7 +586,7 @@
|
|||||||
|
|
||||||
- (void)viewDidLoad
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
viewJustLoaded = true;
|
_viewJustLoaded = true;
|
||||||
viewIsBeingResized = false;
|
viewIsBeingResized = false;
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
|
||||||
@@ -768,7 +771,7 @@
|
|||||||
[self presentViewController:_layoutOnScreenControlsVC animated:YES completion:nil];
|
[self presentViewController:_layoutOnScreenControlsVC animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)switchWidgetProfile{
|
- (void)openWidgetProfileTableWithPickProfile:(BOOL)pickProfile{
|
||||||
[_streamView saveRelocatedWidgetViews];
|
[_streamView saveRelocatedWidgetViews];
|
||||||
_streamView.widgetToolOpened = true;
|
_streamView.widgetToolOpened = true;
|
||||||
[self->_streamView disableOnScreenControls];
|
[self->_streamView disableOnScreenControls];
|
||||||
@@ -777,7 +780,7 @@
|
|||||||
_layoutOnScreenControlsVC.toolbarStackView.hidden = true;
|
_layoutOnScreenControlsVC.toolbarStackView.hidden = true;
|
||||||
_layoutOnScreenControlsVC.toolbarRootView.hidden = true;
|
_layoutOnScreenControlsVC.toolbarRootView.hidden = true;
|
||||||
[self presentViewController:_layoutOnScreenControlsVC animated:NO completion:^{
|
[self presentViewController:_layoutOnScreenControlsVC animated:NO completion:^{
|
||||||
[self->_layoutOnScreenControlsVC presentProfilesTableView];
|
[self->_layoutOnScreenControlsVC presentProfilesTableViewWithPickProfile:pickProfile];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,8 +802,8 @@
|
|||||||
[self->_streamView disableOnScreenControls]; // add this to get realtime back menu working.
|
[self->_streamView disableOnScreenControls]; // add this to get realtime back menu working.
|
||||||
[self->_streamView reloadOnScreenControlsWith:(ControllerSupport*)_controllerSupport
|
[self->_streamView reloadOnScreenControlsWith:(ControllerSupport*)_controllerSupport
|
||||||
andConfig:(StreamConfiguration*)_streamConfig];
|
andConfig:(StreamConfiguration*)_streamConfig];
|
||||||
[self->_streamView showOnScreenControls];
|
// [self->_streamView reloadLegacyWidgets];
|
||||||
[self->_streamView reloadOnScreenWidgetViews]; //update keyboard buttons here
|
[self->_streamView reloadOnScreenWidgetViews:true]; //update keyboard buttons here
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setUserInteractionEnabledForStreamView:(bool)enabled{
|
- (void)setUserInteractionEnabledForStreamView:(bool)enabled{
|
||||||
@@ -817,7 +820,8 @@
|
|||||||
- (void)willMoveToParentViewController:(UIViewController *)parent {
|
- (void)willMoveToParentViewController:(UIViewController *)parent {
|
||||||
// Only cleanup when we're being destroyed
|
// Only cleanup when we're being destroyed
|
||||||
if (parent == nil) {
|
if (parent == nil) {
|
||||||
//NSLog(@"gyro cleanup, count: %ld", _controller.count);
|
_streamView = nil;
|
||||||
|
[_streamView cleanUp];
|
||||||
[_controllerSupport cleanup];
|
[_controllerSupport cleanup];
|
||||||
|
|
||||||
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
[UIApplication sharedApplication].idleTimerDisabled = NO;
|
||||||
@@ -832,7 +836,11 @@
|
|||||||
self.metalViewController = nil;
|
self.metalViewController = nil;
|
||||||
NSLog(@"Metal renderer stopped and cleaned up.");
|
NSLog(@"Metal renderer stopped and cleaned up.");
|
||||||
}
|
}
|
||||||
|
[NativeTouchPointer cleanUpContext];
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
for(UIView* view in self.view.subviews){
|
||||||
|
[view removeFromSuperview];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -936,7 +944,7 @@
|
|||||||
- (void) returnToMainFrame {
|
- (void) returnToMainFrame {
|
||||||
[_streamView clearOnScreenWidgets];
|
[_streamView clearOnScreenWidgets];
|
||||||
if(micHandler) [micHandler clean];
|
if(micHandler) [micHandler clean];
|
||||||
PencilHandler.sharedInstance = nil;
|
PencilHandler.shared = nil;
|
||||||
|
|
||||||
// Reset display mode back to default
|
// Reset display mode back to default
|
||||||
[self updatePreferredDisplayMode:NO];
|
[self updatePreferredDisplayMode:NO];
|
||||||
@@ -1188,7 +1196,7 @@
|
|||||||
[self.view sendSubviewToBack:self->_streamView];
|
[self.view sendSubviewToBack:self->_streamView];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self->_streamView showOnScreenControls];
|
// [self->_streamView showOnScreenControls];
|
||||||
|
|
||||||
[self->_controllerSupport connectionEstablished];
|
[self->_controllerSupport connectionEstablished];
|
||||||
|
|
||||||
@@ -1609,6 +1617,28 @@
|
|||||||
[_streamView disablePencilHover];
|
[_streamView disablePencilHover];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setAllowSingleTouchEnabled:(BOOL)enabled{
|
||||||
|
[_streamView setAllowSingleTouchEnabled:enabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)replaceBrushWithShortcut:(NSString *)shortcut{
|
||||||
|
if(PencilHandler.shared){
|
||||||
|
[PencilHandler.shared replaceBrushWith:shortcut];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)replaceEraserWithShortcut:(NSString *)shortcut{
|
||||||
|
if(PencilHandler.shared){
|
||||||
|
[PencilHandler.shared replaceEraserWith:shortcut];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)presentPressureCurveVC{
|
||||||
|
PressureCurveViewController* pressureCurveVC = [[PressureCurveViewController alloc] init];
|
||||||
|
pressureCurveVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
|
||||||
|
[self presentViewController:pressureCurveVC animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
#if !TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
// Require a confirmation when streaming to activate a system gesture
|
// Require a confirmation when streaming to activate a system gesture
|
||||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
||||||
@@ -1645,6 +1675,7 @@
|
|||||||
|
|
||||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
|
||||||
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
||||||
|
[self->_streamView saveRelocatedWidgetViews];
|
||||||
|
|
||||||
if (_isRestoringFromPiP) {
|
if (_isRestoringFromPiP) {
|
||||||
Log(LOG_I, @"View size changed during PiP restore, skipping redundant reconfiguration.");
|
Log(LOG_I, @"View size changed during PiP restore, skipping redundant reconfiguration.");
|
||||||
@@ -1668,6 +1699,7 @@
|
|||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
[self stopDisplayLink];
|
[self stopDisplayLink];
|
||||||
|
NSLog(@"dealloc StreamFrameViewController %f", CACurrentMediaTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setupDisplayLink {
|
- (void)setupDisplayLink {
|
||||||
@@ -1698,5 +1730,4 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -10,7 +10,7 @@ import UIKit
|
|||||||
|
|
||||||
@objc protocol ToolboxSpecialEntryDelegate: NSObjectProtocol {
|
@objc protocol ToolboxSpecialEntryDelegate: NSObjectProtocol {
|
||||||
@objc optional func openWidgetLayoutTool()
|
@objc optional func openWidgetLayoutTool()
|
||||||
@objc optional func switchWidgetProfile()
|
@objc optional func openWidgetProfileTable(pickProfile: Bool)
|
||||||
@objc optional func bringUpSoftKeyboard()
|
@objc optional func bringUpSoftKeyboard()
|
||||||
@objc optional func enterPip()
|
@objc optional func enterPip()
|
||||||
@objc optional func toggleStatsOverlay()
|
@objc optional func toggleStatsOverlay()
|
||||||
@@ -18,7 +18,7 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc public class ToolboxViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
|
@objc public class ToolboxViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIGestureRecognizerDelegate {
|
||||||
|
|
||||||
@objc weak var specialEntryDelegate: ToolboxSpecialEntryDelegate?
|
@objc weak var specialEntryDelegate: ToolboxSpecialEntryDelegate?
|
||||||
public let tableView = UITableView()
|
public let tableView = UITableView()
|
||||||
@@ -30,6 +30,8 @@ import UIKit
|
|||||||
private let viewBackgroundColor = UIColor(white: 0.2, alpha: 0.8);
|
private let viewBackgroundColor = UIColor(white: 0.2, alpha: 0.8);
|
||||||
private let highlightColor = UIColor(white: 0.55, alpha: 0.8);
|
private let highlightColor = UIColor(white: 0.55, alpha: 0.8);
|
||||||
private let titleLabel = UILabel()
|
private let titleLabel = UILabel()
|
||||||
|
private var contentView = UIView()
|
||||||
|
|
||||||
@objc public var specialEntries : NSMutableArray = ["widgetSwitchTool", "widgetLayoutTool", "bringUpSoftKeyboard", "enterPip", "toggleStatsOverlay", "disconnectAndQuitApp"]
|
@objc public var specialEntries : NSMutableArray = ["widgetSwitchTool", "widgetLayoutTool", "bringUpSoftKeyboard", "enterPip", "toggleStatsOverlay", "disconnectAndQuitApp"]
|
||||||
private let specialEntryAliasDic : [String:String] = [
|
private let specialEntryAliasDic : [String:String] = [
|
||||||
"widgetSwitchTool":SwiftLocalizationHelper.localizedString(forKey: "[ Switch on-screen widget profile ]"),
|
"widgetSwitchTool":SwiftLocalizationHelper.localizedString(forKey: "[ Switch on-screen widget profile ]"),
|
||||||
@@ -48,6 +50,7 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func viewDidLoad() {
|
override public func viewDidLoad() {
|
||||||
|
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
setupViews()
|
setupViews()
|
||||||
@@ -58,6 +61,11 @@ import UIKit
|
|||||||
|
|
||||||
// Register the cell class
|
// Register the cell class
|
||||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||||
|
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissSelf))
|
||||||
|
tap.delegate = self
|
||||||
|
view.addGestureRecognizer(tap)
|
||||||
|
|
||||||
//pass self to the CommandManager
|
//pass self to the CommandManager
|
||||||
CommandManager.shared.viewController = self
|
CommandManager.shared.viewController = self
|
||||||
}
|
}
|
||||||
@@ -75,21 +83,21 @@ import UIKit
|
|||||||
//setupConstraints()
|
//setupConstraints()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private func setupViews() {
|
private func setupViews() {
|
||||||
|
contentView = UIView(frame: self.view.frame)
|
||||||
|
|
||||||
// Set corner radius
|
// Set corner radius
|
||||||
view.layer.cornerRadius = 20 // Adjust the corner radius
|
contentView.layer.cornerRadius = 20 // Adjust the corner radius
|
||||||
view.layer.masksToBounds = true
|
contentView.layer.masksToBounds = true
|
||||||
|
|
||||||
// Set up the title label
|
// Set up the title label
|
||||||
titleLabel.text = SwiftLocalizationHelper.localizedString(forKey: "Toolbox")
|
titleLabel.text = SwiftLocalizationHelper.localizedString(forKey: "Toolbox")
|
||||||
titleLabel.font = UIFont.boldSystemFont(ofSize: 20) // Adjust font size as needed
|
titleLabel.font = UIFont.boldSystemFont(ofSize: 20) // Adjust font size as needed
|
||||||
titleLabel.textColor = UIColor.white // Adjust color as needed
|
titleLabel.textColor = UIColor.white // Adjust color as needed
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
view.addSubview(titleLabel)
|
contentView.addSubview(titleLabel)
|
||||||
|
|
||||||
view.backgroundColor = viewBackgroundColor
|
contentView.backgroundColor = viewBackgroundColor
|
||||||
tableView.backgroundColor = .clear
|
tableView.backgroundColor = .clear
|
||||||
tableView.rowHeight = isIPhone() ? 47 : 60
|
tableView.rowHeight = isIPhone() ? 47 : 60
|
||||||
tableView.separatorColor = .white.withAlphaComponent(0.33)
|
tableView.separatorColor = .white.withAlphaComponent(0.33)
|
||||||
@@ -107,12 +115,14 @@ import UIKit
|
|||||||
pinButton.titleLabel?.font = UIFont.systemFont(ofSize: 20)
|
pinButton.titleLabel?.font = UIFont.systemFont(ofSize: 20)
|
||||||
|
|
||||||
// Add subviews
|
// Add subviews
|
||||||
view.addSubview(tableView)
|
contentView.addSubview(tableView)
|
||||||
view.addSubview(addButton)
|
contentView.addSubview(addButton)
|
||||||
view.addSubview(deleteButton)
|
contentView.addSubview(deleteButton)
|
||||||
view.addSubview(editButton)
|
contentView.addSubview(editButton)
|
||||||
view.addSubview(exitButton)
|
contentView.addSubview(exitButton)
|
||||||
view.addSubview(pinButton)
|
contentView.addSubview(pinButton)
|
||||||
|
|
||||||
|
self.view.addSubview(contentView)
|
||||||
|
|
||||||
// Setup button targets
|
// Setup button targets
|
||||||
addButton.addTarget(self, action: #selector(addButtonTapped), for: .touchUpInside)
|
addButton.addTarget(self, action: #selector(addButtonTapped), for: .touchUpInside)
|
||||||
@@ -135,13 +145,9 @@ import UIKit
|
|||||||
|
|
||||||
@objc public func setupConstraints() {
|
@objc public func setupConstraints() {
|
||||||
|
|
||||||
guard view.superview != nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
NSLayoutConstraint.deactivate(view.constraints)
|
NSLayoutConstraint.deactivate(view.constraints)
|
||||||
|
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
contentView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
addButton.translatesAutoresizingMaskIntoConstraints = false
|
addButton.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@@ -154,47 +160,47 @@ import UIKit
|
|||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
|
||||||
// Set the width and height of the view
|
// Set the width and height of the view
|
||||||
view.widthAnchor.constraint(equalTo: view.superview!.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.52),
|
contentView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: isIPhone() ? 0.6 : 0.52),
|
||||||
view.heightAnchor.constraint(equalTo: view.superview!.heightAnchor, multiplier: 0.93),
|
contentView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.93),
|
||||||
// Set the width and height of the view
|
// Set the width and height of the view
|
||||||
//view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 60),
|
//view.leadingAnchor.constraint(equalTo: view.superview!.leadingAnchor, constant: 60),
|
||||||
//view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: -60),
|
//view.trailingAnchor.constraint(equalTo: view.superview!.trailingAnchor, constant: -60),
|
||||||
|
|
||||||
// Center the view horizontally and vertically
|
// Center the view horizontally and vertically
|
||||||
view.centerXAnchor.constraint(equalTo: view.superview!.centerXAnchor),
|
contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||||
view.centerYAnchor.constraint(equalTo: view.superview!.centerYAnchor),
|
contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||||
|
|
||||||
// ViewTitle constrains
|
// ViewTitle constrains
|
||||||
titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 13.5),
|
titleLabel.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor, constant: 13.5),
|
||||||
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
|
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
|
||||||
titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
|
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10),
|
||||||
|
|
||||||
|
|
||||||
// TableView constraints
|
// TableView constraints
|
||||||
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
|
tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
|
||||||
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
|
tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10),
|
||||||
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
|
tableView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
|
||||||
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60),
|
tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -60),
|
||||||
|
|
||||||
// ExitButton constraints
|
// ExitButton constraints
|
||||||
exitButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 25),
|
exitButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 25),
|
||||||
exitButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
exitButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
|
||||||
|
|
||||||
// EditButton constraints
|
// EditButton constraints
|
||||||
editButton.leadingAnchor.constraint(equalTo: exitButton.trailingAnchor, constant: 25),
|
editButton.leadingAnchor.constraint(equalTo: exitButton.trailingAnchor, constant: 25),
|
||||||
editButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
editButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
|
||||||
|
|
||||||
// AddButton constraints
|
// AddButton constraints
|
||||||
addButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -25),
|
addButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -25),
|
||||||
addButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
addButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
|
||||||
|
|
||||||
// DeleteButton constraints
|
// DeleteButton constraints
|
||||||
deleteButton.trailingAnchor.constraint(equalTo: addButton.leadingAnchor, constant: -25),
|
deleteButton.trailingAnchor.constraint(equalTo: addButton.leadingAnchor, constant: -25),
|
||||||
deleteButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
deleteButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
|
||||||
|
|
||||||
// DeleteButton constraints
|
// DeleteButton constraints
|
||||||
pinButton.trailingAnchor.constraint(equalTo: deleteButton.leadingAnchor, constant: -25),
|
pinButton.trailingAnchor.constraint(equalTo: deleteButton.leadingAnchor, constant: -25),
|
||||||
pinButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
|
pinButton.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,8 +363,12 @@ import UIKit
|
|||||||
else {
|
else {
|
||||||
let command = CommandManager.shared.getAllCommands()[indexPath.row-specialEntries.count]
|
let command = CommandManager.shared.getAllCommands()[indexPath.row-specialEntries.count]
|
||||||
sendKeyboardCommand(command)
|
sendKeyboardCommand(command)
|
||||||
|
if !viewPinned {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
|
||||||
|
self.dismiss(animated: false, completion: nil)
|
||||||
|
}
|
||||||
|
} // dimiss the view in sending mode & the view is not pinned
|
||||||
}
|
}
|
||||||
if !viewPinned { dismiss(animated: false, completion: nil) } // dimiss the view in sending mode & the view is not pinned
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let specialEntrySelected = indexPath.row < specialEntries.count
|
let specialEntrySelected = indexPath.row < specialEntries.count
|
||||||
@@ -372,30 +382,42 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handleSpecialEntries(index:Int){
|
private func handleSpecialEntries(index:Int){
|
||||||
usleep(1000*100)
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
|
||||||
dismiss(animated: true, completion: nil)
|
self.dismiss(animated: false, completion: nil)
|
||||||
switch specialEntries[index] as? String {
|
switch self.specialEntries[index] as? String {
|
||||||
case "widgetLayoutTool":
|
case "widgetLayoutTool":
|
||||||
specialEntryDelegate?.openWidgetLayoutTool!()
|
self.specialEntryDelegate?.openWidgetLayoutTool!()
|
||||||
case "widgetSwitchTool":
|
case "widgetSwitchTool":
|
||||||
specialEntryDelegate?.switchWidgetProfile?()
|
self.specialEntryDelegate?.openWidgetProfileTable?(pickProfile: false)
|
||||||
case "bringUpSoftKeyboard":
|
case "bringUpSoftKeyboard":
|
||||||
specialEntryDelegate?.bringUpSoftKeyboard?()
|
self.specialEntryDelegate?.bringUpSoftKeyboard?()
|
||||||
case "enterPip":
|
case "enterPip":
|
||||||
specialEntryDelegate?.enterPip?()
|
self.specialEntryDelegate?.enterPip?()
|
||||||
case "toggleStatsOverlay":
|
case "toggleStatsOverlay":
|
||||||
specialEntryDelegate?.toggleStatsOverlay?()
|
self.specialEntryDelegate?.toggleStatsOverlay?()
|
||||||
case "disconnectAndQuitApp":
|
case "disconnectAndQuitApp":
|
||||||
specialEntryDelegate?.disconnectAndQuitApp?()
|
self.specialEntryDelegate?.disconnectAndQuitApp?()
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private func sendKeyboardCommand(_ cmd: RemoteCommand) {
|
private func sendKeyboardCommand(_ cmd: RemoteCommand) {
|
||||||
print("Sending key-value")
|
print("Sending key-value")
|
||||||
let keyboardCmdStrings = CommandManager.shared.extractKeyStringsFromComboCommand(from: cmd.cmdString)
|
let keyboardCmdStrings = CommandManager.shared.extractKeyStrings(from: cmd.cmdString)
|
||||||
CommandManager.shared.sendKeyComboCommand(keyboardCmdStrings: keyboardCmdStrings!)
|
CommandManager.shared.sendKeyComboCommand(keyboardCmdStrings: keyboardCmdStrings!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func gestureRecognizer(
|
||||||
|
_ gestureRecognizer: UIGestureRecognizer,
|
||||||
|
shouldReceive touch: UITouch
|
||||||
|
) -> Bool {
|
||||||
|
return touch.view == view
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func dismissSelf(){
|
||||||
|
dismiss(animated: false, completion: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3031,6 +3031,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hZw-pC-Qxm.text" : {
|
||||||
|
"comment" : "Class = \"UILabel\"; text = \"Pencil Pauses Native Touch\"; ObjectID = \"hZw-pC-Qxm\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "Pencil Pauses Native Touch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "使用笔时暂停多点触控"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "使用筆時暫停多點觸控"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "使用筆時暫停多點觸控"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"iel-xl-xd9.text" : {
|
"iel-xl-xd9.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Profile:\"; ObjectID = \"iel-xl-xd9\";",
|
"comment" : "Class = \"UILabel\"; text = \"Profile:\"; ObjectID = \"iel-xl-xd9\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -4009,6 +4039,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"MyP-Aq-htW.text" : {
|
||||||
|
"comment" : "Class = \"UILabel\"; text = \" Reveal mode \"; ObjectID = \"MyP-Aq-htW\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : " Reveal mode "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"MzN-ZR-qyM.segmentTitles[0]" : {
|
"MzN-ZR-qyM.segmentTitles[0]" : {
|
||||||
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[0] = \"Auto\"; ObjectID = \"MzN-ZR-qyM\";",
|
"comment" : "Class = \"UISegmentedControl\"; MzN-ZR-qyM.segmentTitles[0] = \"Auto\"; ObjectID = \"MzN-ZR-qyM\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -4705,6 +4747,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Qr8-Df-7Zu.segmentTitles[0]" : {
|
||||||
|
"comment" : "Class = \"UISegmentedControl\"; Qr8-Df-7Zu.segmentTitles[0] = \"coexist\"; ObjectID = \"Qr8-Df-7Zu\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "coexist"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Qr8-Df-7Zu.segmentTitles[1]" : {
|
||||||
|
"comment" : "Class = \"UISegmentedControl\"; Qr8-Df-7Zu.segmentTitles[1] = \"exclusive\"; ObjectID = \"Qr8-Df-7Zu\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "exclusive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Qs9-iS-YoW.text" : {
|
"Qs9-iS-YoW.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Divider Position\"; ObjectID = \"Qs9-iS-YoW\";",
|
"comment" : "Class = \"UILabel\"; text = \"Divider Position\"; ObjectID = \"Qs9-iS-YoW\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -4981,6 +5047,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sch-0e-nfa.segmentTitles[0]" : {
|
||||||
|
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[0] = \"display\"; ObjectID = \"sch-0e-nfa\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "display"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sch-0e-nfa.segmentTitles[1]" : {
|
||||||
|
"comment" : "Class = \"UISegmentedControl\"; sch-0e-nfa.segmentTitles[1] = \"hide\"; ObjectID = \"sch-0e-nfa\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "hide"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"shy-hG-9wY.text" : {
|
"shy-hG-9wY.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Remember Menu Fold/Expand\"; ObjectID = \"shy-hG-9wY\";",
|
"comment" : "Class = \"UILabel\"; text = \"Remember Menu Fold/Expand\"; ObjectID = \"shy-hG-9wY\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -5185,6 +5275,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"v5f-j3-pEc.text" : {
|
||||||
|
"comment" : "Class = \"UILabel\"; text = \"Double Tap Shorcut\"; ObjectID = \"v5f-j3-pEc\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "Double Tap Shorcut"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "轻点两下快捷键"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "輕點兩下快速鍵"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "輕點兩下快速鍵"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"v8l-hf-kiR.text" : {
|
"v8l-hf-kiR.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Rendering Mode (Experimental)\"; ObjectID = \"v8l-hf-kiR\";",
|
"comment" : "Class = \"UILabel\"; text = \"Rendering Mode (Experimental)\"; ObjectID = \"v8l-hf-kiR\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -5389,6 +5509,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"WLg-7a-5wu.text" : {
|
||||||
|
"comment" : "Class = \"UILabel\"; text = \"Collected widgets \"; ObjectID = \"WLg-7a-5wu\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "Collected widgets "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"x9i-JN-FSn.text" : {
|
"x9i-JN-FSn.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Roll factor\"; ObjectID = \"x9i-JN-FSn\";",
|
"comment" : "Class = \"UILabel\"; text = \"Roll factor\"; ObjectID = \"x9i-JN-FSn\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
|
|||||||
Reference in new issue
Block a user