@rafaelaugusto/jolt 0.1.0-beta.9 → 0.1.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +167 -21
- package/dist/animate.d.ts +25 -4
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +67 -26
- package/dist/animate.js.map +1 -1
- package/dist/blur/index.d.ts +6 -0
- package/dist/blur/index.d.ts.map +1 -0
- package/dist/blur/index.js +196 -0
- package/dist/blur/index.js.map +1 -0
- package/dist/blur/native.d.ts +17 -0
- package/dist/blur/native.d.ts.map +1 -0
- package/dist/blur/native.js +44 -0
- package/dist/blur/native.js.map +1 -0
- package/dist/blur/types.d.ts +32 -0
- package/dist/blur/types.d.ts.map +1 -0
- package/dist/blur/types.js +2 -0
- package/dist/blur/types.js.map +1 -0
- package/dist/bottom-sheet/geometry.d.ts +18 -0
- package/dist/bottom-sheet/geometry.d.ts.map +1 -0
- package/dist/bottom-sheet/geometry.js +51 -0
- package/dist/bottom-sheet/geometry.js.map +1 -0
- package/dist/bottom-sheet/index.d.ts +56 -0
- package/dist/bottom-sheet/index.d.ts.map +1 -0
- package/dist/bottom-sheet/index.js +462 -0
- package/dist/bottom-sheet/index.js.map +1 -0
- package/dist/bottom-sheet/native.d.ts +11 -0
- package/dist/bottom-sheet/native.d.ts.map +1 -0
- package/dist/bottom-sheet/native.js +173 -0
- package/dist/bottom-sheet/native.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +40 -1
- package/dist/config.js.map +1 -1
- package/dist/decay.d.ts +1 -0
- package/dist/decay.d.ts.map +1 -1
- package/dist/decay.js +7 -0
- package/dist/decay.js.map +1 -1
- package/dist/drag-physics.d.ts +6 -1
- package/dist/drag-physics.d.ts.map +1 -1
- package/dist/drag.d.ts +17 -3
- package/dist/drag.d.ts.map +1 -1
- package/dist/drag.js +34 -11
- package/dist/drag.js.map +1 -1
- package/dist/driver/android-gradient.d.ts +5 -0
- package/dist/driver/android-gradient.d.ts.map +1 -0
- package/dist/driver/android-gradient.js +99 -0
- package/dist/driver/android-gradient.js.map +1 -0
- package/dist/driver/android-particles.d.ts +6 -0
- package/dist/driver/android-particles.d.ts.map +1 -0
- package/dist/driver/android-particles.js +93 -0
- package/dist/driver/android-particles.js.map +1 -0
- package/dist/driver/android.d.ts.map +1 -1
- package/dist/driver/android.js +27 -1
- package/dist/driver/android.js.map +1 -1
- package/dist/driver/frame.d.ts +3 -0
- package/dist/driver/frame.d.ts.map +1 -0
- package/dist/driver/frame.js +7 -0
- package/dist/driver/frame.js.map +1 -0
- package/dist/driver/index.d.ts +4 -0
- package/dist/driver/index.d.ts.map +1 -1
- package/dist/driver/index.js.map +1 -1
- package/dist/driver/ios-gradient.d.ts +5 -0
- package/dist/driver/ios-gradient.d.ts.map +1 -0
- package/dist/driver/ios-gradient.js +131 -0
- package/dist/driver/ios-gradient.js.map +1 -0
- package/dist/driver/ios-scroll-delegate.d.ts +4 -0
- package/dist/driver/ios-scroll-delegate.d.ts.map +1 -0
- package/dist/driver/ios-scroll-delegate.js +26 -0
- package/dist/driver/ios-scroll-delegate.js.map +1 -0
- package/dist/driver/ios.d.ts.map +1 -1
- package/dist/driver/ios.js +9 -0
- package/dist/driver/ios.js.map +1 -1
- package/dist/easing.d.ts +3 -1
- package/dist/easing.d.ts.map +1 -1
- package/dist/easing.js +18 -1
- package/dist/easing.js.map +1 -1
- package/dist/engine.d.ts +31 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +194 -42
- package/dist/engine.js.map +1 -1
- package/dist/gesture-native.d.ts +28 -0
- package/dist/gesture-native.d.ts.map +1 -0
- package/dist/gesture-native.js +61 -0
- package/dist/gesture-native.js.map +1 -0
- package/dist/gestures/index.d.ts +69 -0
- package/dist/gestures/index.d.ts.map +1 -0
- package/dist/gestures/index.js +262 -0
- package/dist/gestures/index.js.map +1 -0
- package/dist/glass/index.d.ts +55 -0
- package/dist/glass/index.d.ts.map +1 -0
- package/dist/glass/index.js +205 -0
- package/dist/glass/index.js.map +1 -0
- package/dist/gradient-binding.d.ts +38 -0
- package/dist/gradient-binding.d.ts.map +1 -0
- package/dist/gradient-binding.js +128 -0
- package/dist/gradient-binding.js.map +1 -0
- package/dist/gradient.d.ts +105 -0
- package/dist/gradient.d.ts.map +1 -0
- package/dist/gradient.js +514 -0
- package/dist/gradient.js.map +1 -0
- package/dist/gravity.d.ts +13 -0
- package/dist/gravity.d.ts.map +1 -0
- package/dist/gravity.js +84 -0
- package/dist/gravity.js.map +1 -0
- package/dist/haptics.d.ts.map +1 -1
- package/dist/haptics.js +101 -28
- package/dist/haptics.js.map +1 -1
- package/dist/image-effect.d.ts +1 -0
- package/dist/image-effect.d.ts.map +1 -1
- package/dist/image-effect.js +10 -2
- package/dist/image-effect.js.map +1 -1
- package/dist/index.d.ts +19 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.d.ts +86 -0
- package/dist/inspector/index.d.ts.map +1 -0
- package/dist/inspector/index.js +419 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspector/plot.d.ts +4 -0
- package/dist/inspector/plot.d.ts.map +1 -0
- package/dist/inspector/plot.js +23 -0
- package/dist/inspector/plot.js.map +1 -0
- package/dist/inspector/probe.d.ts +19 -0
- package/dist/inspector/probe.d.ts.map +1 -0
- package/dist/inspector/probe.js +37 -0
- package/dist/inspector/probe.js.map +1 -0
- package/dist/inspector/tuning.d.ts +19 -0
- package/dist/inspector/tuning.d.ts.map +1 -0
- package/dist/inspector/tuning.js +37 -0
- package/dist/inspector/tuning.js.map +1 -0
- package/dist/interactive-navigation/index.d.ts +44 -0
- package/dist/interactive-navigation/index.d.ts.map +1 -0
- package/dist/interactive-navigation/index.js +350 -0
- package/dist/interactive-navigation/index.js.map +1 -0
- package/dist/keyboard.d.ts +24 -0
- package/dist/keyboard.d.ts.map +1 -1
- package/dist/keyboard.js +199 -6
- package/dist/keyboard.js.map +1 -1
- package/dist/live-spring-driver.d.ts +52 -0
- package/dist/live-spring-driver.d.ts.map +1 -0
- package/dist/live-spring-driver.js +104 -0
- package/dist/live-spring-driver.js.map +1 -0
- package/dist/mixer.d.ts +55 -0
- package/dist/mixer.d.ts.map +1 -0
- package/dist/mixer.js +286 -0
- package/dist/mixer.js.map +1 -0
- package/dist/motion-scope.d.ts +8 -2
- package/dist/motion-scope.d.ts.map +1 -1
- package/dist/motion-scope.js +24 -3
- package/dist/motion-scope.js.map +1 -1
- package/dist/motion-states.d.ts +19 -7
- package/dist/motion-states.d.ts.map +1 -1
- package/dist/motion-states.js +116 -26
- package/dist/motion-states.js.map +1 -1
- package/dist/motion-value.d.ts +227 -0
- package/dist/motion-value.d.ts.map +1 -0
- package/dist/motion-value.js +1074 -0
- package/dist/motion-value.js.map +1 -0
- package/dist/native/index.d.ts +10 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.js +6 -0
- package/dist/native/index.js.map +1 -0
- package/dist/native-properties.d.ts +28 -0
- package/dist/native-properties.d.ts.map +1 -0
- package/dist/native-properties.js +154 -0
- package/dist/native-properties.js.map +1 -0
- package/dist/native-property-driver.d.ts +19 -0
- package/dist/native-property-driver.d.ts.map +1 -0
- package/dist/native-property-driver.js +69 -0
- package/dist/native-property-driver.js.map +1 -0
- package/dist/native-property.d.ts +37 -0
- package/dist/native-property.d.ts.map +1 -0
- package/dist/native-property.js +285 -0
- package/dist/native-property.js.map +1 -0
- package/dist/particles.d.ts +5 -2
- package/dist/particles.d.ts.map +1 -1
- package/dist/particles.js +16 -10
- package/dist/particles.js.map +1 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +2 -2
- package/dist/path.js.map +1 -1
- package/dist/physics/index.d.ts +139 -0
- package/dist/physics/index.d.ts.map +1 -0
- package/dist/physics/index.js +316 -0
- package/dist/physics/index.js.map +1 -0
- package/dist/physics/native.d.ts +54 -0
- package/dist/physics/native.d.ts.map +1 -0
- package/dist/physics/native.js +64 -0
- package/dist/physics/native.js.map +1 -0
- package/dist/playback-group.d.ts.map +1 -1
- package/dist/playback-group.js +17 -1
- package/dist/playback-group.js.map +1 -1
- package/dist/playback.d.ts +15 -0
- package/dist/playback.d.ts.map +1 -1
- package/dist/playback.js +23 -0
- package/dist/playback.js.map +1 -1
- package/dist/predictive-back/index.d.ts +45 -0
- package/dist/predictive-back/index.d.ts.map +1 -0
- package/dist/predictive-back/index.js +220 -0
- package/dist/predictive-back/index.js.map +1 -0
- package/dist/predictive-back/presentation.d.ts +4 -0
- package/dist/predictive-back/presentation.d.ts.map +1 -0
- package/dist/predictive-back/presentation.js +3 -0
- package/dist/predictive-back/presentation.js.map +1 -0
- package/dist/press.d.ts.map +1 -1
- package/dist/press.js +11 -2
- package/dist/press.js.map +1 -1
- package/dist/reorder/handle.d.ts +6 -0
- package/dist/reorder/handle.d.ts.map +1 -0
- package/dist/reorder/handle.js +10 -0
- package/dist/reorder/handle.js.map +1 -0
- package/dist/reorder/index.d.ts +10 -0
- package/dist/reorder/index.d.ts.map +1 -0
- package/dist/reorder/index.js +233 -0
- package/dist/reorder/index.js.map +1 -0
- package/dist/reorder/list-view.d.ts +5 -0
- package/dist/reorder/list-view.d.ts.map +1 -0
- package/dist/reorder/list-view.js +238 -0
- package/dist/reorder/list-view.js.map +1 -0
- package/dist/reorder/model.d.ts +6 -0
- package/dist/reorder/model.d.ts.map +1 -0
- package/dist/reorder/model.js +30 -0
- package/dist/reorder/model.js.map +1 -0
- package/dist/reorder/surface.d.ts +6 -0
- package/dist/reorder/surface.d.ts.map +1 -0
- package/dist/reorder/surface.js +10 -0
- package/dist/reorder/surface.js.map +1 -0
- package/dist/reorder/types.d.ts +92 -0
- package/dist/reorder/types.d.ts.map +1 -0
- package/dist/reorder/types.js +2 -0
- package/dist/reorder/types.js.map +1 -0
- package/dist/sampling.d.ts +35 -0
- package/dist/sampling.d.ts.map +1 -0
- package/dist/sampling.js +123 -0
- package/dist/sampling.js.map +1 -0
- package/dist/scene-appearance.d.ts +14 -0
- package/dist/scene-appearance.d.ts.map +1 -0
- package/dist/scene-appearance.js +68 -0
- package/dist/scene-appearance.js.map +1 -0
- package/dist/scene-camera.d.ts +5 -0
- package/dist/scene-camera.d.ts.map +1 -0
- package/dist/scene-camera.js +23 -0
- package/dist/scene-camera.js.map +1 -0
- package/dist/scene-shader.d.ts +18 -0
- package/dist/scene-shader.d.ts.map +1 -0
- package/dist/scene-shader.js +76 -0
- package/dist/scene-shader.js.map +1 -0
- package/dist/scroll-header/geometry.d.ts +18 -0
- package/dist/scroll-header/geometry.d.ts.map +1 -0
- package/dist/scroll-header/geometry.js +46 -0
- package/dist/scroll-header/geometry.js.map +1 -0
- package/dist/scroll-header/index.d.ts +48 -0
- package/dist/scroll-header/index.d.ts.map +1 -0
- package/dist/scroll-header/index.js +399 -0
- package/dist/scroll-header/index.js.map +1 -0
- package/dist/scroll-header/native.d.ts +28 -0
- package/dist/scroll-header/native.d.ts.map +1 -0
- package/dist/scroll-header/native.js +43 -0
- package/dist/scroll-header/native.js.map +1 -0
- package/dist/sensors/index.d.ts +69 -0
- package/dist/sensors/index.d.ts.map +1 -0
- package/dist/sensors/index.js +149 -0
- package/dist/sensors/index.js.map +1 -0
- package/dist/sensors/native.d.ts +20 -0
- package/dist/sensors/native.d.ts.map +1 -0
- package/dist/sensors/native.js +48 -0
- package/dist/sensors/native.js.map +1 -0
- package/dist/sequence.d.ts +24 -0
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +181 -19
- package/dist/sequence.js.map +1 -1
- package/dist/shapes/android.d.ts +3 -0
- package/dist/shapes/android.d.ts.map +1 -0
- package/dist/shapes/android.js +51 -0
- package/dist/shapes/android.js.map +1 -0
- package/dist/shapes/index.d.ts +6 -0
- package/dist/shapes/index.d.ts.map +1 -0
- package/dist/shapes/index.js +238 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/shapes/ios.d.ts +3 -0
- package/dist/shapes/ios.d.ts.map +1 -0
- package/dist/shapes/ios.js +164 -0
- package/dist/shapes/ios.js.map +1 -0
- package/dist/shapes/native.d.ts +18 -0
- package/dist/shapes/native.d.ts.map +1 -0
- package/dist/shapes/native.js +10 -0
- package/dist/shapes/native.js.map +1 -0
- package/dist/shapes/path.d.ts +10 -0
- package/dist/shapes/path.d.ts.map +1 -0
- package/dist/shapes/path.js +106 -0
- package/dist/shapes/path.js.map +1 -0
- package/dist/shapes/types.d.ts +55 -0
- package/dist/shapes/types.d.ts.map +1 -0
- package/dist/shapes/types.js +11 -0
- package/dist/shapes/types.js.map +1 -0
- package/dist/shared-layout/index.d.ts +40 -0
- package/dist/shared-layout/index.d.ts.map +1 -0
- package/dist/shared-layout/index.js +267 -0
- package/dist/shared-layout/index.js.map +1 -0
- package/dist/shared-layout/native.d.ts +15 -0
- package/dist/shared-layout/native.d.ts.map +1 -0
- package/dist/shared-layout/native.js +79 -0
- package/dist/shared-layout/native.js.map +1 -0
- package/dist/shared-layout/timing.d.ts +9 -0
- package/dist/shared-layout/timing.d.ts.map +1 -0
- package/dist/shared-layout/timing.js +68 -0
- package/dist/shared-layout/timing.js.map +1 -0
- package/dist/shared-navigation/entry.d.ts +51 -0
- package/dist/shared-navigation/entry.d.ts.map +1 -0
- package/dist/shared-navigation/entry.js +619 -0
- package/dist/shared-navigation/entry.js.map +1 -0
- package/dist/shared-navigation/index.d.ts +58 -0
- package/dist/shared-navigation/index.d.ts.map +1 -0
- package/dist/shared-navigation/index.js +318 -0
- package/dist/shared-navigation/index.js.map +1 -0
- package/dist/shared-navigation/return-signal.d.ts +16 -0
- package/dist/shared-navigation/return-signal.d.ts.map +1 -0
- package/dist/shared-navigation/return-signal.js +35 -0
- package/dist/shared-navigation/return-signal.js.map +1 -0
- package/dist/shared-navigation/return-target.d.ts +32 -0
- package/dist/shared-navigation/return-target.d.ts.map +1 -0
- package/dist/shared-navigation/return-target.js +168 -0
- package/dist/shared-navigation/return-target.js.map +1 -0
- package/dist/shared-navigation/scope.d.ts +4 -0
- package/dist/shared-navigation/scope.d.ts.map +1 -0
- package/dist/shared-navigation/scope.js +2 -0
- package/dist/shared-navigation/scope.js.map +1 -0
- package/dist/shared-navigation/targets.d.ts +6 -0
- package/dist/shared-navigation/targets.d.ts.map +1 -0
- package/dist/shared-navigation/targets.js +36 -0
- package/dist/shared-navigation/targets.js.map +1 -0
- package/dist/size-layout.d.ts +19 -0
- package/dist/size-layout.d.ts.map +1 -0
- package/dist/size-layout.js +216 -0
- package/dist/size-layout.js.map +1 -0
- package/dist/size.d.ts +19 -0
- package/dist/size.d.ts.map +1 -0
- package/dist/size.js +251 -0
- package/dist/size.js.map +1 -0
- package/dist/spring.d.ts +2 -0
- package/dist/spring.d.ts.map +1 -1
- package/dist/spring.js +11 -0
- package/dist/spring.js.map +1 -1
- package/dist/svg-path.d.ts +18 -0
- package/dist/svg-path.d.ts.map +1 -1
- package/dist/svg-path.js +3 -2
- package/dist/svg-path.js.map +1 -1
- package/dist/testing/clock.d.ts +40 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +116 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/handoff-recorder.d.ts +8 -0
- package/dist/testing/handoff-recorder.d.ts.map +1 -0
- package/dist/testing/handoff-recorder.js +77 -0
- package/dist/testing/handoff-recorder.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/native.d.ts +46 -0
- package/dist/testing/native.d.ts.map +1 -0
- package/dist/testing/native.js +313 -0
- package/dist/testing/native.js.map +1 -0
- package/dist/testing/presentation.d.ts +11 -0
- package/dist/testing/presentation.d.ts.map +1 -0
- package/dist/testing/presentation.js +45 -0
- package/dist/testing/presentation.js.map +1 -0
- package/dist/testing/replay.d.ts +39 -0
- package/dist/testing/replay.d.ts.map +1 -0
- package/dist/testing/replay.js +99 -0
- package/dist/testing/replay.js.map +1 -0
- package/dist/testing/scroll-handoff-native.d.ts +10 -0
- package/dist/testing/scroll-handoff-native.d.ts.map +1 -0
- package/dist/testing/scroll-handoff-native.js +151 -0
- package/dist/testing/scroll-handoff-native.js.map +1 -0
- package/dist/testing/scroll-handoff.d.ts +25 -0
- package/dist/testing/scroll-handoff.d.ts.map +1 -0
- package/dist/testing/scroll-handoff.js +127 -0
- package/dist/testing/scroll-handoff.js.map +1 -0
- package/dist/testing/sensors.d.ts +13 -0
- package/dist/testing/sensors.d.ts.map +1 -0
- package/dist/testing/sensors.js +26 -0
- package/dist/testing/sensors.js.map +1 -0
- package/dist/testing/trace.d.ts +101 -0
- package/dist/testing/trace.d.ts.map +1 -0
- package/dist/testing/trace.js +263 -0
- package/dist/testing/trace.js.map +1 -0
- package/dist/timed-animation.d.ts +38 -0
- package/dist/timed-animation.d.ts.map +1 -0
- package/dist/timed-animation.js +177 -0
- package/dist/timed-animation.js.map +1 -0
- package/dist/track.d.ts +3 -0
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +281 -40
- package/dist/track.js.map +1 -1
- package/dist/transition.d.ts +54 -2
- package/dist/transition.d.ts.map +1 -1
- package/dist/transition.js +128 -8
- package/dist/transition.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/value-observers.d.ts +22 -0
- package/dist/value-observers.d.ts.map +1 -0
- package/dist/value-observers.js +122 -0
- package/dist/value-observers.js.map +1 -0
- package/dist/value-track.d.ts +13 -0
- package/dist/value-track.d.ts.map +1 -0
- package/dist/value-track.js +59 -0
- package/dist/value-track.js.map +1 -0
- package/dist/vue/index.d.ts +33 -3
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/index.js +118 -3
- package/dist/vue/index.js.map +1 -1
- package/dist/zoomable.d.ts +1 -1
- package/dist/zoomable.d.ts.map +1 -1
- package/package.json +68 -3
- package/platforms/android/include.gradle +10 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/BlurEffect.java +89 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/CircleMath.java +158 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/CircleWorld.java +221 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GestureSession.java +227 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GestureSurface.java +54 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/GradientLayer.java +224 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrame.java +53 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrameFollower.java +57 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardObserver.java +97 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/LiveSpring.java +277 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/MotionProbe.java +70 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ParticleEmitter.java +192 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ParticleSimulation.java +114 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/PredictiveBackSession.java +212 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderHandle.java +25 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSession.java +213 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSurface.java +27 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ScrollHeader.java +84 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SensorMath.java +28 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SensorSource.java +217 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/ShapeLayer.java +120 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SharedLayoutFlight.java +287 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SharedNavigationScene.java +115 -0
- package/platforms/android/java/org/rafaelaugusto/jolt/SpringState.java +39 -0
- package/platforms/android/proguard-rules.pro +20 -0
- package/platforms/ios/build.xcconfig +1 -1
- package/platforms/ios/src/JoltBlur.h +14 -0
- package/platforms/ios/src/JoltBlur.m +86 -0
- package/platforms/ios/src/JoltCircleMath.h +191 -0
- package/platforms/ios/src/JoltCircleWorld.h +18 -0
- package/platforms/ios/src/JoltCircleWorld.m +218 -0
- package/platforms/ios/src/JoltGestureSession.h +23 -0
- package/platforms/ios/src/JoltGestureSession.m +251 -0
- package/platforms/ios/src/JoltInteractiveNavigation.h +23 -0
- package/platforms/ios/src/JoltInteractiveNavigation.m +255 -0
- package/platforms/ios/src/JoltLiveSpring.h +29 -0
- package/platforms/ios/src/JoltLiveSpring.m +243 -0
- package/platforms/ios/src/JoltMotionProbe.h +9 -0
- package/platforms/ios/src/JoltMotionProbe.m +72 -0
- package/platforms/ios/src/JoltReorderSession.h +15 -0
- package/platforms/ios/src/JoltReorderSession.m +205 -0
- package/platforms/ios/src/JoltScrollHeader.h +13 -0
- package/platforms/ios/src/JoltScrollHeader.m +101 -0
- package/platforms/ios/src/JoltSensorMath.h +39 -0
- package/platforms/ios/src/JoltSensorSource.h +13 -0
- package/platforms/ios/src/JoltSensorSource.m +201 -0
- package/platforms/ios/src/JoltSharedLayoutFlight.h +19 -0
- package/platforms/ios/src/JoltSharedLayoutFlight.m +250 -0
- package/platforms/ios/src/JoltSpringState.h +35 -0
- package/platforms/ios/src/module.modulemap +10 -0
- package/src/android-plugin.d.ts +464 -0
- package/src/animate.ts +129 -15
- package/src/blur/index.ts +195 -0
- package/src/blur/native.ts +70 -0
- package/src/blur/types.ts +32 -0
- package/src/bottom-sheet/geometry.ts +84 -0
- package/src/bottom-sheet/index.ts +536 -0
- package/src/bottom-sheet/native.ts +214 -0
- package/src/config.ts +39 -1
- package/src/decay.ts +9 -0
- package/src/drag.ts +67 -21
- package/src/driver/android-gradient.ts +116 -0
- package/src/driver/android-particles.ts +118 -0
- package/src/driver/android.ts +31 -1
- package/src/driver/frame.ts +10 -0
- package/src/driver/index.ts +4 -0
- package/src/driver/ios-gradient.ts +136 -0
- package/src/driver/ios-scroll-delegate.ts +23 -0
- package/src/driver/ios.ts +10 -0
- package/src/easing.ts +21 -1
- package/src/engine.ts +209 -60
- package/src/gesture-native.ts +139 -0
- package/src/gestures/index.ts +365 -0
- package/src/glass/index.ts +218 -0
- package/src/gradient-binding.ts +158 -0
- package/src/gradient.ts +663 -0
- package/src/gravity.ts +107 -0
- package/src/haptics.ts +106 -28
- package/src/image-effect.ts +10 -2
- package/src/index.ts +56 -7
- package/src/inspector/index.ts +523 -0
- package/src/inspector/plot.ts +27 -0
- package/src/inspector/probe.ts +50 -0
- package/src/inspector/tuning.ts +51 -0
- package/src/interactive-navigation/index.ts +427 -0
- package/src/ios-plugin.d.ts +280 -0
- package/src/keyboard.ts +231 -7
- package/src/live-spring-driver.ts +181 -0
- package/src/mixer.ts +312 -0
- package/src/motion-scope.ts +39 -6
- package/src/motion-states.ts +149 -42
- package/src/motion-value.ts +1289 -0
- package/src/native/index.ts +30 -0
- package/src/native-properties.ts +188 -0
- package/src/native-property-driver.ts +123 -0
- package/src/native-property.ts +366 -0
- package/src/particles.ts +18 -17
- package/src/path.ts +2 -1
- package/src/physics/index.ts +476 -0
- package/src/physics/native.ts +121 -0
- package/src/playback-group.ts +17 -1
- package/src/playback.ts +41 -0
- package/src/predictive-back/index.ts +280 -0
- package/src/predictive-back/presentation.ts +6 -0
- package/src/press.ts +10 -2
- package/src/reorder/handle.ts +9 -0
- package/src/reorder/index.ts +243 -0
- package/src/reorder/list-view.ts +262 -0
- package/src/reorder/model.ts +47 -0
- package/src/reorder/surface.ts +10 -0
- package/src/reorder/types.ts +87 -0
- package/src/sampling.ts +173 -0
- package/src/scene-appearance.ts +92 -0
- package/src/scene-camera.ts +30 -0
- package/src/scene-shader.ts +139 -0
- package/src/scroll-header/geometry.ts +88 -0
- package/src/scroll-header/index.ts +530 -0
- package/src/scroll-header/native.ts +89 -0
- package/src/sensors/index.ts +246 -0
- package/src/sensors/native.ts +72 -0
- package/src/sequence.ts +209 -20
- package/src/shapes/android.ts +63 -0
- package/src/shapes/index.ts +267 -0
- package/src/shapes/ios.ts +194 -0
- package/src/shapes/native.ts +27 -0
- package/src/shapes/path.ts +127 -0
- package/src/shapes/types.ts +63 -0
- package/src/shared-layout/index.ts +343 -0
- package/src/shared-layout/native.ts +138 -0
- package/src/shared-layout/timing.ts +87 -0
- package/src/shared-navigation/entry.ts +695 -0
- package/src/shared-navigation/index.ts +414 -0
- package/src/shared-navigation/return-signal.ts +41 -0
- package/src/shared-navigation/return-target.ts +197 -0
- package/src/shared-navigation/scope.ts +3 -0
- package/src/shared-navigation/targets.ts +38 -0
- package/src/size-layout.ts +237 -0
- package/src/size.ts +302 -0
- package/src/spring.ts +18 -0
- package/src/svg-path.ts +8 -3
- package/src/testing/clock.ts +128 -0
- package/src/testing/handoff-recorder.ts +98 -0
- package/src/testing/index.ts +4 -0
- package/src/testing/native.ts +386 -0
- package/src/testing/presentation.ts +46 -0
- package/src/testing/replay.ts +149 -0
- package/src/testing/scroll-handoff-native.ts +201 -0
- package/src/testing/scroll-handoff.ts +140 -0
- package/src/testing/sensors.ts +41 -0
- package/src/testing/trace.ts +340 -0
- package/src/timed-animation.ts +192 -0
- package/src/track.ts +334 -38
- package/src/transition.ts +197 -9
- package/src/types.ts +11 -1
- package/src/value-observers.ts +147 -0
- package/src/value-track.ts +71 -0
- package/src/vue/index.ts +147 -1
- package/src/zoomable.ts +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#import "JoltCircleWorld.h"
|
|
2
|
+
#import "JoltCircleMath.h"
|
|
3
|
+
#import <QuartzCore/QuartzCore.h>
|
|
4
|
+
|
|
5
|
+
@interface JoltCircleWorld () <UIGestureRecognizerDelegate> {
|
|
6
|
+
JoltCircleState state;
|
|
7
|
+
BOOL originalInteraction[16];
|
|
8
|
+
double touchOffsetX[16],touchOffsetY[16];
|
|
9
|
+
double initialX[16],initialY[16],initialVX[16],initialVY[16],originalX[16],originalY[16];
|
|
10
|
+
}
|
|
11
|
+
@property(nonatomic) UIView *container;
|
|
12
|
+
@property(nonatomic) NSMutableArray *views,*pans,*guides,*pointerGuides;
|
|
13
|
+
@property(nonatomic) CADisplayLink *link;
|
|
14
|
+
@property(nonatomic) BOOL enabled,disposed,background,fits;
|
|
15
|
+
@property(nonatomic) double previous,accumulator,processingMs,droppedMs,offsetX,offsetY;
|
|
16
|
+
@property(nonatomic) NSUInteger frames,dragStarts,dragMoves,dragEnds,dragCancels;
|
|
17
|
+
@property(nonatomic) NSInteger dragging;
|
|
18
|
+
- (void)refresh;
|
|
19
|
+
- (void)apply;
|
|
20
|
+
- (void)cancelDrag;
|
|
21
|
+
- (id)makeGuide:(id)line;
|
|
22
|
+
- (void)configureAttachment:(id)value index:(int)index;
|
|
23
|
+
@end
|
|
24
|
+
|
|
25
|
+
@implementation JoltCircleWorld
|
|
26
|
+
static NSMutableSet<JoltCircleWorld *> *worlds;
|
|
27
|
+
+ (void)initialize { if(self==JoltCircleWorld.class)worlds=[NSMutableSet new]; }
|
|
28
|
+
+ (NSUInteger)worldCount{return worlds.count;}
|
|
29
|
+
+ (NSUInteger)activeCount{NSUInteger count=0;for(JoltCircleWorld *w in worlds)if(w.link)count++;return count;}
|
|
30
|
+
+ (instancetype)create:(UIView *)container options:(NSString *)options {
|
|
31
|
+
NSDictionary *config=[NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
32
|
+
NSArray *bodies=config[@"bodies"];
|
|
33
|
+
if(bodies.count<1||bodies.count>16)[NSException raise:NSInvalidArgumentException format:@"Physics needs 1–16 circles"];
|
|
34
|
+
JoltCircleWorld *w=[self new];w.container=container;w.views=[NSMutableArray new];w.pans=[NSMutableArray new];w.guides=[NSMutableArray new];w.pointerGuides=[NSMutableArray new];w.dragging=-1;
|
|
35
|
+
w->state.count=(int)bodies.count;w->state.width=[config[@"width"] doubleValue];w->state.height=[config[@"height"] doubleValue];
|
|
36
|
+
w->state.gx=[config[@"gravity"][@"x"] doubleValue];w->state.gy=[config[@"gravity"][@"y"] doubleValue];
|
|
37
|
+
w->state.restitution=[config[@"restitution"] doubleValue];w->state.damping=[config[@"damping"] doubleValue];
|
|
38
|
+
for(int i=0;i<bodies.count;i++){
|
|
39
|
+
NSDictionary *v=bodies[i];JoltCircle *b=&w->state.bodies[i];
|
|
40
|
+
b->x=[v[@"x"] doubleValue];b->y=[v[@"y"] doubleValue];b->r=[v[@"radius"] doubleValue];b->m=[v[@"mass"] doubleValue];
|
|
41
|
+
b->vx=[v[@"vx"] doubleValue];b->vy=[v[@"vy"] doubleValue];
|
|
42
|
+
w->initialX[i]=b->x/w->state.width;w->initialY[i]=b->y/w->state.height;w->initialVX[i]=b->vx;w->initialVY[i]=b->vy;
|
|
43
|
+
[w.views addObject:NSNull.null];[w.pans addObject:NSNull.null];[w.guides addObject:NSNull.null];[w.pointerGuides addObject:NSNull.null];
|
|
44
|
+
[w configureAttachment:v[@"attachment"] index:i];
|
|
45
|
+
id drag=v[@"drag"];
|
|
46
|
+
if([drag isKindOfClass:NSDictionary.class]){
|
|
47
|
+
b->drag.enabled=true;b->drag.length=[drag[@"length"] doubleValue];b->drag.stiffness=[drag[@"stiffness"] doubleValue];b->drag.damping=[drag[@"damping"] doubleValue];
|
|
48
|
+
w.pointerGuides[i]=[w makeGuide:drag[@"line"]];
|
|
49
|
+
}
|
|
50
|
+
id snap=v[@"snap"];
|
|
51
|
+
if([snap isKindOfClass:NSDictionary.class]){
|
|
52
|
+
NSArray *points=snap[@"points"];if(points.count>JOLT_CIRCLE_SNAP_LIMIT)[NSException raise:NSInvalidArgumentException format:@"Too many snap points"];
|
|
53
|
+
b->snap.count=(int)points.count;b->snap.stiffness=[snap[@"stiffness"] doubleValue];b->snap.damping=[snap[@"damping"] doubleValue];b->snap.projection=[snap[@"projection"] doubleValue];
|
|
54
|
+
for(int j=0;j<points.count;j++){b->snap.u[j]=[points[j][@"x"] doubleValue]/w->state.width;b->snap.v[j]=[points[j][@"y"] doubleValue]/w->state.height;}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
w.fits=JoltCircleFits(&w->state,w->state.width,w->state.height);
|
|
58
|
+
w.background=UIApplication.sharedApplication.applicationState==UIApplicationStateBackground;
|
|
59
|
+
[[NSNotificationCenter defaultCenter] addObserver:w selector:@selector(backgrounded) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
|
60
|
+
[[NSNotificationCenter defaultCenter] addObserver:w selector:@selector(foregrounded) name:UIApplicationDidBecomeActiveNotification object:nil];
|
|
61
|
+
[worlds addObject:w];return w;
|
|
62
|
+
}
|
|
63
|
+
- (void)configureAttachment:(id)value index:(int)index {
|
|
64
|
+
BOOL active=[value isKindOfClass:NSDictionary.class];
|
|
65
|
+
if(active)JoltCircleAttach(&state,index,true,[value[@"x"] doubleValue],[value[@"y"] doubleValue],[value[@"length"] doubleValue],[value[@"stiffness"] doubleValue],[value[@"damping"] doubleValue]);
|
|
66
|
+
else JoltCircleAttach(&state,index,false,0,0,0,180,24);
|
|
67
|
+
if(self.guides[index]!=NSNull.null){[(CALayer *)self.guides[index] removeFromSuperlayer];self.guides[index]=NSNull.null;}
|
|
68
|
+
id line=active?value[@"line"]:nil;
|
|
69
|
+
self.guides[index]=[self makeGuide:line];
|
|
70
|
+
}
|
|
71
|
+
- (id)makeGuide:(id)line {
|
|
72
|
+
if(![line isKindOfClass:NSDictionary.class])return NSNull.null;
|
|
73
|
+
CAShapeLayer *guide=[CAShapeLayer layer];unsigned int color=[line[@"color"] unsignedIntValue];
|
|
74
|
+
guide.strokeColor=[UIColor colorWithRed:((color>>16)&255)/255.0 green:((color>>8)&255)/255.0 blue:(color&255)/255.0 alpha:1].CGColor;
|
|
75
|
+
guide.fillColor=nil;guide.contentsScale=UIScreen.mainScreen.scale;guide.lineWidth=[line[@"width"] doubleValue];guide.lineCap=kCALineCapRound;
|
|
76
|
+
[self.container.layer addSublayer:guide];return guide;
|
|
77
|
+
}
|
|
78
|
+
- (BOOL)supportsPointerSpring {return YES;}
|
|
79
|
+
|
|
80
|
+
- (void)attach:(NSInteger)index options:(NSString *)options {
|
|
81
|
+
if(self.disposed||index<0||index>=state.count)return;
|
|
82
|
+
id value=[NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingFragmentsAllowed error:nil];
|
|
83
|
+
[self configureAttachment:value index:(int)index];[self apply];[self refresh];
|
|
84
|
+
}
|
|
85
|
+
- (void)snapTo:(NSInteger)index target:(NSInteger)target {
|
|
86
|
+
if(self.disposed||index<0||index>=state.count)return;
|
|
87
|
+
JoltCircleSnapTo(&state,(int)index,(int)target);[self apply];[self refresh];
|
|
88
|
+
}
|
|
89
|
+
- (void)connect:(UIView *)view index:(NSInteger)index {
|
|
90
|
+
if(self.disposed||index<0||index>=state.count)return;
|
|
91
|
+
if(view.superview!=self.container)[NSException raise:NSInvalidArgumentException format:@"Physics circles must be direct native children"];
|
|
92
|
+
self.views[index]=view;originalInteraction[index]=view.userInteractionEnabled;view.userInteractionEnabled=YES;originalX[index]=[[view.layer valueForKeyPath:@"transform.translation.x"] doubleValue];originalY[index]=[[view.layer valueForKeyPath:@"transform.translation.y"] doubleValue];
|
|
93
|
+
UIPanGestureRecognizer *pan=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)];
|
|
94
|
+
pan.maximumNumberOfTouches=1;pan.delegate=self;pan.enabled=NO;pan.cancelsTouchesInView=YES;
|
|
95
|
+
self.pans[index]=pan;[view addGestureRecognizer:pan];
|
|
96
|
+
[self apply];
|
|
97
|
+
}
|
|
98
|
+
- (BOOL)ready {return self.enabled&&!self.disposed&&!self.background&&self.fits&&self.container.window!=nil;}
|
|
99
|
+
- (void)refresh {
|
|
100
|
+
BOOL ready=[self ready];
|
|
101
|
+
for(id candidate in self.pans)if(candidate!=NSNull.null){UIPanGestureRecognizer *pan=candidate;if(pan.enabled!=ready)pan.enabled=ready;}
|
|
102
|
+
if(ready&&!state.sleeping){
|
|
103
|
+
if(!self.link){self.previous=0;self.accumulator=0;self.link=[CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];[self.link addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];}
|
|
104
|
+
}else if(self.link){[self.link invalidate];self.link=nil;self.previous=0;self.accumulator=0;}
|
|
105
|
+
}
|
|
106
|
+
- (void)tick:(CADisplayLink *)link {
|
|
107
|
+
if(![self ready]){[self cancelDrag];[self refresh];return;}
|
|
108
|
+
double started=CACurrentMediaTime(),elapsed=self.previous?MAX(0,link.timestamp-self.previous):0;self.previous=link.timestamp;
|
|
109
|
+
self.droppedMs+=MAX(0,elapsed-1.0/15)*1000;self.accumulator+=MIN(elapsed,1.0/15);
|
|
110
|
+
int budget=16;
|
|
111
|
+
while(self.accumulator+1e-10>=JOLT_CIRCLE_DT&&budget-->0&&!state.sleeping){JoltCircleStep(&state);self.accumulator-=JOLT_CIRCLE_DT;}
|
|
112
|
+
[self apply];self.frames++;self.processingMs+=(CACurrentMediaTime()-started)*1000;[self refresh];
|
|
113
|
+
}
|
|
114
|
+
- (void)apply {
|
|
115
|
+
[CATransaction begin];[CATransaction setDisableActions:YES];
|
|
116
|
+
for(int i=0;i<state.count;i++){
|
|
117
|
+
if(self.views[i]==NSNull.null)continue;UIView *v=self.views[i];
|
|
118
|
+
if(v.superview!=self.container){self.enabled=NO;continue;}
|
|
119
|
+
// layer.position is the untransformed layout center; body coordinates use container DIPs.
|
|
120
|
+
[v.layer setValue:@(state.bodies[i].x-v.layer.position.x) forKeyPath:@"transform.translation.x"];
|
|
121
|
+
[v.layer setValue:@(state.bodies[i].y-v.layer.position.y) forKeyPath:@"transform.translation.y"];
|
|
122
|
+
}
|
|
123
|
+
for(int i=0;i<state.count;i++)for(int kind=0;kind<2;kind++){
|
|
124
|
+
id candidate=(kind?self.pointerGuides:self.guides)[i];if(candidate==NSNull.null)continue;
|
|
125
|
+
JoltCircle *b=&state.bodies[i];CAShapeLayer *guide=candidate;
|
|
126
|
+
BOOL pointer=b->held&&b->drag.enabled;
|
|
127
|
+
guide.hidden=pointer!=(kind==1);if(guide.hidden)continue;
|
|
128
|
+
double x=pointer?b->tx:b->snap.active?JoltCircleSnapX(&state,b,b->snap.index):b->attachment.u*state.width;
|
|
129
|
+
double y=pointer?b->ty:b->snap.active?JoltCircleSnapY(&state,b,b->snap.index):b->attachment.v*state.height;
|
|
130
|
+
double dx=b->x-x,dy=b->y-y,d=hypot(dx,dy);
|
|
131
|
+
UIBezierPath *path=[UIBezierPath bezierPath];
|
|
132
|
+
if(d>b->r){[path moveToPoint:CGPointMake(x,y)];[path addLineToPoint:CGPointMake(b->x-dx/d*b->r,b->y-dy/d*b->r)];}
|
|
133
|
+
if(pointer||d>b->r)[path appendPath:[UIBezierPath bezierPathWithOvalInRect:CGRectMake(x-2.5,y-2.5,5,5)]];
|
|
134
|
+
guide.path=path.CGPath;
|
|
135
|
+
}
|
|
136
|
+
[CATransaction commit];
|
|
137
|
+
}
|
|
138
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch {
|
|
139
|
+
if(![self ready]||self.dragging>=0)return NO;
|
|
140
|
+
NSInteger i=[self.pans indexOfObject:gesture];if(i==NSNotFound)return NO;
|
|
141
|
+
CGPoint p=[touch locationInView:self.container];JoltCircle *b=&state.bodies[i];
|
|
142
|
+
touchOffsetX[i]=b->x-p.x;touchOffsetY[i]=b->y-p.y;
|
|
143
|
+
return hypot(p.x-b->x,p.y-b->y)<=b->r;
|
|
144
|
+
}
|
|
145
|
+
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gesture {
|
|
146
|
+
return [self ready]&&self.dragging<0;
|
|
147
|
+
}
|
|
148
|
+
- (void)panned:(UIPanGestureRecognizer *)pan {
|
|
149
|
+
NSInteger i=[self.pans indexOfObject:pan];if(i==NSNotFound)return;
|
|
150
|
+
CGPoint point=[pan locationInView:self.container];
|
|
151
|
+
if(pan.state==UIGestureRecognizerStateBegan){
|
|
152
|
+
if(![self ready]||self.dragging>=0)return;
|
|
153
|
+
self.dragging=i;self.offsetX=touchOffsetX[i];self.offsetY=touchOffsetY[i];self.dragStarts++;
|
|
154
|
+
}
|
|
155
|
+
if(self.dragging!=i)return;
|
|
156
|
+
if(pan.state==UIGestureRecognizerStateBegan||pan.state==UIGestureRecognizerStateChanged){
|
|
157
|
+
JoltCircleDrag(&state,(int)i,point.x+self.offsetX,point.y+self.offsetY);self.dragMoves++;[self refresh];
|
|
158
|
+
}else if(pan.state==UIGestureRecognizerStateEnded){
|
|
159
|
+
CGPoint velocity=[pan velocityInView:self.container];JoltCircleRelease(&state,(int)i,velocity.x,velocity.y);
|
|
160
|
+
self.dragging=-1;self.dragEnds++;[self refresh];
|
|
161
|
+
}else if(pan.state==UIGestureRecognizerStateCancelled||pan.state==UIGestureRecognizerStateFailed)[self cancelDrag];
|
|
162
|
+
}
|
|
163
|
+
- (void)cancelDrag {
|
|
164
|
+
if(self.dragging<0)return;
|
|
165
|
+
JoltCircleCancel(&state,(int)self.dragging);self.dragging=-1;self.dragCancels++;[self apply];
|
|
166
|
+
}
|
|
167
|
+
- (void)setEnabled:(BOOL)enabled {
|
|
168
|
+
if(self.disposed)return;BOOL changed=_enabled!=enabled;_enabled=enabled;
|
|
169
|
+
if(!enabled)[self cancelDrag];else if(changed)JoltCircleWake(&state);
|
|
170
|
+
[self refresh];
|
|
171
|
+
}
|
|
172
|
+
- (void)backgrounded {self.background=YES;[self cancelDrag];[self refresh];}
|
|
173
|
+
- (void)foregrounded {self.background=NO;[self refresh];}
|
|
174
|
+
- (void)resize:(double)width height:(double)height {
|
|
175
|
+
if(self.disposed)return;
|
|
176
|
+
self.fits=JoltCircleFits(&state,width,height);
|
|
177
|
+
if(!self.fits){[self cancelDrag];[self refresh];return;}
|
|
178
|
+
if(fabs(width-state.width)>.1||fabs(height-state.height)>.1){[self cancelDrag];JoltCircleResize(&state,width,height);}
|
|
179
|
+
[self apply];[self refresh];
|
|
180
|
+
}
|
|
181
|
+
- (void)impulse:(NSInteger)index x:(double)x y:(double)y {
|
|
182
|
+
if(![self ready]||index<0||index>=state.count||state.bodies[index].held||!isfinite(x)||!isfinite(y))return;
|
|
183
|
+
JoltCircle *b=&state.bodies[index];b->vx+=x/b->m;b->vy+=y/b->m;JoltCircleLimitVelocity(b);JoltCircleWake(&state);[self refresh];
|
|
184
|
+
}
|
|
185
|
+
- (void)reset {
|
|
186
|
+
if(self.disposed)return;[self cancelDrag];
|
|
187
|
+
for(int i=0;i<state.count;i++){JoltCircle *b=&state.bodies[i];b->x=initialX[i]*state.width;b->y=initialY[i]*state.height;b->vx=initialVX[i];b->vy=initialVY[i];b->snap.active=b->snap.previousActive=false;b->released=false;}
|
|
188
|
+
JoltCircleContacts(&state,false,64);JoltCircleWake(&state);[self apply];[self refresh];
|
|
189
|
+
}
|
|
190
|
+
- (NSString *)snapshot {
|
|
191
|
+
NSMutableArray *bodies=[NSMutableArray new];
|
|
192
|
+
NSUInteger guideCount=0;
|
|
193
|
+
for(NSArray *list in @[self.guides,self.pointerGuides])for(id guide in list)if(guide!=NSNull.null)guideCount++;
|
|
194
|
+
for(int i=0;i<state.count;i++){
|
|
195
|
+
JoltCircle *b=&state.bodies[i];
|
|
196
|
+
id attachment=b->attachment.enabled?@{@"anchor":@{@"x":@(b->attachment.u*state.width),@"y":@(b->attachment.v*state.height)},@"length":@(b->attachment.length),@"stiffness":@(b->attachment.stiffness),@"damping":@(b->attachment.damping)}:NSNull.null;
|
|
197
|
+
id snap=NSNull.null;
|
|
198
|
+
if(b->snap.active){double x=JoltCircleSnapX(&state,b,b->snap.index),y=JoltCircleSnapY(&state,b,b->snap.index);snap=@{@"index":@(b->snap.index),@"point":@{@"x":@(x),@"y":@(y)},@"settled":[NSNumber numberWithBool:hypot(b->x-x,b->y-y)<=.25&&hypot(b->vx,b->vy)<=4&&!b->held]};}
|
|
199
|
+
id pointer=b->held&&b->drag.enabled?@{@"anchor":@{@"x":@(b->tx),@"y":@(b->ty)},@"length":@(b->drag.length),@"stiffness":@(b->drag.stiffness),@"damping":@(b->drag.damping)}:NSNull.null;
|
|
200
|
+
id release=b->released?@{@"x":@(b->releaseX),@"y":@(b->releaseY),@"vx":@(b->releaseVX),@"vy":@(b->releaseVY)}:NSNull.null;
|
|
201
|
+
[bodies addObject:@{@"x":@(b->x),@"y":@(b->y),@"vx":@(b->vx),@"vy":@(b->vy),@"radius":@(b->r),@"held":@(b->held),@"attachment":attachment,@"pointer":pointer,@"snap":snap,@"release":release}];
|
|
202
|
+
}
|
|
203
|
+
NSString *status=self.disposed?@"disposed":!self.enabled?@"paused":self.background||!self.container.window?@"detached":!self.fits?@"invalid-bounds":state.sleeping?@"sleeping":@"running";
|
|
204
|
+
NSDictionary *data=@{@"status":status,@"guides":@(guideCount),@"bodies":bodies,@"frames":@(self.frames),@"steps":@(state.steps),@"contacts":@(state.contacts),@"dragStarts":@(self.dragStarts),@"dragMoves":@(self.dragMoves),@"dragEnds":@(self.dragEnds),@"dragCancels":@(self.dragCancels),@"processingMs":@(self.processingMs),@"droppedMs":@(self.droppedMs),@"clock":[NSNumber numberWithBool:self.link!=nil]};
|
|
205
|
+
return [[NSString alloc]initWithData:[NSJSONSerialization dataWithJSONObject:data options:0 error:nil] encoding:NSUTF8StringEncoding];
|
|
206
|
+
}
|
|
207
|
+
- (void)dispose {
|
|
208
|
+
if(self.disposed)return;self.enabled=NO;self.disposed=YES;[self cancelDrag];[self refresh];
|
|
209
|
+
[[NSNotificationCenter defaultCenter]removeObserver:self];
|
|
210
|
+
[CATransaction begin];[CATransaction setDisableActions:YES];
|
|
211
|
+
for(int i=0;i<state.count;i++)if(self.views[i]!=NSNull.null){
|
|
212
|
+
UIView *v=self.views[i];v.userInteractionEnabled=originalInteraction[i];if(self.pans[i]!=NSNull.null)[v removeGestureRecognizer:self.pans[i]];
|
|
213
|
+
[v.layer setValue:@(originalX[i]) forKeyPath:@"transform.translation.x"];[v.layer setValue:@(originalY[i]) forKeyPath:@"transform.translation.y"];
|
|
214
|
+
}
|
|
215
|
+
for(NSMutableArray *list in @[self.guides,self.pointerGuides]){for(id guide in list)if(guide!=NSNull.null)[guide removeFromSuperlayer];[list removeAllObjects];}
|
|
216
|
+
[CATransaction commit];[self.views removeAllObjects];[self.pans removeAllObjects];self.container=nil;[worlds removeObject:self];
|
|
217
|
+
}
|
|
218
|
+
@end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
#import "JoltLiveSpring.h"
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
@interface JoltGestureSession : NSObject
|
|
6
|
+
@property(nonatomic, readonly) BOOL active;
|
|
7
|
+
+ (BOOL)supportsContactEvents;
|
|
8
|
+
// Development-only semantic input. Requires the isolated "replay" option.
|
|
9
|
+
+ (BOOL)supportsScrollReplay;
|
|
10
|
+
+ (BOOL)hasSession:(UIView *)surface;
|
|
11
|
+
- (void)replayScroll:(NSInteger)phase delta:(double)delta velocity:(double)velocity;
|
|
12
|
+
- (void)replayScrollOffset:(double)offset;
|
|
13
|
+
+ (instancetype)attach:(UIView *)surface scroll:(nullable UIScrollView *)scroll
|
|
14
|
+
x:(JoltLiveSpring *)x y:(JoltLiveSpring *)y scale:(JoltLiveSpring *)scale rotation:(JoltLiveSpring *)rotation
|
|
15
|
+
options:(NSString *)options onState:(void (^)(NSInteger, double, double))onState;
|
|
16
|
+
- (void)cancel;
|
|
17
|
+
- (void)refreshScrollDelegate;
|
|
18
|
+
- (void)setEnabled:(BOOL)enabled;
|
|
19
|
+
- (void)settleX:(double)x y:(double)y scale:(double)scale rotation:(double)rotation animated:(BOOL)animated;
|
|
20
|
+
- (void)updateLeft:(double)left right:(double)right top:(double)top bottom:(double)bottom;
|
|
21
|
+
- (void)dispose;
|
|
22
|
+
@end
|
|
23
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#import "JoltGestureSession.h"
|
|
2
|
+
#import <UIKit/UIGestureRecognizerSubclass.h>
|
|
3
|
+
|
|
4
|
+
static double clamp(double value, double minimum, double maximum) { return MAX(minimum, MIN(maximum, value)); }
|
|
5
|
+
@class JoltGestureSession;
|
|
6
|
+
|
|
7
|
+
/* Centroid tracking in window coordinates. Pointer membership changes rebase without movement. */
|
|
8
|
+
@interface JoltAxisPan : UIGestureRecognizer
|
|
9
|
+
@property(nonatomic, weak) JoltGestureSession *owner;
|
|
10
|
+
@property(nonatomic) NSMutableSet<UITouch *> *contacts;
|
|
11
|
+
@property(nonatomic) CGPoint previous, origin, delta, velocity;
|
|
12
|
+
@property(nonatomic) double previousTime, threshold, failOffset;
|
|
13
|
+
@property(nonatomic) NSInteger axis;
|
|
14
|
+
- (void)rebase;
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
@interface JoltGestureSession () <UIGestureRecognizerDelegate, UIScrollViewDelegate>
|
|
18
|
+
@property(nonatomic, weak) UIView *surface;
|
|
19
|
+
@property(nonatomic, weak) UIScrollView *scroll;
|
|
20
|
+
@property(nonatomic) id<UIScrollViewDelegate> previousDelegate;
|
|
21
|
+
@property(nonatomic) JoltAxisPan *pan;
|
|
22
|
+
@property(nonatomic) UIPinchGestureRecognizer *pinch;
|
|
23
|
+
@property(nonatomic) UIRotationGestureRecognizer *rotate;
|
|
24
|
+
@property(nonatomic) UITapGestureRecognizer *tap, *doubleTap;
|
|
25
|
+
@property(nonatomic) JoltLiveSpring *x, *y, *scale, *rotation;
|
|
26
|
+
@property(nonatomic) double minX, maxX, minY, maxY, minScale, maxScale, velocityX, velocityY, scrollPosition;
|
|
27
|
+
@property(nonatomic, readwrite) BOOL active;
|
|
28
|
+
@property(nonatomic) BOOL enabled, disposed, contactEvents, contact, fromScroll, adjusting, ending, replayOnly;
|
|
29
|
+
@property(nonatomic, copy) void (^onState)(NSInteger, double, double);
|
|
30
|
+
- (void)touchStarted:(UITouch *)touch;
|
|
31
|
+
- (void)finish:(BOOL)cancelled;
|
|
32
|
+
- (void)applyScroll;
|
|
33
|
+
@end
|
|
34
|
+
|
|
35
|
+
@implementation JoltAxisPan
|
|
36
|
+
- (instancetype)initWithTarget:(id)target action:(SEL)action {
|
|
37
|
+
if ((self = [super initWithTarget:target action:action])) self.contacts = [NSMutableSet new];
|
|
38
|
+
return self;
|
|
39
|
+
}
|
|
40
|
+
- (CGPoint)centroid {
|
|
41
|
+
CGPoint point = CGPointZero;
|
|
42
|
+
for (UITouch *touch in self.contacts) { CGPoint p = [touch locationInView:nil]; point.x += p.x; point.y += p.y; }
|
|
43
|
+
if (self.contacts.count) { point.x /= self.contacts.count; point.y /= self.contacts.count; }
|
|
44
|
+
return point;
|
|
45
|
+
}
|
|
46
|
+
- (void)rebase { self.previous = [self centroid]; self.previousTime = CACurrentMediaTime(); self.delta = CGPointZero; self.velocity = CGPointZero; }
|
|
47
|
+
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
48
|
+
BOOL first = !self.contacts.count;
|
|
49
|
+
[self.contacts unionSet:touches]; [self rebase];
|
|
50
|
+
if (self.state == UIGestureRecognizerStatePossible) self.origin = self.previous;
|
|
51
|
+
if (first) { self.origin = self.previous; [self.owner touchStarted:touches.anyObject]; }
|
|
52
|
+
}
|
|
53
|
+
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
54
|
+
CGPoint point = [self centroid]; double now = CACurrentMediaTime(), dt = MAX(.001, now - self.previousTime);
|
|
55
|
+
self.delta = CGPointMake(point.x - self.previous.x, point.y - self.previous.y);
|
|
56
|
+
self.velocity = CGPointMake(self.delta.x / dt, self.delta.y / dt);
|
|
57
|
+
self.previous = point; self.previousTime = now;
|
|
58
|
+
if (self.state == UIGestureRecognizerStatePossible) {
|
|
59
|
+
double dx = fabs(point.x - self.origin.x), dy = fabs(point.y - self.origin.y);
|
|
60
|
+
if ((self.axis == 1 && dy > self.failOffset) || (self.axis == 2 && dx > self.failOffset)) { self.state = UIGestureRecognizerStateFailed; return; }
|
|
61
|
+
double distance = self.axis == 1 ? dx : self.axis == 2 ? dy : hypot(dx, dy);
|
|
62
|
+
if (self.axis && distance >= self.threshold) self.state = UIGestureRecognizerStateBegan;
|
|
63
|
+
} else if (self.state == UIGestureRecognizerStateBegan || self.state == UIGestureRecognizerStateChanged) self.state = UIGestureRecognizerStateChanged;
|
|
64
|
+
}
|
|
65
|
+
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
66
|
+
[self.contacts minusSet:touches];
|
|
67
|
+
if (self.contacts.count) [self rebase];
|
|
68
|
+
else {
|
|
69
|
+
if (CACurrentMediaTime() - self.previousTime > .08) self.velocity = CGPointZero;
|
|
70
|
+
self.owner.velocityX = (self.axis & 1) ? self.velocity.x : 0; self.owner.velocityY = (self.axis & 2) ? self.velocity.y : 0;
|
|
71
|
+
self.state = self.state == UIGestureRecognizerStatePossible ? UIGestureRecognizerStateFailed : UIGestureRecognizerStateEnded;
|
|
72
|
+
[self.owner finish:NO];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.state = UIGestureRecognizerStateCancelled; [self.owner finish:YES]; }
|
|
76
|
+
- (void)reset { [super reset]; [self.contacts removeAllObjects]; self.delta = CGPointZero; self.velocity = CGPointZero; }
|
|
77
|
+
@end
|
|
78
|
+
|
|
79
|
+
@implementation JoltGestureSession
|
|
80
|
+
+ (BOOL)supportsContactEvents { return YES; }
|
|
81
|
+
+ (BOOL)hasSession:(UIView *)surface {
|
|
82
|
+
for (UIGestureRecognizer *g in surface.gestureRecognizers) if ([g isKindOfClass:JoltAxisPan.class]) return YES;
|
|
83
|
+
return NO;
|
|
84
|
+
}
|
|
85
|
+
+ (instancetype)attach:(UIView *)surface scroll:(UIScrollView *)scroll x:(JoltLiveSpring *)x y:(JoltLiveSpring *)y scale:(JoltLiveSpring *)scale rotation:(JoltLiveSpring *)rotation options:(NSString *)options onState:(void (^)(NSInteger,double,double))onState {
|
|
86
|
+
NSDictionary *config = [NSJSONSerialization JSONObjectWithData:[options dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
|
|
87
|
+
if ([config[@"replay"] boolValue] && [self hasSession:surface])
|
|
88
|
+
[NSException raise:NSInvalidArgumentException format:@"Replay requires an unowned gesture surface"];
|
|
89
|
+
JoltGestureSession *s = [self new]; s.surface = surface; s.scroll = scroll; s.x = x; s.y = y; s.scale = scale; s.rotation = rotation;
|
|
90
|
+
s.minX = [config[@"minX"] doubleValue]; s.maxX = [config[@"maxX"] doubleValue]; s.minY = [config[@"minY"] doubleValue]; s.maxY = [config[@"maxY"] doubleValue];
|
|
91
|
+
s.minScale = [config[@"minScale"] doubleValue]; s.maxScale = [config[@"maxScale"] doubleValue]; s.onState = onState; s.enabled = YES;
|
|
92
|
+
s.pan = [[JoltAxisPan alloc] initWithTarget:s action:@selector(panned:)]; s.pan.owner = s;
|
|
93
|
+
s.pan.axis = [config[@"axis"] integerValue]; s.pan.threshold = [config[@"threshold"] doubleValue]; s.pan.failOffset = [config[@"failOffset"] doubleValue];
|
|
94
|
+
s.pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:s action:@selector(pinched:)];
|
|
95
|
+
s.rotate = [[UIRotationGestureRecognizer alloc] initWithTarget:s action:@selector(rotated:)];
|
|
96
|
+
s.tap = [[UITapGestureRecognizer alloc] initWithTarget:s action:@selector(tapped:)];
|
|
97
|
+
s.doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:s action:@selector(tapped:)]; s.doubleTap.numberOfTapsRequired = 2;
|
|
98
|
+
[s.tap requireGestureRecognizerToFail:s.doubleTap];
|
|
99
|
+
for (UIGestureRecognizer *g in @[s.pan, s.pinch, s.rotate, s.tap, s.doubleTap]) { g.delegate = s; [surface addGestureRecognizer:g]; }
|
|
100
|
+
s.pinch.enabled = [config[@"pinch"] boolValue]; s.rotate.enabled = [config[@"rotate"] boolValue];
|
|
101
|
+
s.contactEvents = [config[@"contactEvents"] boolValue];
|
|
102
|
+
s.replayOnly = [config[@"replay"] boolValue];
|
|
103
|
+
s.tap.enabled = [config[@"tap"] boolValue]; s.doubleTap.enabled = [config[@"doubleTap"] boolValue];
|
|
104
|
+
if (s.replayOnly) for (UIGestureRecognizer *g in @[s.pan, s.pinch, s.rotate, s.tap, s.doubleTap]) g.enabled = NO;
|
|
105
|
+
// NativeScript's scroll delegate is forwarded, never replaced with a JS per-frame bridge.
|
|
106
|
+
if (scroll) { s.previousDelegate = scroll.delegate; scroll.delegate = s; }
|
|
107
|
+
return s;
|
|
108
|
+
}
|
|
109
|
+
- (BOOL)respondsToSelector:(SEL)selector { return [super respondsToSelector:selector] || [self.previousDelegate respondsToSelector:selector]; }
|
|
110
|
+
- (void)refreshScrollDelegate {
|
|
111
|
+
if (!self.disposed && self.scroll && self.scroll.delegate != self) {
|
|
112
|
+
self.previousDelegate = self.scroll.delegate; self.scroll.delegate = self;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
- (id)forwardingTargetForSelector:(SEL)selector { return [self.previousDelegate respondsToSelector:selector] ? self.previousDelegate : [super forwardingTargetForSelector:selector]; }
|
|
116
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)first shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)second {
|
|
117
|
+
if ([first isKindOfClass:UITapGestureRecognizer.class] || [second isKindOfClass:UITapGestureRecognizer.class]) return NO;
|
|
118
|
+
return YES;
|
|
119
|
+
}
|
|
120
|
+
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch {
|
|
121
|
+
return self.enabled && !self.disposed;
|
|
122
|
+
}
|
|
123
|
+
- (void)touchStarted:(UITouch *)touch {
|
|
124
|
+
if (self.disposed || !self.enabled) return;
|
|
125
|
+
self.contact = YES; self.fromScroll = self.scroll && [touch.view isDescendantOfView:self.scroll];
|
|
126
|
+
self.scrollPosition = MAX(-self.scroll.adjustedContentInset.top, self.scroll.contentOffset.y);
|
|
127
|
+
self.velocityX = self.velocityY = 0;
|
|
128
|
+
for (JoltLiveSpring *node in @[self.x, self.y, self.scale, self.rotation]) [node releaseInput:node.position velocity:0];
|
|
129
|
+
if (self.contactEvents) [self emit:6];
|
|
130
|
+
}
|
|
131
|
+
- (void)emit:(NSInteger)state { if (!self.disposed && self.onState) self.onState(state, self.velocityX, self.velocityY); }
|
|
132
|
+
- (void)begin {
|
|
133
|
+
if (self.active || self.disposed || !self.enabled) return;
|
|
134
|
+
self.active = YES;
|
|
135
|
+
for (JoltLiveSpring *node in @[self.x, self.y, self.scale, self.rotation]) [node holdInput:node.position velocity:0];
|
|
136
|
+
[self emit:1];
|
|
137
|
+
}
|
|
138
|
+
- (void)panned:(JoltAxisPan *)pan {
|
|
139
|
+
if (self.disposed || !self.enabled) return;
|
|
140
|
+
if (pan.state == UIGestureRecognizerStateBegan || pan.state == UIGestureRecognizerStateChanged) {
|
|
141
|
+
[self begin]; if (self.disposed || !self.enabled || !self.active) return;
|
|
142
|
+
self.velocityX = (pan.axis & 1) ? pan.velocity.x : 0; self.velocityY = (pan.axis & 2) ? pan.velocity.y : 0;
|
|
143
|
+
double dx = pan.delta.x, dy = pan.delta.y;
|
|
144
|
+
if (self.fromScroll) {
|
|
145
|
+
[self consumeScrollDelta:dy];
|
|
146
|
+
} else {
|
|
147
|
+
if (pan.axis & 1) [self.x holdInput:clamp(self.x.position + dx, self.minX, self.maxX) velocity:self.velocityX];
|
|
148
|
+
if (pan.axis & 2) [self.y holdInput:clamp(self.y.position + dy, self.minY, self.maxY) velocity:self.velocityY];
|
|
149
|
+
}
|
|
150
|
+
} else if (pan.state == UIGestureRecognizerStateEnded) [self finish:NO];
|
|
151
|
+
else if (pan.state == UIGestureRecognizerStateCancelled || pan.state == UIGestureRecognizerStateFailed) [self finish:YES];
|
|
152
|
+
}
|
|
153
|
+
// Shared by the OS recognizer and the isolated semantic replay adapter.
|
|
154
|
+
- (void)consumeScrollDelta:(double)dy {
|
|
155
|
+
double oldY = self.y.position, nextY = oldY, top = -self.scroll.adjustedContentInset.top;
|
|
156
|
+
if (dy < 0) { nextY = MAX(self.minY, oldY + dy); dy -= nextY - oldY; }
|
|
157
|
+
else {
|
|
158
|
+
double consumed = MIN(dy, MAX(0, self.scrollPosition - top));
|
|
159
|
+
self.scrollPosition -= consumed; dy -= consumed;
|
|
160
|
+
nextY = MIN(self.maxY, oldY + dy); dy -= nextY - oldY;
|
|
161
|
+
}
|
|
162
|
+
double bottom = MAX(top, self.scroll.contentSize.height - self.scroll.bounds.size.height + self.scroll.adjustedContentInset.bottom);
|
|
163
|
+
self.scrollPosition = clamp(self.scrollPosition - dy, top, bottom);
|
|
164
|
+
[self.y holdInput:nextY velocity:self.velocityY]; [self applyScroll];
|
|
165
|
+
}
|
|
166
|
+
+ (BOOL)supportsScrollReplay { return YES; }
|
|
167
|
+
- (void)replayScroll:(NSInteger)phase delta:(double)dy velocity:(double)velocity {
|
|
168
|
+
if (!self.replayOnly || self.disposed || !self.scroll || !isfinite(dy) || !isfinite(velocity))
|
|
169
|
+
[NSException raise:NSInvalidArgumentException format:@"Scroll replay needs an isolated replay session and finite input"];
|
|
170
|
+
if (phase == 1) {
|
|
171
|
+
[self cancel]; self.contact = YES; self.fromScroll = YES;
|
|
172
|
+
self.scrollPosition = MAX(-self.scroll.adjustedContentInset.top, self.scroll.contentOffset.y);
|
|
173
|
+
self.velocityX = self.velocityY = 0; [self begin];
|
|
174
|
+
} else if (phase == 2 && self.contact) {
|
|
175
|
+
self.velocityY = velocity; [self consumeScrollDelta:dy];
|
|
176
|
+
} else if (phase == 3 || phase == 4) [self finish:phase == 4];
|
|
177
|
+
}
|
|
178
|
+
- (void)replayScrollOffset:(double)offset {
|
|
179
|
+
if (!self.replayOnly || self.disposed || !isfinite(offset))
|
|
180
|
+
[NSException raise:NSInvalidArgumentException format:@"Invalid scroll replay offset"];
|
|
181
|
+
self.scrollPosition = -self.scroll.adjustedContentInset.top + offset; [self applyScroll];
|
|
182
|
+
}
|
|
183
|
+
- (void)pinched:(UIPinchGestureRecognizer *)gesture {
|
|
184
|
+
if (self.fromScroll || self.disposed || !self.enabled) return;
|
|
185
|
+
if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged) {
|
|
186
|
+
[self begin]; if (self.disposed || !self.active) return;
|
|
187
|
+
[self.scale holdInput:clamp(self.scale.position * gesture.scale, self.minScale, self.maxScale) velocity:0]; gesture.scale = 1;
|
|
188
|
+
} else if (!self.pan.contacts.count) [self finish:gesture.state == UIGestureRecognizerStateCancelled];
|
|
189
|
+
}
|
|
190
|
+
- (void)rotated:(UIRotationGestureRecognizer *)gesture {
|
|
191
|
+
if (self.fromScroll || self.disposed || !self.enabled) return;
|
|
192
|
+
if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged) {
|
|
193
|
+
[self begin]; if (self.disposed || !self.active) return;
|
|
194
|
+
[self.rotation holdInput:self.rotation.position + gesture.rotation * 180 / M_PI velocity:0]; gesture.rotation = 0;
|
|
195
|
+
} else if (!self.pan.contacts.count) [self finish:gesture.state == UIGestureRecognizerStateCancelled];
|
|
196
|
+
}
|
|
197
|
+
- (void)tapped:(UITapGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateRecognized) [self emit:gesture == self.doubleTap ? 5 : 4]; }
|
|
198
|
+
- (void)applyScroll {
|
|
199
|
+
if (!self.scroll || self.adjusting) return;
|
|
200
|
+
self.adjusting = YES;
|
|
201
|
+
[self.scroll setContentOffset:CGPointMake(self.scroll.contentOffset.x, self.scrollPosition) animated:NO];
|
|
202
|
+
self.adjusting = NO;
|
|
203
|
+
}
|
|
204
|
+
- (void)scrollViewDidScroll:(UIScrollView *)scroll {
|
|
205
|
+
if (self.contact && self.fromScroll && !self.adjusting) [self applyScroll];
|
|
206
|
+
if (!self.adjusting && [self.previousDelegate respondsToSelector:_cmd]) [self.previousDelegate scrollViewDidScroll:scroll];
|
|
207
|
+
}
|
|
208
|
+
- (void)scrollViewWillEndDragging:(UIScrollView *)scroll withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)target {
|
|
209
|
+
if (self.y.position > self.minY + .01) target->y = scroll.contentOffset.y;
|
|
210
|
+
if ([self.previousDelegate respondsToSelector:_cmd]) [self.previousDelegate scrollViewWillEndDragging:scroll withVelocity:velocity targetContentOffset:target];
|
|
211
|
+
}
|
|
212
|
+
- (void)finish:(BOOL)cancelled {
|
|
213
|
+
BOOL hadContact = self.contact;
|
|
214
|
+
self.contact = NO;
|
|
215
|
+
if (!self.active) { if (hadContact && self.contactEvents) [self emit:7]; return; }
|
|
216
|
+
self.active = NO;
|
|
217
|
+
for (JoltLiveSpring *node in @[self.x, self.y, self.scale, self.rotation]) [node releaseInput:node.position velocity:0];
|
|
218
|
+
self.ending = !cancelled;
|
|
219
|
+
@try { [self emit:cancelled ? 3 : 2]; } @finally { self.ending = NO; }
|
|
220
|
+
if (hadContact && self.contactEvents) [self emit:7];
|
|
221
|
+
}
|
|
222
|
+
- (void)cancel {
|
|
223
|
+
if (self.active) [self finish:YES];
|
|
224
|
+
else {
|
|
225
|
+
[self finish:YES];
|
|
226
|
+
for (JoltLiveSpring *node in @[self.x, self.y, self.scale, self.rotation]) [node releaseInput:node.position velocity:0];
|
|
227
|
+
}
|
|
228
|
+
for (UIGestureRecognizer *g in @[self.pan, self.pinch, self.rotate, self.tap, self.doubleTap]) if (g.enabled) { g.enabled = NO; g.enabled = YES; }
|
|
229
|
+
}
|
|
230
|
+
- (void)setEnabled:(BOOL)value { _enabled = value; if (!value) [self cancel]; }
|
|
231
|
+
- (void)settleX:(double)x y:(double)y scale:(double)scale rotation:(double)rotation animated:(BOOL)animated {
|
|
232
|
+
if (self.disposed) return;
|
|
233
|
+
double vx = self.ending ? self.velocityX : self.x.velocity, vy = self.ending ? self.velocityY : self.y.velocity;
|
|
234
|
+
[self cancel];
|
|
235
|
+
double targets[] = {clamp(x, self.minX, self.maxX), clamp(y, self.minY, self.maxY), clamp(scale, self.minScale, self.maxScale), rotation};
|
|
236
|
+
NSArray *nodes = @[self.x, self.y, self.scale, self.rotation];
|
|
237
|
+
for (NSUInteger i = 0; i < nodes.count; i++) {
|
|
238
|
+
JoltLiveSpring *node = nodes[i];
|
|
239
|
+
if (!animated) [node holdInput:targets[i] velocity:0];
|
|
240
|
+
[node releaseInput:targets[i] velocity:animated ? i == 0 ? vx : i == 1 ? vy : 0 : 0];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
- (void)updateLeft:(double)left right:(double)right top:(double)top bottom:(double)bottom { self.minX = left; self.maxX = right; self.minY = top; self.maxY = bottom; }
|
|
244
|
+
- (void)dispose {
|
|
245
|
+
if (self.disposed) return;
|
|
246
|
+
[self cancel]; self.disposed = YES;
|
|
247
|
+
for (UIGestureRecognizer *g in @[self.pan, self.pinch, self.rotate, self.tap, self.doubleTap]) [self.surface removeGestureRecognizer:g];
|
|
248
|
+
if (self.scroll.delegate == self) self.scroll.delegate = self.previousDelegate;
|
|
249
|
+
self.previousDelegate = nil; self.onState = nil;
|
|
250
|
+
}
|
|
251
|
+
@end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
3
|
+
|
|
4
|
+
/** Frame's delegate supplies this object to UIKit; it never replaces that delegate. */
|
|
5
|
+
@interface JoltInteractiveNavigation : NSObject <UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning, UIGestureRecognizerDelegate>
|
|
6
|
+
+ (instancetype)attach:(UINavigationController *)navigation stiffness:(double)stiffness
|
|
7
|
+
damping:(double)damping mass:(double)mass
|
|
8
|
+
shouldBegin:(BOOL (^)(void))shouldBegin onEvent:(void (^)(NSInteger))onEvent;
|
|
9
|
+
+ (NSUInteger)activeCount;
|
|
10
|
+
+ (NSUInteger)recognizerCount;
|
|
11
|
+
@property(nonatomic, readonly) BOOL interactive;
|
|
12
|
+
@property(nonatomic, readonly) double progress;
|
|
13
|
+
@property(nonatomic, readonly) double velocity;
|
|
14
|
+
@property(nonatomic) BOOL sharedEnabled;
|
|
15
|
+
@property(nonatomic) BOOL sharedDeferred;
|
|
16
|
+
- (void)completeSharedPreparation;
|
|
17
|
+
- (BOOL)prepareSharedFrom:(UIView *)from to:(UIView *)to image:(BOOL)image fromRadius:(double)fromRadius toRadius:(double)toRadius maxPixels:(double)maxPixels;
|
|
18
|
+
- (void)prepareOperation:(NSInteger)operation presented:(UIViewController *)presented reduced:(BOOL)reduced timeScale:(double)timeScale;
|
|
19
|
+
- (void)sync;
|
|
20
|
+
- (void)cancel;
|
|
21
|
+
- (void)disposeRestoringSwipe:(BOOL)enabled;
|
|
22
|
+
@end
|
|
23
|
+
NS_ASSUME_NONNULL_END
|