dazscript-framework 0.1.14 → 0.1.16
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 +365 -93
- package/babel.config.js +33 -33
- package/dist/babel/trace-babel-plugin.js +243 -243
- package/dist/babel/trace-log-babel-plugin.js +164 -164
- package/dist/scripts/install-generator.js +185 -185
- package/package.json +72 -70
- package/src/common/dz-dump.ts +120 -120
- package/src/common/log.ts +56 -57
- package/src/common/trace.ts +26 -26
- package/src/core/action-decorator.ts +15 -15
- package/src/core/base-script.ts +30 -30
- package/src/core/custom-action.ts +11 -11
- package/src/core/global.ts +4 -4
- package/src/dialog/basic-dialog.ts +40 -32
- package/src/dialog/builders/button-builder.ts +52 -52
- package/src/dialog/builders/checkbox-builder.ts +29 -29
- package/src/dialog/builders/color-picker-builder.ts +36 -0
- package/src/dialog/builders/combo-box-builder.ts +38 -35
- package/src/dialog/builders/combo-edit-builder.ts +35 -35
- package/src/dialog/builders/dialog-builder.ts +49 -49
- package/src/dialog/builders/groupbox-builder.ts +121 -73
- package/src/dialog/builders/label-builder.ts +33 -29
- package/src/dialog/builders/layout-builder.ts +59 -59
- package/src/dialog/builders/line-edit-builder.ts +124 -119
- package/src/dialog/builders/list-box-builder.ts +103 -0
- package/src/dialog/builders/list-view-builder.ts +396 -328
- package/src/dialog/builders/node-selection-builder.ts +55 -55
- package/src/dialog/builders/path-combo-box-builder.ts +24 -24
- package/src/dialog/builders/popup-menu-builder.ts +46 -46
- package/src/dialog/builders/radio-builder.ts +42 -42
- package/src/dialog/builders/slider-builder.ts +40 -0
- package/src/dialog/builders/splitter-builder.ts +88 -88
- package/src/dialog/builders/tab-builder.ts +120 -106
- package/src/dialog/builders/widget-builder.ts +136 -124
- package/src/dialog/builders/widgets-builder.ts +140 -125
- package/src/dialog/input-dialog.ts +30 -27
- package/src/dialog/input-validator.ts +8 -8
- package/src/dialog/selection-dialog.ts +47 -0
- package/src/dialog/shared.ts +8 -8
- package/src/helpers/action-helper.ts +214 -81
- package/src/helpers/array-helper.ts +170 -145
- package/src/helpers/camera-helper.ts +12 -12
- package/src/helpers/custom-action-helper.ts +176 -176
- package/src/helpers/directory-helper.ts +14 -0
- package/src/helpers/file-helper.ts +90 -90
- package/src/helpers/http-helper.ts +186 -0
- package/src/helpers/input-helper.ts +18 -18
- package/src/helpers/list-view-helper.ts +105 -89
- package/src/helpers/menu-helper.ts +28 -28
- package/src/helpers/message-box-helper.ts +25 -15
- package/src/helpers/node-helper.ts +461 -236
- package/src/helpers/number-helper.ts +10 -10
- package/src/helpers/numeric-property-helper.ts +91 -91
- package/src/helpers/object-helper.ts +2 -2
- package/src/helpers/pane-helper.ts +28 -20
- package/src/helpers/progress-helper.ts +51 -33
- package/src/helpers/property-helper.ts +61 -52
- package/src/helpers/record-helper.ts +16 -16
- package/src/helpers/scene-helper.ts +144 -95
- package/src/helpers/script-helper.ts +15 -15
- package/src/helpers/skeleton-helper.ts +26 -26
- package/src/helpers/splitter-helper.ts +8 -8
- package/src/helpers/string-helper.ts +39 -31
- package/src/helpers/surface-helper.ts +5 -5
- package/src/helpers/undo-helper.ts +8 -7
- package/src/helpers/viewport-helper.ts +21 -8
- package/src/lib/delayed.ts +38 -38
- package/src/lib/dictionary.ts +3 -0
- package/src/lib/frame-keys.ts +67 -67
- package/src/lib/guid.ts +2 -2
- package/src/lib/menu-item.ts +10 -9
- package/src/lib/observable.ts +147 -94
- package/src/lib/set.ts +50 -25
- package/src/lib/settings.ts +112 -104
- package/src/lib/tree-node.ts +149 -145
- package/src/samples/config.ts +2 -2
- package/src/samples/hello-world.dsa.ts +12 -12
- package/src/samples/sample-dialog.dsa.ts +51 -51
- package/src/samples/sample-dialog.ts +48 -48
- package/src/shared/set-keyboard-shortcut.ts +146 -102
- package/tsconfig.json +116 -116
- package/webpack.config.js +70 -70
|
@@ -1,81 +1,214 @@
|
|
|
1
|
-
import { debug, warn } from '@dsf/common/log'
|
|
2
|
-
import { mainWindow } from '@dsf/core/global'
|
|
3
|
-
import { isGUID } from './string-helper'
|
|
4
|
-
|
|
5
|
-
const actionMgr = mainWindow.getActionMgr()
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
import { debug, warn } from '@dsf/common/log'
|
|
2
|
+
import { mainWindow } from '@dsf/core/global'
|
|
3
|
+
import { isGUID } from './string-helper'
|
|
4
|
+
|
|
5
|
+
const actionMgr = mainWindow.getActionMgr()
|
|
6
|
+
|
|
7
|
+
const shortcutTokenMap: { [key: string]: string } = {
|
|
8
|
+
'CTRL': 'Ctrl',
|
|
9
|
+
'CONTROL': 'Ctrl',
|
|
10
|
+
'SHIFT': 'Shift',
|
|
11
|
+
'ALT': 'Alt',
|
|
12
|
+
'OPTION': 'Alt',
|
|
13
|
+
'WIN': 'Win',
|
|
14
|
+
'WINDOWS': 'Win',
|
|
15
|
+
'CMD': 'Win',
|
|
16
|
+
'COMMAND': 'Win',
|
|
17
|
+
'SPACE': 'Space',
|
|
18
|
+
'HOME': 'Home',
|
|
19
|
+
'END': 'End',
|
|
20
|
+
'INS': 'Ins',
|
|
21
|
+
'INSERT': 'Ins',
|
|
22
|
+
'DEL': 'Del',
|
|
23
|
+
'DELETE': 'Del',
|
|
24
|
+
'TAB': 'Tab',
|
|
25
|
+
'BACKSPACE': 'Backspace',
|
|
26
|
+
'COMMA': 'Comma',
|
|
27
|
+
'PERIOD': 'Period',
|
|
28
|
+
'PLUS': 'Plus',
|
|
29
|
+
'MINUS': 'Minus',
|
|
30
|
+
'PGUP': 'PgUp',
|
|
31
|
+
'PAGEUP': 'PgUp',
|
|
32
|
+
'PGDOWN': 'PgDn',
|
|
33
|
+
'PGDN': 'PgDn',
|
|
34
|
+
'LEFT': 'Left',
|
|
35
|
+
'RIGHT': 'Right',
|
|
36
|
+
'UP': 'Up',
|
|
37
|
+
'DOWN': 'Down',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const normalizeShortcut = (shortcut: string): string => {
|
|
41
|
+
if (!shortcut) return ''
|
|
42
|
+
|
|
43
|
+
return shortcut
|
|
44
|
+
.split('+')
|
|
45
|
+
.map(part => part.trim())
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
.map(part => {
|
|
48
|
+
if (part.length === 1) return part.toUpperCase()
|
|
49
|
+
|
|
50
|
+
const key = part.toUpperCase()
|
|
51
|
+
return shortcutTokenMap[key] || part
|
|
52
|
+
})
|
|
53
|
+
.join('+')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type ActionShortcutEntry = {
|
|
57
|
+
action: DzAction
|
|
58
|
+
shortcut: string
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getAllActions = (): ActionShortcutEntry[] => {
|
|
62
|
+
const actions: ActionShortcutEntry[] = []
|
|
63
|
+
|
|
64
|
+
const numActions = actionMgr.getNumActions()
|
|
65
|
+
for (let i = 0; i < numActions; i++) {
|
|
66
|
+
const action = actionMgr.getAction(i)
|
|
67
|
+
if (!action) continue
|
|
68
|
+
|
|
69
|
+
actions.push({
|
|
70
|
+
action,
|
|
71
|
+
shortcut: String(action.shortcut?.toString() ?? '').trim()
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const numCustomActions = actionMgr.getNumCustomActions()
|
|
76
|
+
for (let i = 0; i < numCustomActions; i++) {
|
|
77
|
+
const action = actionMgr.getCustomActionByIndex(i)
|
|
78
|
+
if (!action) continue
|
|
79
|
+
|
|
80
|
+
actions.push({
|
|
81
|
+
action,
|
|
82
|
+
shortcut: String(actionMgr.getCustomActionShortcut(i) ?? '').trim()
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return actions
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const isCustomAction = (action: string | DzAction): boolean => {
|
|
90
|
+
return typeof action === 'string'
|
|
91
|
+
? isGUID(action)
|
|
92
|
+
: action.inherits('DzCustomAction')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const findAction = (name: string): DzAction | null => {
|
|
96
|
+
return isCustomAction(name)
|
|
97
|
+
? findCustomAction(name)
|
|
98
|
+
: actionMgr.findAction(name)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const actionExists = (name: string): boolean => {
|
|
102
|
+
return findAction(name) !== null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export const getCustomActionFilePath = (name: string): string | null => {
|
|
106
|
+
let index = actionMgr.findCustomAction(name)
|
|
107
|
+
if (index < 0) return null
|
|
108
|
+
|
|
109
|
+
let filePath = actionMgr.getCustomActionFile(index)
|
|
110
|
+
return filePath ? filePath.toString() : null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const findCustomActionByFilePath = (filePath: string): DzCustomAction | null => {
|
|
114
|
+
let count = actionMgr.getNumCustomActions()
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < count; i++) {
|
|
117
|
+
let customActionFile = actionMgr.getCustomActionFile(i)
|
|
118
|
+
if (!customActionFile) continue
|
|
119
|
+
if (customActionFile.toString() !== filePath) continue
|
|
120
|
+
|
|
121
|
+
return actionMgr.getCustomActionByIndex(i)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return null
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const findCustomAction = (name: string): DzCustomAction | null => {
|
|
128
|
+
let index = actionMgr.findCustomAction(name)
|
|
129
|
+
return index >= 0
|
|
130
|
+
? actionMgr.getCustomActionByIndex(index)
|
|
131
|
+
: null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const triggerAction = (name: string) => {
|
|
135
|
+
const action = findAction(name)
|
|
136
|
+
if (!action) {
|
|
137
|
+
warn(`Power Menu - Action not found: "${name}"`)
|
|
138
|
+
}
|
|
139
|
+
debug(`Power Menu - Trigger Action: "${action?.text}" (${name})`)
|
|
140
|
+
action?.trigger()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const setActionShortcut = (name: string, shortcut: string) => {
|
|
144
|
+
let action = findAction(name)
|
|
145
|
+
if (!action) return
|
|
146
|
+
const normalizedShortcut = normalizeShortcut(shortcut)
|
|
147
|
+
if (isCustomAction(action)) {
|
|
148
|
+
actionMgr.setCustomActionShortcut(actionMgr.findCustomAction(name), normalizedShortcut)
|
|
149
|
+
debug(`Shortcut set for Custom Action ${action.text}: ${normalizedShortcut}`)
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
actionMgr.setAccel(name, normalizedShortcut)
|
|
153
|
+
debug(`Shortcut set for Action ${action.text}: ${normalizedShortcut}`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export const findActionsForShortcut = (shortcut: string): DzAction[] => {
|
|
159
|
+
if (!shortcut) return []
|
|
160
|
+
|
|
161
|
+
const normalizedShortcut = normalizeShortcut(shortcut)
|
|
162
|
+
const resultEntries = getAllActions().filter(({ shortcut: actionShortcut }) =>
|
|
163
|
+
actionShortcut && normalizeShortcut(actionShortcut) === normalizedShortcut
|
|
164
|
+
)
|
|
165
|
+
const result = resultEntries.map(({ action }) => action)
|
|
166
|
+
|
|
167
|
+
debug(
|
|
168
|
+
`[ShortcutLookup] input="${shortcut}" normalized="${normalizedShortcut}" result=${resultEntries.map(({ action, shortcut }) => `${action?.text || action?.name}=${shortcut}`).join(', ')}`
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
return result
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export const clearActionShorcut = (name: string) => {
|
|
175
|
+
let action = findAction(name)
|
|
176
|
+
if (!action) return
|
|
177
|
+
if (isCustomAction(action)) {
|
|
178
|
+
actionMgr.setCustomActionShortcut(actionMgr.findCustomAction(name), '')
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
actionMgr.setAccel(name, '')
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export const getActionPixmap = (action: string, icon: string, maxSize?: number): QPixmap | null => {
|
|
186
|
+
try {
|
|
187
|
+
if (!action) return null;
|
|
188
|
+
let isCustom = isCustomAction(action)
|
|
189
|
+
|
|
190
|
+
if (isCustom && icon && typeof icon === 'string' && icon) {
|
|
191
|
+
let image: DzImageTexture = (App.getImageMgr() as any)['getImage(QString)'](icon)
|
|
192
|
+
if (image) {
|
|
193
|
+
let size = image.getOriginalImageSize();
|
|
194
|
+
let pixmap: QPixmap
|
|
195
|
+
// Only clamp if maxSize is provided and image is larger
|
|
196
|
+
if (maxSize && (size.width > maxSize || size.height > maxSize)) {
|
|
197
|
+
pixmap = image.getPreviewPixmap(Math.min(size.width, maxSize), Math.min(size.height, maxSize))
|
|
198
|
+
} else {
|
|
199
|
+
pixmap = new Pixmap(image.getFilename())
|
|
200
|
+
}
|
|
201
|
+
return pixmap
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else if (!isCustom) {
|
|
205
|
+
let pixmap = App.getStyle().actionPixmap(action, 0, 0)
|
|
206
|
+
return pixmap?.height === 0 ? null : pixmap
|
|
207
|
+
}
|
|
208
|
+
} catch (error) {
|
|
209
|
+
warn(`Error while trying to get icon pixmap: ${error}`)
|
|
210
|
+
}
|
|
211
|
+
return null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
@@ -1,145 +1,170 @@
|
|
|
1
|
-
import Set from '@dsf/lib/set';
|
|
2
|
-
|
|
3
|
-
export const contains = <T>(array: T[], searchElement: T, fromIndex?: number): boolean => {
|
|
4
|
-
if (array == null) {
|
|
5
|
-
throw new TypeError('Array.prototype includes called on null or undefined');
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const O = Object(array);
|
|
9
|
-
const len = O.length >>> 0;
|
|
10
|
-
|
|
11
|
-
if (len === 0) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
let k = 0;
|
|
16
|
-
|
|
17
|
-
if (fromIndex !== undefined) {
|
|
18
|
-
k = fromIndex | 0;
|
|
19
|
-
k = Math.max(k >= 0 ? k : len - Math.abs(k), 0);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
while (k < len) {
|
|
23
|
-
if (O[k] === searchElement) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
k++;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const find = <T>(array: T[], f: (item: T) => boolean): T | null => {
|
|
33
|
-
for (const item of array) {
|
|
34
|
-
if (f(item)) {
|
|
35
|
-
return item
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return null
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const distinct = <T>(items: T[], f?: (item: T) => any): T[] => {
|
|
42
|
-
const distinctItems: T[] = [];
|
|
43
|
-
const customSet = new Set<T>();
|
|
44
|
-
|
|
45
|
-
for (const item of items) {
|
|
46
|
-
const key = f ? f(item) : item;
|
|
47
|
-
if (!customSet.has(key)) {
|
|
48
|
-
customSet.add(key);
|
|
49
|
-
distinctItems.push(item);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return distinctItems;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Adds the item to the array only if it is not already contained
|
|
58
|
-
* @param array
|
|
59
|
-
* @param item
|
|
60
|
-
* @returns
|
|
61
|
-
*/
|
|
62
|
-
export const append = <T>(array: T[], item: T): T[] => {
|
|
63
|
-
if (!contains(array, item)) {
|
|
64
|
-
array.push(item);
|
|
65
|
-
}
|
|
66
|
-
return array
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
1
|
+
import Set from '@dsf/lib/set';
|
|
2
|
+
|
|
3
|
+
export const contains = <T>(array: T[], searchElement: T, fromIndex?: number): boolean => {
|
|
4
|
+
if (array == null) {
|
|
5
|
+
throw new TypeError('Array.prototype includes called on null or undefined');
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const O = Object(array);
|
|
9
|
+
const len = O.length >>> 0;
|
|
10
|
+
|
|
11
|
+
if (len === 0) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let k = 0;
|
|
16
|
+
|
|
17
|
+
if (fromIndex !== undefined) {
|
|
18
|
+
k = fromIndex | 0;
|
|
19
|
+
k = Math.max(k >= 0 ? k : len - Math.abs(k), 0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
while (k < len) {
|
|
23
|
+
if (O[k] === searchElement) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
k++;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const find = <T>(array: T[], f: (item: T) => boolean): T | null => {
|
|
33
|
+
for (const item of array) {
|
|
34
|
+
if (f(item)) {
|
|
35
|
+
return item
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const distinct = <T>(items: T[], f?: (item: T) => any): T[] => {
|
|
42
|
+
const distinctItems: T[] = [];
|
|
43
|
+
const customSet = new Set<T>();
|
|
44
|
+
|
|
45
|
+
for (const item of items) {
|
|
46
|
+
const key = f ? f(item) : item;
|
|
47
|
+
if (!customSet.has(key)) {
|
|
48
|
+
customSet.add(key);
|
|
49
|
+
distinctItems.push(item);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return distinctItems;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Adds the item to the array only if it is not already contained
|
|
58
|
+
* @param array
|
|
59
|
+
* @param item
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
export const append = <T>(array: T[], item: T): T[] => {
|
|
63
|
+
if (!contains(array, item)) {
|
|
64
|
+
array.push(item);
|
|
65
|
+
}
|
|
66
|
+
return array
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @deprecated Probably inefficient, avoid using in performance critical code
|
|
71
|
+
* @param array
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
export const flattenOld = <T>(array: (T | T[])[]): T[] => {
|
|
75
|
+
const flattened: T[] = [];
|
|
76
|
+
const stack: (T | T[])[] = [...array];
|
|
77
|
+
|
|
78
|
+
while (stack.length) {
|
|
79
|
+
const item = stack.pop();
|
|
80
|
+
if (Array.isArray(item)) {
|
|
81
|
+
// If the item is an array, push its contents onto the stack.
|
|
82
|
+
stack.push(...item);
|
|
83
|
+
} else {
|
|
84
|
+
// If the item is not an array, add it to the flattened array.
|
|
85
|
+
flattened.push(item);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return flattened.reverse(); // Reverse the array to maintain original order.
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Flattens only one level of nested arrays
|
|
94
|
+
* @param array
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
97
|
+
export const flatten = <T>(array: (T | T[])[]): T[] => {
|
|
98
|
+
const out: T[] = [];
|
|
99
|
+
for (let i = 0; i < array.length; i++) {
|
|
100
|
+
const item = array[i];
|
|
101
|
+
if (Array.isArray(item)) {
|
|
102
|
+
for (let j = 0; j < item.length; j++) {
|
|
103
|
+
out.push(item[j]);
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
out.push(item);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const any = <T>(array: T[], f?: (item: T) => boolean): boolean => {
|
|
113
|
+
if (!f)
|
|
114
|
+
return array.length > 0
|
|
115
|
+
|
|
116
|
+
for (const item of array) {
|
|
117
|
+
if (f(item)) {
|
|
118
|
+
return true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const moveToTop = <T>(arr: T[], element: T, findBy: (item: T) => string) => {
|
|
125
|
+
const findByValue = findBy(element);
|
|
126
|
+
let index = -1;
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < arr.length; i++) {
|
|
129
|
+
if (findBy(arr[i]) === findByValue) {
|
|
130
|
+
index = i;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (index > -1) {
|
|
136
|
+
const [removed] = arr.splice(index, 1);
|
|
137
|
+
arr.unshift(removed);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const moveToBottom = <T>(arr: T[], element: T, findBy: (item: T) => string) => {
|
|
143
|
+
const findByValue = findBy(element);
|
|
144
|
+
let index = -1;
|
|
145
|
+
|
|
146
|
+
for (let i = arr.length - 1; i >= 0; i--) {
|
|
147
|
+
if (findBy(arr[i]) === findByValue) {
|
|
148
|
+
index = i;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (index > -1) {
|
|
154
|
+
const [removed] = arr.splice(index, 1);
|
|
155
|
+
arr.push(removed);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const group = <T, K extends string>(array: T[], getKey: (item: T) => K): Record<K, T[]> => {
|
|
161
|
+
let reduced: Record<K, T[]> = array.reduce((previous, currentItem) => {
|
|
162
|
+
let group = getKey(currentItem);
|
|
163
|
+
if (!group) group = "" as K;
|
|
164
|
+
if (!previous[group]) previous[group] = [];
|
|
165
|
+
previous[group].push(currentItem);
|
|
166
|
+
return previous;
|
|
167
|
+
}, {} as Record<K, T[]>);
|
|
168
|
+
return reduced;
|
|
169
|
+
}
|
|
170
|
+
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { mainWindow } from '@dsf/core/global';
|
|
2
|
-
|
|
3
|
-
export const getActiveCamera = ():
|
|
4
|
-
return mainWindow.getViewportMgr().getActiveViewport().get3DViewport().getCamera()
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export const setActiveCamera = (camera: DzCamera) => {
|
|
8
|
-
mainWindow.getViewportMgr().getActiveViewport().get3DViewport().setCamera(camera);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const getPerspectiveCamera = (): DzCamera => {
|
|
12
|
-
return mainWindow.getViewportMgr().getViewCamera(DzCamera.PERSPECTIVE_CAM)
|
|
1
|
+
import { mainWindow } from '@dsf/core/global';
|
|
2
|
+
|
|
3
|
+
export const getActiveCamera = (): DzBasicCamera => {
|
|
4
|
+
return mainWindow.getViewportMgr().getActiveViewport().get3DViewport().getCamera() as DzBasicCamera
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const setActiveCamera = (camera: string | DzCamera) => {
|
|
8
|
+
mainWindow.getViewportMgr().getActiveViewport().get3DViewport().setCamera(camera as any);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getPerspectiveCamera = (): DzCamera => {
|
|
12
|
+
return mainWindow.getViewportMgr().getViewCamera(DzCamera.PERSPECTIVE_CAM)
|
|
13
13
|
}
|