|
1 | 1 | <script lang="ts"> |
| 2 | + import { onDestroy } from 'svelte' |
| 3 | + import { roundTo } from '../../util/misc' |
2 | 4 | import { Valuable } from '../../util/stores' |
3 | 5 | import BaseDialogItem from './baseDialogItem.svelte' |
4 | 6 |
|
5 | 7 | export let label: string |
6 | 8 | export let tooltip: string = '' |
7 | 9 | export let value: Valuable<number> |
8 | 10 | export let defaultValue: number |
9 | | - export let min: number | undefined = undefined |
10 | | - export let max: number | undefined = undefined |
11 | | - export let step: number | undefined = undefined |
12 | | -
|
13 | | - const molangParser = new Molang() |
| 11 | + export let min = -Infinity |
| 12 | + export let max = Infinity |
| 13 | + /** Minimum difference between two unique values */ |
| 14 | + export let valueStep = 0.1 |
| 15 | + /** How much to change when dragging */ |
| 16 | + export let dragStep: number | undefined = valueStep |
14 | 17 |
|
15 | 18 | let input: HTMLInputElement |
16 | 19 | let slider: HTMLElement |
17 | 20 |
|
18 | | - requestAnimationFrame(() => { |
19 | | - addEventListeners(slider, 'mousedown touchstart', (e1: any) => { |
20 | | - convertTouchEvent(e1) |
21 | | - let last_difference = 0 |
22 | | - function move(e2: any) { |
23 | | - convertTouchEvent(e2) |
24 | | - let difference = Math.trunc((e2.clientX - e1.clientX) / 10) * (step || 1) |
25 | | - if (difference != last_difference) { |
26 | | - value.set( |
27 | | - Math.clamp( |
28 | | - value.get() + (difference - last_difference), |
29 | | - min !== undefined ? min : -Infinity, |
30 | | - max !== undefined ? max : Infinity, |
31 | | - ) || 0, |
32 | | - ) |
33 | | - last_difference = difference |
34 | | - } |
35 | | - } |
36 | | - function stop(e2: any) { |
37 | | - removeEventListeners(document, 'mousemove touchmove', move, null) |
38 | | - removeEventListeners(document, 'mouseup touchend', stop, null) |
| 21 | + const clampValue = (v: number) => { |
| 22 | + return Math.clamp(roundTo(v, 1 / (valueStep ?? 1)), min, max) || 0 |
| 23 | + } |
| 24 | +
|
| 25 | + const onStartDrag = (moveEvent: MouseEvent | TouchEvent) => { |
| 26 | + const mouseStartEvent = convertTouchEvent(moveEvent) |
| 27 | + const originalValue = value.get() |
| 28 | +
|
| 29 | + const drag = (moveEvent: MouseEvent | TouchEvent) => { |
| 30 | + const mouseEndEvent = convertTouchEvent(moveEvent) |
| 31 | + const diff = |
| 32 | + Math.trunc((mouseEndEvent.clientX - mouseStartEvent.clientX) / 10) * (dragStep ?? 1) |
| 33 | + const adjustedValue = clampValue(originalValue + diff) |
| 34 | + if (adjustedValue !== value.get()) { |
| 35 | + value.set(adjustedValue) |
39 | 36 | } |
40 | | - addEventListeners(document as unknown as any, 'mousemove touchmove', move) |
41 | | - addEventListeners(document as unknown as any, 'mouseup touchend', stop) |
42 | | - }) |
| 37 | + } |
| 38 | +
|
| 39 | + addEventListeners(document, 'mousemove touchmove', drag) |
| 40 | + addEventListeners( |
| 41 | + document, |
| 42 | + 'mouseup touchend', |
| 43 | + () => removeEventListeners(document, 'mousemove touchmove', drag), // End drag |
| 44 | + { once: true } |
| 45 | + ) |
| 46 | + } |
| 47 | +
|
| 48 | + const MOLANG_PARSER = new Molang() |
| 49 | + const onInput = () => { |
| 50 | + value.set(clampValue(MOLANG_PARSER.parse(value.get()))) |
| 51 | + } |
| 52 | +
|
| 53 | + // onMount |
| 54 | + requestAnimationFrame(() => { |
| 55 | + addEventListeners(slider, 'mousedown touchstart', onStartDrag) |
| 56 | + addEventListeners(input, 'focusout dblclick', onInput) |
| 57 | + }) |
43 | 58 |
|
44 | | - addEventListeners(input, 'focusout dblclick', () => { |
45 | | - value.set( |
46 | | - Math.clamp( |
47 | | - molangParser.parse(value.get()), |
48 | | - min !== undefined ? min : -Infinity, |
49 | | - max !== undefined ? max : Infinity, |
50 | | - ) || 0, |
51 | | - ) |
52 | | - }) |
| 59 | + onDestroy(() => { |
| 60 | + removeEventListeners(input, 'focusout dblclick', onInput) |
| 61 | + removeEventListeners(slider, 'mousedown touchstart', onStartDrag) |
53 | 62 | }) |
54 | 63 |
|
55 | 64 | function onReset() { |
|
0 commit comments