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.
Files changed (82) hide show
  1. package/README.md +365 -93
  2. package/babel.config.js +33 -33
  3. package/dist/babel/trace-babel-plugin.js +243 -243
  4. package/dist/babel/trace-log-babel-plugin.js +164 -164
  5. package/dist/scripts/install-generator.js +185 -185
  6. package/package.json +72 -70
  7. package/src/common/dz-dump.ts +120 -120
  8. package/src/common/log.ts +56 -57
  9. package/src/common/trace.ts +26 -26
  10. package/src/core/action-decorator.ts +15 -15
  11. package/src/core/base-script.ts +30 -30
  12. package/src/core/custom-action.ts +11 -11
  13. package/src/core/global.ts +4 -4
  14. package/src/dialog/basic-dialog.ts +40 -32
  15. package/src/dialog/builders/button-builder.ts +52 -52
  16. package/src/dialog/builders/checkbox-builder.ts +29 -29
  17. package/src/dialog/builders/color-picker-builder.ts +36 -0
  18. package/src/dialog/builders/combo-box-builder.ts +38 -35
  19. package/src/dialog/builders/combo-edit-builder.ts +35 -35
  20. package/src/dialog/builders/dialog-builder.ts +49 -49
  21. package/src/dialog/builders/groupbox-builder.ts +121 -73
  22. package/src/dialog/builders/label-builder.ts +33 -29
  23. package/src/dialog/builders/layout-builder.ts +59 -59
  24. package/src/dialog/builders/line-edit-builder.ts +124 -119
  25. package/src/dialog/builders/list-box-builder.ts +103 -0
  26. package/src/dialog/builders/list-view-builder.ts +396 -328
  27. package/src/dialog/builders/node-selection-builder.ts +55 -55
  28. package/src/dialog/builders/path-combo-box-builder.ts +24 -24
  29. package/src/dialog/builders/popup-menu-builder.ts +46 -46
  30. package/src/dialog/builders/radio-builder.ts +42 -42
  31. package/src/dialog/builders/slider-builder.ts +40 -0
  32. package/src/dialog/builders/splitter-builder.ts +88 -88
  33. package/src/dialog/builders/tab-builder.ts +120 -106
  34. package/src/dialog/builders/widget-builder.ts +136 -124
  35. package/src/dialog/builders/widgets-builder.ts +140 -125
  36. package/src/dialog/input-dialog.ts +30 -27
  37. package/src/dialog/input-validator.ts +8 -8
  38. package/src/dialog/selection-dialog.ts +47 -0
  39. package/src/dialog/shared.ts +8 -8
  40. package/src/helpers/action-helper.ts +214 -81
  41. package/src/helpers/array-helper.ts +170 -145
  42. package/src/helpers/camera-helper.ts +12 -12
  43. package/src/helpers/custom-action-helper.ts +176 -176
  44. package/src/helpers/directory-helper.ts +14 -0
  45. package/src/helpers/file-helper.ts +90 -90
  46. package/src/helpers/http-helper.ts +186 -0
  47. package/src/helpers/input-helper.ts +18 -18
  48. package/src/helpers/list-view-helper.ts +105 -89
  49. package/src/helpers/menu-helper.ts +28 -28
  50. package/src/helpers/message-box-helper.ts +25 -15
  51. package/src/helpers/node-helper.ts +461 -236
  52. package/src/helpers/number-helper.ts +10 -10
  53. package/src/helpers/numeric-property-helper.ts +91 -91
  54. package/src/helpers/object-helper.ts +2 -2
  55. package/src/helpers/pane-helper.ts +28 -20
  56. package/src/helpers/progress-helper.ts +51 -33
  57. package/src/helpers/property-helper.ts +61 -52
  58. package/src/helpers/record-helper.ts +16 -16
  59. package/src/helpers/scene-helper.ts +144 -95
  60. package/src/helpers/script-helper.ts +15 -15
  61. package/src/helpers/skeleton-helper.ts +26 -26
  62. package/src/helpers/splitter-helper.ts +8 -8
  63. package/src/helpers/string-helper.ts +39 -31
  64. package/src/helpers/surface-helper.ts +5 -5
  65. package/src/helpers/undo-helper.ts +8 -7
  66. package/src/helpers/viewport-helper.ts +21 -8
  67. package/src/lib/delayed.ts +38 -38
  68. package/src/lib/dictionary.ts +3 -0
  69. package/src/lib/frame-keys.ts +67 -67
  70. package/src/lib/guid.ts +2 -2
  71. package/src/lib/menu-item.ts +10 -9
  72. package/src/lib/observable.ts +147 -94
  73. package/src/lib/set.ts +50 -25
  74. package/src/lib/settings.ts +112 -104
  75. package/src/lib/tree-node.ts +149 -145
  76. package/src/samples/config.ts +2 -2
  77. package/src/samples/hello-world.dsa.ts +12 -12
  78. package/src/samples/sample-dialog.dsa.ts +51 -51
  79. package/src/samples/sample-dialog.ts +48 -48
  80. package/src/shared/set-keyboard-shortcut.ts +146 -102
  81. package/tsconfig.json +116 -116
  82. package/webpack.config.js +70 -70
