From fe2193dbebf5857438a4efa584eb8d40509c95f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Godoy?= Date: Fri, 15 May 2020 15:48:26 -0300 Subject: [PATCH 1/5] Improve triggering of touch event and introduce Eraser device --- .../SKTouchHandler.cs | 159 ++++++++++++++---- .../SKTouchHandler.cs | 3 +- .../SKTouchEventArgs.cs | 8 +- .../SKTouchHandler.cs | 3 +- .../SKTouchHandler.cs | 13 +- .../SKTouchHandlerElement.cs | 151 +++++++++++++---- .../SKTouchHandler.cs | 2 +- 7 files changed, 269 insertions(+), 70 deletions(-) diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKTouchHandler.cs index 2528a562f6..bfad826adc 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Android/SKTouchHandler.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Android.Views; namespace SkiaSharp.Views.Forms @@ -19,9 +20,11 @@ public void SetEnabled(View view, bool enableTouchEvents) if (view != null) { view.Touch -= OnTouch; + view.GenericMotion -= OnGenericMotion; if (enableTouchEvents) { view.Touch += OnTouch; + view.GenericMotion += OnGenericMotion; } } } @@ -42,43 +45,31 @@ private void OnTouch(object sender, View.TouchEventArgs e) return; var evt = e.Event; - var pointer = evt.ActionIndex; - - var id = evt.GetPointerId(pointer); - var coords = scalePixels(evt.GetX(pointer), evt.GetY(pointer)); - - var toolType = evt.GetToolType(pointer); - - var deviceType = GetDeviceType(toolType); - - var pressure = evt.GetPressure(pointer); - - var button = GetButton(evt, toolType); + var count = evt.PointerCount; switch (evt.ActionMasked) { case MotionEventActions.Down: case MotionEventActions.PointerDown: { - var args = new SKTouchEventArgs(id, SKTouchAction.Pressed, button, deviceType, coords, true, 0, pressure); + for (var pointer = 0; pointer < count; pointer++) + { + var args = CreateTouchEventArgs(SKTouchAction.Pressed, true, evt, pointer); - onTouchAction(args); - e.Handled = args.Handled; + onTouchAction(args); + e.Handled |= args.Handled; + } break; } case MotionEventActions.Move: { - var count = evt.PointerCount; - for (pointer = 0; pointer < count; pointer++) + for (var pointer = 0; pointer < count; pointer++) { - id = evt.GetPointerId(pointer); - coords = scalePixels(evt.GetX(pointer), evt.GetY(pointer)); - - var args = new SKTouchEventArgs(id, SKTouchAction.Moved, button, deviceType, coords, true, 0, pressure); + var args = CreateTouchEventArgs(SKTouchAction.Moved, true, evt, pointer); onTouchAction(args); - e.Handled = e.Handled || args.Handled; + e.Handled |= args.Handled; } break; } @@ -86,16 +77,96 @@ private void OnTouch(object sender, View.TouchEventArgs e) case MotionEventActions.Up: case MotionEventActions.PointerUp: { - var args = new SKTouchEventArgs(id, SKTouchAction.Released, button, deviceType, coords, false, 0, pressure); + for (var pointer = 0; pointer < count; pointer++) + { + var args = CreateTouchEventArgs(SKTouchAction.Released, false, evt, pointer); + + onTouchAction(args); + e.Handled |= args.Handled; + } + break; + } + + case MotionEventActions.Cancel: + { + for (var pointer = 0; pointer < count; pointer++) + { + var args = CreateTouchEventArgs(SKTouchAction.Cancelled, false, evt, pointer); + + onTouchAction(args); + e.Handled |= args.Handled; + } + break; + } + } + } + + private void OnGenericMotion(object sender, View.GenericMotionEventArgs e) + { + if (onTouchAction == null || scalePixels == null) + return; + + if (!e.Event.IsFromSource(InputSourceType.Mouse)) + return; + + var evt = e.Event; + var pointer = evt.ActionIndex; + + var id = evt.GetPointerId(pointer); + var coords = scalePixels(evt.GetX(pointer), evt.GetY(pointer)); + + var toolType = evt.GetToolType(pointer); + var deviceType = GetDeviceType(toolType); + var button = GetButton(evt.ActionButton, toolType); + var inContact = button != SKMouseButton.Unknown; + + switch (evt.Action) + { + case MotionEventActions.ButtonPress: + { + var args = new SKTouchEventArgs(id, SKTouchAction.Pressed, button, deviceType, coords, inContact); onTouchAction(args); e.Handled = args.Handled; break; } + case MotionEventActions.ButtonRelease: + { + var args = new SKTouchEventArgs(id, SKTouchAction.Released, button, deviceType, coords, inContact); - case MotionEventActions.Cancel: + onTouchAction(args); + e.Handled = args.Handled; + break; + } + case MotionEventActions.HoverEnter: + { + var args = new SKTouchEventArgs(id, SKTouchAction.Entered, button, deviceType, coords, inContact); + + onTouchAction(args); + e.Handled = args.Handled; + break; + } + case MotionEventActions.HoverExit: + { + var args = new SKTouchEventArgs(id, SKTouchAction.Exited, button, deviceType, coords, inContact); + + onTouchAction(args); + e.Handled = args.Handled; + break; + } + case MotionEventActions.HoverMove: { - var args = new SKTouchEventArgs(id, SKTouchAction.Cancelled, button, deviceType, coords, false, 0, pressure); + var args = new SKTouchEventArgs(id, SKTouchAction.Moved, button, deviceType, coords, inContact); + + onTouchAction(args); + e.Handled = args.Handled; + break; + } + case MotionEventActions.Scroll: + { + var axisValue = evt.GetAxisValue(Axis.Vscroll, pointer); + var wheelDelta = axisValue.Equals(0) ? 0 : axisValue > 0 ? 1 : -1; + var args = new SKTouchEventArgs(id, SKTouchAction.WheelChanged, button, deviceType, coords, inContact, wheelDelta); onTouchAction(args); e.Handled = args.Handled; @@ -104,18 +175,46 @@ private void OnTouch(object sender, View.TouchEventArgs e) } } - private static SKMouseButton GetButton(MotionEvent evt, MotionEventToolType toolType) + private SKTouchEventArgs CreateTouchEventArgs(SKTouchAction actionType, bool inContact, MotionEvent evt, int pointerIndex) + { + var id = evt.GetPointerId(pointerIndex); + var toolType = evt.GetToolType(pointerIndex); + var button = GetButton(evt.ButtonState, toolType); + var coords = scalePixels(evt.GetX(pointerIndex), evt.GetY(pointerIndex)); + var deviceType = GetDeviceType(toolType); + var pressure = evt.GetPressure(pointerIndex); + + return new SKTouchEventArgs(id, actionType, button, deviceType, coords, inContact, 0, pressure); + } + + private static SKMouseButton GetButton(MotionEventButtonState buttonState, MotionEventToolType toolType) { var button = SKMouseButton.Left; - if (toolType == MotionEventToolType.Eraser) + if (buttonState.HasFlag(MotionEventButtonState.StylusPrimary)) { - button = SKMouseButton.Middle; + button = SKMouseButton.Left; + } + else if (buttonState.HasFlag(MotionEventButtonState.Primary)) + { + button = SKMouseButton.Left; + } + else if (buttonState.HasFlag(MotionEventButtonState.StylusSecondary)) + { + button = SKMouseButton.Right; } - else if (evt.ButtonState.HasFlag(MotionEventButtonState.StylusSecondary)) + else if (buttonState.HasFlag(MotionEventButtonState.Secondary)) { button = SKMouseButton.Right; } + else if (buttonState.HasFlag(MotionEventButtonState.Tertiary)) + { + button = SKMouseButton.Middle; + } + else if (toolType == MotionEventToolType.Mouse) + { + button = SKMouseButton.Unknown; + } return button; } @@ -126,7 +225,7 @@ private static SKTouchDeviceType GetDeviceType(MotionEventToolType toolType) => MotionEventToolType.Unknown => SKTouchDeviceType.Touch, MotionEventToolType.Finger => SKTouchDeviceType.Touch, MotionEventToolType.Stylus => SKTouchDeviceType.Pen, - MotionEventToolType.Eraser => SKTouchDeviceType.Pen, + MotionEventToolType.Eraser => SKTouchDeviceType.Eraser, MotionEventToolType.Mouse => SKTouchDeviceType.Mouse, _ => SKTouchDeviceType.Touch, }; diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Mac/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Mac/SKTouchHandler.cs index fac7028ec1..d96c6b817b 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Mac/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Mac/SKTouchHandler.cs @@ -116,8 +116,9 @@ private bool FireEvent(SKTouchAction actionType, SKMouseButton mouse, SKTouchDev cgPoint.Y = View.Bounds.Height - cgPoint.Y; var point = scalePixels(cgPoint.X, cgPoint.Y); + var wheelDelta = (int)mouseEvent.ScrollingDeltaY; - var args = new SKTouchEventArgs(id, actionType, mouse, device, point, inContact); + var args = new SKTouchEventArgs(id, actionType, mouse, device, point, inContact, wheelDelta, mouseEvent.Pressure); onTouchAction(args); return args.Handled; } diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKTouchEventArgs.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKTouchEventArgs.cs index 55e3baf6dc..a1dc7d2136 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKTouchEventArgs.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKTouchEventArgs.cs @@ -9,6 +9,11 @@ public SKTouchEventArgs(long id, SKTouchAction type, SKPoint location, bool inCo { } + public SKTouchEventArgs(long id, SKTouchAction type, SKPoint location, bool inContact, float pressure) + : this(id, type, SKMouseButton.Left, SKTouchDeviceType.Touch, location, inContact, 0, pressure) + { + } + public SKTouchEventArgs(long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SKPoint location, bool inContact) : this(id, type, mouseButton, deviceType, location, inContact, 0, 1) { @@ -70,7 +75,8 @@ public enum SKTouchDeviceType { Touch, Mouse, - Pen + Pen, + Eraser } public enum SKMouseButton diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Tizen/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Tizen/SKTouchHandler.cs index 20124bb871..71a3ceee34 100755 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Tizen/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Tizen/SKTouchHandler.cs @@ -86,6 +86,7 @@ public MomentumHandler(SKTouchHandler h) public void OnStarted() { + // TODO: id is always increasing ++currentId; PostEvent(SKTouchAction.Pressed); } @@ -112,7 +113,7 @@ private void PostEvent(SKTouchAction action) var p = handler.gestureLayer.EvasCanvas.Pointer; var coords = handler.scalePixels(p.X, p.Y); - var inContact = (action == SKTouchAction.Pressed || action == SKTouchAction.Moved) ? true : false; + var inContact = action == SKTouchAction.Pressed || action == SKTouchAction.Moved; handler.onTouchAction(new SKTouchEventArgs(currentId, action, coords, inContact)); } diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs index 6824dfb1af..118d0bff33 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs @@ -110,22 +110,27 @@ private bool CommonHandler(object sender, SKTouchAction touchActionType, Pointer var skPoint = scalePixels(windowsPoint.X, windowsPoint.Y); var mouse = GetMouseButton(pointerPoint); - var device = GetTouchDevice(evt); + var device = GetTouchDevice(evt, pointerPoint); var wheelDelta = pointerPoint?.Properties?.MouseWheelDelta ?? 0; + var pressure = pointerPoint?.Properties?.Pressure ?? 1; - var args = new SKTouchEventArgs(id, touchActionType, mouse, device, skPoint, evt.Pointer.IsInContact, wheelDelta); + var args = new SKTouchEventArgs(id, touchActionType, mouse, device, skPoint, evt.Pointer.IsInContact, wheelDelta, pressure); onTouchAction(args); return args.Handled; } - private static SKTouchDeviceType GetTouchDevice(PointerRoutedEventArgs evt) + private static SKTouchDeviceType GetTouchDevice(PointerRoutedEventArgs evt, PointerPoint pointerPoint) { var device = SKTouchDeviceType.Touch; switch (evt.Pointer.PointerDeviceType) { case PointerDeviceType.Pen: - device = SKTouchDeviceType.Pen; + var isEraser = false; + isEraser |= pointerPoint?.Properties?.IsInverted == true; + isEraser |= pointerPoint?.Properties?.IsEraser == true; + + device = isEraser ? SKTouchDeviceType.Eraser : SKTouchDeviceType.Pen; break; case PointerDeviceType.Mouse: device = SKTouchDeviceType.Mouse; diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.WPF/SKTouchHandlerElement.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.WPF/SKTouchHandlerElement.cs index bce1062d7e..3268bacbdd 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.WPF/SKTouchHandlerElement.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.WPF/SKTouchHandlerElement.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Windows; using System.Windows.Input; @@ -18,8 +17,6 @@ public SKTouchHandlerElement(Action onTouchAction, Func b.Name))); - mouse = stylus.InAir ? SKMouseButton.Unknown : SKMouseButton.Left; + var buttonsCount = stylus.StylusDevice.StylusButtons.Count; + var isPrimaryPressed = false; + var isSecondaryPressed = false; + var isTertiaryPressed = false; + if (buttonsCount > 0) + isPrimaryPressed = stylus.StylusDevice.StylusButtons[0].StylusButtonState == StylusButtonState.Down; + if (buttonsCount > 1) + isSecondaryPressed = stylus.StylusDevice.StylusButtons[1].StylusButtonState == StylusButtonState.Down; + if (buttonsCount > 2) + isTertiaryPressed = stylus.StylusDevice.StylusButtons[2].StylusButtonState == StylusButtonState.Down; + + if (isPrimaryPressed) + mouse = SKMouseButton.Left; + else if (isSecondaryPressed) + mouse = SKMouseButton.Right; + else if (isTertiaryPressed) + mouse = SKMouseButton.Middle; } break; } diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKTouchHandler.cs index 447cedb53a..e6f827a4c5 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.iOS/SKTouchHandler.cs @@ -102,7 +102,7 @@ private bool FireEvent(SKTouchAction actionType, UITouch touch, bool inContact) var cgPoint = touch.LocationInView(View); var point = scalePixels(cgPoint.X, cgPoint.Y); - var args = new SKTouchEventArgs(id, actionType, point, inContact); + var args = new SKTouchEventArgs(id, actionType, point, inContact, (float)touch.Force); onTouchAction(args); return args.Handled; } From ab9524982b651010583e0086b8e7e920b41534d4 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Fri, 24 Jul 2020 01:01:25 +0200 Subject: [PATCH 2/5] Update SKTouchHandler.cs --- .../SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs index 118d0bff33..f5ecdd3526 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs @@ -113,7 +113,7 @@ private bool CommonHandler(object sender, SKTouchAction touchActionType, Pointer var device = GetTouchDevice(evt, pointerPoint); var wheelDelta = pointerPoint?.Properties?.MouseWheelDelta ?? 0; - var pressure = pointerPoint?.Properties?.Pressure ?? 1; + var pressure = pointerPoint?.Properties?.Pressure ?? 0.5; var args = new SKTouchEventArgs(id, touchActionType, mouse, device, skPoint, evt.Pointer.IsInContact, wheelDelta, pressure); onTouchAction(args); From 2956a4138c5570ad165d2f848f3512c695472dfc Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Fri, 24 Jul 2020 01:02:49 +0200 Subject: [PATCH 3/5] Update SKTouchHandler.cs --- .../SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs index f5ecdd3526..0a311569bd 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.UWP/SKTouchHandler.cs @@ -126,9 +126,9 @@ private static SKTouchDeviceType GetTouchDevice(PointerRoutedEventArgs evt, Poin switch (evt.Pointer.PointerDeviceType) { case PointerDeviceType.Pen: - var isEraser = false; - isEraser |= pointerPoint?.Properties?.IsInverted == true; - isEraser |= pointerPoint?.Properties?.IsEraser == true; + var isEraser = + pointerPoint?.Properties?.IsInverted == true || + pointerPoint?.Properties?.IsEraser == true; device = isEraser ? SKTouchDeviceType.Eraser : SKTouchDeviceType.Pen; break; From 7f8c9ac4089733e527d461a5cd8d21fe4be9aedf Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Fri, 24 Jul 2020 17:32:17 +0200 Subject: [PATCH 4/5] Update azure-templates-bootstrapper.yml --- scripts/azure-templates-bootstrapper.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/azure-templates-bootstrapper.yml b/scripts/azure-templates-bootstrapper.yml index 7a82bac31c..0604046f0b 100644 --- a/scripts/azure-templates-bootstrapper.yml +++ b/scripts/azure-templates-bootstrapper.yml @@ -15,7 +15,7 @@ parameters: condition: succeeded() # whether or not to run this template shouldPublish: true # whether or not to publish the artifacts configuration: $(CONFIGURATION) # the build configuration - buildExternals: '' # the build number to download externals from + buildExternals: '3918901' # the build number to download externals from verbosity: $(VERBOSITY) # the level of verbosity to use when building docker: '' # the Docker image to build and use dockerArgs: '' # any additional arguments to pass to docker build @@ -26,16 +26,16 @@ parameters: installEmsdk: false # whether or not to install the Emscripten SDK jobs: -# - ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}: -# - template: azure-templates-download.yml -# parameters: -# name: ${{ parameters.name }} -# displayName: ${{ parameters.displayName }} -# vmImage: ${{ parameters.vmImage }} -# condition: ${{ parameters.condition }} -# buildExternals: ${{ parameters.buildExternals }} +- ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}: + - template: azure-templates-download.yml + parameters: + name: ${{ parameters.name }} + displayName: ${{ parameters.displayName }} + vmImage: ${{ parameters.vmImage }} + condition: ${{ parameters.condition }} + buildExternals: ${{ parameters.buildExternals }} -# - ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}: +- ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}: - job: ${{ parameters.name }} displayName: ${{ parameters.displayName }} timeoutInMinutes: 120 From 92d01b150b5cedfe075d7592174eb434cf9af4fa Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Fri, 24 Jul 2020 17:48:47 +0200 Subject: [PATCH 5/5] Update azure-templates-bootstrapper.yml --- scripts/azure-templates-bootstrapper.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/azure-templates-bootstrapper.yml b/scripts/azure-templates-bootstrapper.yml index 0604046f0b..7a82bac31c 100644 --- a/scripts/azure-templates-bootstrapper.yml +++ b/scripts/azure-templates-bootstrapper.yml @@ -15,7 +15,7 @@ parameters: condition: succeeded() # whether or not to run this template shouldPublish: true # whether or not to publish the artifacts configuration: $(CONFIGURATION) # the build configuration - buildExternals: '3918901' # the build number to download externals from + buildExternals: '' # the build number to download externals from verbosity: $(VERBOSITY) # the level of verbosity to use when building docker: '' # the Docker image to build and use dockerArgs: '' # any additional arguments to pass to docker build @@ -26,16 +26,16 @@ parameters: installEmsdk: false # whether or not to install the Emscripten SDK jobs: -- ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}: - - template: azure-templates-download.yml - parameters: - name: ${{ parameters.name }} - displayName: ${{ parameters.displayName }} - vmImage: ${{ parameters.vmImage }} - condition: ${{ parameters.condition }} - buildExternals: ${{ parameters.buildExternals }} +# - ${{ if and(ne(parameters.buildExternals, ''), startsWith(parameters.name, 'native_')) }}: +# - template: azure-templates-download.yml +# parameters: +# name: ${{ parameters.name }} +# displayName: ${{ parameters.displayName }} +# vmImage: ${{ parameters.vmImage }} +# condition: ${{ parameters.condition }} +# buildExternals: ${{ parameters.buildExternals }} -- ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}: +# - ${{ if or(eq(parameters.buildExternals, ''), not(startsWith(parameters.name, 'native_'))) }}: - job: ${{ parameters.name }} displayName: ${{ parameters.displayName }} timeoutInMinutes: 120