@@ -1,68 +1,68 @@
1
- import { find } from '@dsf/helpers/array-helper';
2
-
3
- export class PropertyKey {
4
- index: number
5
- frame: number = 0
6
- time: DzTime
7
- value: number
8
-
9
- toJSON(): Object {
10
- return {
11
- index: this.index,
12
- time: this.time.valueOf(),
13
- frame: this.frame,
14
- value: this.value,
15
- }
16
- }
17
- }
18
-
19
- export class PropertyKeys {
20
- constructor(private _items: PropertyKey[]) {
21
- if (!this._items) this._items = [];
22
- }
23
-
24
- forEach(callback: (key: PropertyKey) => any) {
25
- this._items.forEach(key => {
26
- callback(key);
27
- });
28
- }
29
-
30
- get items(): PropertyKey[] {
31
- return this._items;
32
- }
33
-
34
- get first(): PropertyKey | null {
35
- return this._items[0]
36
- }
37
-
38
- get length(): number {
39
- return this._items.length;
40
- }
41
-
42
- get current(): PropertyKey {
43
- return find(this._items, k => k.time.valueOf() == Scene.getTime().valueOf())
44
- }
45
-
46
- get previous(): PropertyKey {
47
- return find(this._items.sort((a, b) => b.index - a.index), k => k.time.valueOf() < Scene.getTime().valueOf())
48
- }
49
-
50
- get next(): PropertyKey {
51
- return find(this._items, k => k.time.valueOf() > Scene.getTime().valueOf())
52
- }
53
-
54
- /**
55
- * Given the animation frame number or time, return the property key
56
- * @param frameorTime frame number or time
57
- * @returns the property key
58
- */
59
- at(frameorTime: number | DzTime): PropertyKey | null {
60
- return typeof frameorTime === 'number'
61
- ? find(this._items, k => k.frame === frameorTime)
62
- : find(this._items, k => k.time === frameorTime)
63
- }
64
-
65
- any(): boolean {
66
- return this.items.length > 0
67
- }
1
+ import { find } from '@dsf/helpers/array-helper';
2
+
3
+ export class PropertyKey {
4
+ index: number
5
+ frame: number = 0
6
+ time: DzTime
7
+ value: number
8
+
9
+ toJSON(): Object {
10
+ return {
11
+ index: this.index,
12
+ time: this.time.valueOf(),
13
+ frame: this.frame,
14
+ value: this.value,
15
+ }
16
+ }
17
+ }
18
+
19
+ export class PropertyKeys {
20
+ constructor(private _items: PropertyKey[]) {
21
+ if (!this._items) this._items = [];
22
+ }
23
+
24
+ forEach(callback: (key: PropertyKey) => any) {
25
+ this._items.forEach(key => {
26
+ callback(key);
27
+ });
28
+ }
29
+
30
+ get items(): PropertyKey[] {
31
+ return this._items;
32
+ }
33
+
34
+ get first(): PropertyKey | null {
35
+ return this._items[0]
36
+ }
37
+
38
+ get length(): number {
39
+ return this._items.length;
40
+ }
41
+
42
+ get current(): PropertyKey {
43
+ return find(this._items, k => k.time.valueOf() == Scene.getTime().valueOf())
44
+ }
45
+
46
+ get previous(): PropertyKey {
47
+ return find(this._items.sort((a, b) => b.index - a.index), k => k.time.valueOf() < Scene.getTime().valueOf())
48
+ }
49
+
50
+ get next(): PropertyKey {
51
+ return find(this._items, k => k.time.valueOf() > Scene.getTime().valueOf())
52
+ }
53
+
54
+ /**
55
+ * Given the animation frame number or time, return the property key
56
+ * @param frameorTime frame number or time
57
+ * @returns the property key
58
+ */
59
+ at(frameorTime: number | DzTime): PropertyKey | null {
60
+ return typeof frameorTime === 'number'
61
+ ? find(this._items, k => k.frame === frameorTime)
62
+ : find(this._items, k => k.time === frameorTime)
63
+ }
64
+
65
+ any(): boolean {
66
+ return this.items.length > 0
67
+ }
68
68
  }
package/src/lib/guid.ts CHANGED
@@ -1,3 +1,3 @@
1
- export const createUID = (): string => {
2
- return "uuid-" + ((new Date).getTime().toString(16) + Math.floor(1E7 * Math.random()).toString(16));
1
+ export const createUID = (): string => {
2
+ return "uuid-" + ((new Date).getTime().toString(16) + Math.floor(1E7 * Math.random()).toString(16));
3
3
  }
@@ -1,9 +1,10 @@
1
- export type MenuItem = {
2
- description: string
3
- shortcut: string
4
- name: string
5
- label: string
6
- path: string
7
- icon: string
8
- hidden: boolean
9
- }
1
+ export type MenuItem = {
2
+ description: string
3
+ shortcut: string
4
+ name: string
5
+ label: string
6
+ path: string
7
+ filePath?: string
8
+ icon: string
9
+ hidden: boolean
10
+ }
@@ -1,94 +1,147 @@
1
- export class Observable<T> {
2
- protected _value: T;
3
- private _beforeChange: (previous: T, current: T) => T
4
- private _onChange: Array<(value: T) => void> = []
5
- private _afterChange: (previous: T, current: T) => T
6
- private _paused: boolean
7
-
8
- constructor(value?: T, onChange?: (value: T) => void) {
9
- this.value = value;
10
- if (onChange)
11
- this._onChange.push(onChange);
12
- }
13
-
14
- get value(): T {
15
- return this._value;
16
- }
17
-
18
- set value(value: T) {
19
- let previous = this._value
20
- this._value = this._beforeChange?.(this._value, value) ?? value
21
- if (!this._paused) this.trigger()
22
- this._value = this._afterChange?.(previous, this._value) ?? this._value
23
- }
24
-
25
- connect(onChange: (value: T) => void): this {
26
- if (this._onChange.indexOf(onChange) === -1) {
27
- this._onChange.push(onChange)
28
- }
29
- return this
30
- }
31
-
32
- intercept(beforeChange: (previous: T, current: T) => T, afterChange?: (previous: T, current: T) => T): this {
33
- this._beforeChange = beforeChange
34
- this._afterChange = afterChange
35
- return this
36
- }
37
-
38
- disconnect(onChange: (value: T) => void) {
39
- const index = this._onChange.indexOf(onChange);
40
- if (index > -1) {
41
- this._onChange.splice(index, 1);
42
- }
43
- }
44
-
45
- trigger(): void {
46
- if (!this._paused)
47
- this._onChange.forEach(callback => callback(this._value));
48
- }
49
-
50
- pause(callback?: () => void): void {
51
- this._paused = true
52
- callback?.()
53
- this.resume()
54
- }
55
-
56
- resume(): void {
57
- this._paused = false
58
- }
59
-
60
- toJSON() {
61
- return this._value;
62
- }
63
- }
64
-
65
- export class BooleanObservable extends Observable<boolean> {
66
- private combined: BooleanObservable[] = []
67
-
68
- combine(...observables: BooleanObservable[]): this {
69
- observables.forEach((obs) => {
70
- this.combined.push(obs)
71
- obs.connect(_ => {
72
- this._value = this.combined.every(b => b.value)
73
- })
74
- })
75
- return this
76
- }
77
- }
78
-
79
-
80
- // export class ObservableNumber extends Observable<number> {
81
- // setMax(max: number): this {
82
- // this.connect((value) => {
83
- // if (value > max) value = max
84
- // })
85
- // return this
86
- // }
87
-
88
- // setMin(min: number): this {
89
- // this.connect((value) => {
90
- // if (value < min) value = min
91
- // })
92
- // return this
93
- // }
94
- // }
1
+ export class Observable<T> {
2
+ protected _value: T;
3
+ private _beforeChange?: (previous: T, current: T) => T;
4
+ private _afterChange?: (previous: T, current: T) => T;
5
+ private _onChange: Array<(value: T) => void> = [];
6
+ private _paused = false;
7
+
8
+ // NEW: guards + comparator
9
+ private _isSetting = false;
10
+ private _pendingValue?: T; // last requested value during an active set
11
+ private _equals: (a: T, b: T) => boolean;
12
+ private static readonly MAX_AFTER_CHANGE_DEPTH = 10;
13
+ private static readonly MAX_CHAINED_SETS = 100; // limit for cascading listener-driven sets
14
+
15
+ constructor(value?: T, onChange?: (value: T) => void, equals?: (a: T, b: T) => boolean) {
16
+ this._value = value as T;
17
+ if (onChange) this._onChange.push(onChange);
18
+ this._equals = equals ?? ((a, b) => a === b);
19
+ }
20
+
21
+ get value(): T { return this._value; }
22
+
23
+ set value(next: T) {
24
+ // Coalesce: if actively setting, just remember the latest requested value.
25
+ if (this._isSetting) { this._pendingValue = next; return; }
26
+
27
+ let currentRequested: T | undefined = next;
28
+ let chainedSets = 0;
29
+ let afterDepth = 0;
30
+
31
+ while (currentRequested !== undefined) {
32
+ const prev = this._value;
33
+ let candidate = this._beforeChange?.(prev, currentRequested) ?? currentRequested;
34
+ currentRequested = undefined; // consume
35
+
36
+ if (this._equals(prev, candidate)) {
37
+ // No actual change; ignore any pending identical value.
38
+ this._pendingValue = undefined;
39
+ break;
40
+ }
41
+
42
+ this._isSetting = true;
43
+ this._value = candidate;
44
+ if (!this._paused) this._onChange.slice().forEach(cb => cb(this._value));
45
+
46
+ // Apply afterChange transformations (bounded)
47
+ let transformed = this._afterChange?.(prev, this._value);
48
+ while (transformed !== undefined && !this._equals(this._value, transformed)) {
49
+ afterDepth++;
50
+ if (afterDepth > Observable.MAX_AFTER_CHANGE_DEPTH) {
51
+ this._isSetting = false;
52
+ this._pendingValue = undefined;
53
+ throw new Error(`Observable: _afterChange exceeded depth ${Observable.MAX_AFTER_CHANGE_DEPTH}. Possible loop.`);
54
+ }
55
+ this._value = transformed;
56
+ if (!this._paused) this._onChange.slice().forEach(cb => cb(this._value));
57
+ transformed = this._afterChange?.(prev, this._value);
58
+ }
59
+
60
+ this._isSetting = false;
61
+
62
+ // If a listener requested a new value during this cycle, process it
63
+ if (this._pendingValue !== undefined && !this._equals(this._value, this._pendingValue)) {
64
+ currentRequested = this._pendingValue;
65
+ this._pendingValue = undefined;
66
+ chainedSets++;
67
+ if (chainedSets > Observable.MAX_CHAINED_SETS) {
68
+ throw new Error(`Observable: Too many chained set operations (>${Observable.MAX_CHAINED_SETS}). Possible loop.`);
69
+ }
70
+ } else {
71
+ // Either no pending or it's same-value;
72
+ this._pendingValue = undefined;
73
+ }
74
+ }
75
+ }
76
+
77
+ connect(onChange: (value: T) => void): this {
78
+ if (this._onChange.indexOf(onChange) === -1) this._onChange.push(onChange);
79
+ return this;
80
+ }
81
+
82
+ intercept(
83
+ beforeChange: (previous: T, current: T) => T,
84
+ afterChange?: (previous: T, current: T) => T
85
+ ): this {
86
+ this._beforeChange = beforeChange;
87
+ this._afterChange = afterChange;
88
+ return this;
89
+ }
90
+
91
+ disconnect(onChange: (value: T) => void) {
92
+ const i = this._onChange.indexOf(onChange);
93
+ if (i > -1) this._onChange.splice(i, 1);
94
+ }
95
+
96
+ trigger(): void {
97
+ if (!this._paused) this._onChange.slice().forEach(cb => cb(this._value));
98
+ }
99
+
100
+ pause(callback?: () => void): void {
101
+ this._paused = true;
102
+ callback?.();
103
+ this.resume();
104
+ }
105
+ resume(): void { this._paused = false; }
106
+
107
+ // Optional: silent set (no callbacks) for derived/computed cases
108
+ setSilently(next: T): void { this._value = next; }
109
+
110
+ toJSON() { return this._value; }
111
+ }
112
+
113
+ export class BooleanObservable extends Observable<boolean> {
114
+ private combined: BooleanObservable[] = [];
115
+ private _isUpdatingFromCombined = false;
116
+
117
+ combine(...observables: BooleanObservable[]): this {
118
+ observables.forEach(obs => {
119
+ // Prevent circular references
120
+ if (obs === this) {
121
+ throw new Error('BooleanObservable: Cannot combine with itself');
122
+ }
123
+
124
+ this.combined.push(obs);
125
+ obs.connect(() => {
126
+ // Prevent circular updates
127
+ if (this._isUpdatingFromCombined) return;
128
+
129
+ this._isUpdatingFromCombined = true;
130
+ try {
131
+ this.value = this.combined.every(b => b.value);
132
+ } finally {
133
+ this._isUpdatingFromCombined = false;
134
+ }
135
+ });
136
+ });
137
+ // initialize once
138
+ this._isUpdatingFromCombined = true;
139
+ try {
140
+ this.value = this.combined.every(b => b.value);
141
+ } finally {
142
+ this._isUpdatingFromCombined = false;
143
+ }
144
+ return this;
145
+ }
146
+ }
147
+
package/src/lib/set.ts CHANGED
@@ -1,25 +1,50 @@
1
- export default class CustomSet<T> {
2
- private items: Record<string, T> = {};
3
-
4
- add(item: T): void {
5
- const key = this.getKey(item);
6
- this.items[key] = item;
7
- }
8
-
9
- has(item: T): boolean {
10
- const key = this.getKey(item);
11
- return key in this.items;
12
- }
13
-
14
- private getKey(item: T): string {
15
- if (typeof item === 'object') {
16
- // For object items, use a unique identifier (e.g., JSON string) as the key
17
- return JSON.stringify(item);
18
- }
19
- return String(item);
20
- }
21
-
22
- values(): T[] {
23
- return Object.values(this.items);
24
- }
25
- }
1
+ export default class CustomSet<T> {
2
+ private items: Record<string, T> = {};
3
+
4
+ add(item: T): void {
5
+ const key = this.getKey(item);
6
+ this.items[key] = item;
7
+ }
8
+
9
+ has(item: T): boolean {
10
+ const key = this.getKey(item);
11
+ return key in this.items;
12
+ }
13
+
14
+ remove(item: T): void {
15
+ const key = this.getKey(item);
16
+ delete this.items[key];
17
+ }
18
+
19
+ clear(): void {
20
+ this.items = {};
21
+ }
22
+
23
+ forEach(callback: (item: T) => void): void {
24
+ for (const key in this.items) {
25
+ if (this.items.hasOwnProperty(key)) {
26
+ callback(this.items[key]);
27
+ }
28
+ }
29
+ }
30
+
31
+ private getKey(item: T): string {
32
+ if (typeof item === 'object') {
33
+ // For object items, use a unique identifier (e.g., JSON string) as the key
34
+ return JSON.stringify(item);
35
+ }
36
+ return String(item);
37
+ }
38
+
39
+ values(): T[] {
40
+ let values: T[] = [];
41
+
42
+ for (const key in this.items) {
43
+ if (this.items.hasOwnProperty(key)) {
44
+ values.push(this.items[key]);
45
+ }
46
+ }
47
+
48
+ return values;
49
+ }
50
+ }