dazscript-framework 0.2.3 → 0.2.4
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 +29 -32
- package/dist/scripts/install-generator.js +180 -83
- package/package.json +1 -1
- package/src/core/action-decorator.ts +1 -16
- package/src/core/action.ts +71 -0
- package/src/samples/hello-world.dsa.ts +5 -10
- package/src/samples/sample-dialog.dsa.ts +41 -46
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DazScript Framework
|
|
2
2
|
|
|
3
|
-
> ⚠️
|
|
3
|
+
> ⚠️ This framework is under active development. The API may still evolve between releases. If you need a stable long-term surface, wait for `v1.0`.
|
|
4
4
|
|
|
5
5
|
The **DazScript Framework** is a TypeScript-based framework for writing Daz Studio scripts. It provides all the advantages of a typed language such as autocompletion, error checking, and method parameter documentation and hinting. The framework also includes a set of dialog helpers for rapid UI development.
|
|
6
6
|
|
|
@@ -46,7 +46,7 @@ You can customize the generated defaults:
|
|
|
46
46
|
npx dazscript init --menu-path /MyScripts --scripts-path ./src --out-dir ./out
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
- `--menu-path` sets which Daz Studio menu the scripts are added to by default. See [The
|
|
49
|
+
- `--menu-path` sets which Daz Studio menu the scripts are added to by default. See [The `action(...)` Entrypoint](#the-action-entrypoint) for how a script can override that with `menuPath`.
|
|
50
50
|
- `--scripts-path` tells the installer generator where to scan for runnable `.dsa.ts` entry files.
|
|
51
51
|
- `--out-dir` sets the webpack build output directory for generated `.dsa` files and copied icons.
|
|
52
52
|
|
|
@@ -60,42 +60,45 @@ Create a simple script that logs to the console:
|
|
|
60
60
|
|
|
61
61
|
```typescript
|
|
62
62
|
import { debug } from '@dsf/common/log';
|
|
63
|
-
import { action } from '@dsf/core/action
|
|
64
|
-
import { BaseScript } from '@dsf/core/base-script';
|
|
63
|
+
import { action } from '@dsf/core/action';
|
|
65
64
|
import { info } from '@dsf/helpers/message-box-helper';
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
info('Hello World!');
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
new HelloWorldScript().exec();
|
|
66
|
+
action({ text: 'Hello World' }, () => {
|
|
67
|
+
debug('Hello World!');
|
|
68
|
+
info('Hello World!');
|
|
69
|
+
});
|
|
76
70
|
```
|
|
77
71
|
|
|
78
|
-
### The
|
|
72
|
+
### The `action(...)` Entrypoint
|
|
79
73
|
|
|
80
|
-
Use
|
|
74
|
+
Use `action(...)` at module scope to define how a runnable `.dsa.ts` file should appear in Daz Studio and what it should execute.
|
|
81
75
|
|
|
82
76
|
```typescript
|
|
83
|
-
|
|
77
|
+
action({
|
|
84
78
|
text: 'Hello World',
|
|
85
79
|
menuPath: '#{defaultMenuPath}/Examples',
|
|
86
80
|
shortcut: 'CTRL+SHIFT+H',
|
|
87
81
|
toolbar: 'MyToolbar',
|
|
88
82
|
group: 'Examples',
|
|
89
83
|
description: 'Runs the Hello World script',
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
}, () => {
|
|
85
|
+
info('Hello World!');
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`action(...)` also accepts a reusable class with a `run()` method:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
class HelloWorldScript {
|
|
93
|
+
run(): void {
|
|
93
94
|
info('Hello World!');
|
|
94
95
|
}
|
|
95
96
|
}
|
|
97
|
+
|
|
98
|
+
action({ text: 'Hello World' }, HelloWorldScript);
|
|
96
99
|
```
|
|
97
100
|
|
|
98
|
-
Common
|
|
101
|
+
Common `action(...)` parameters:
|
|
99
102
|
|
|
100
103
|
- `text`: the label shown for the script in Daz Studio.
|
|
101
104
|
- `menuPath`: the menu path where the script should be added. Set it to `false` to skip adding the script to a menu. If omitted, the default menu from `--menu-path` is used.
|
|
@@ -153,14 +156,11 @@ export class MyDialog extends BasicDialog {
|
|
|
153
156
|
#### 3. Connect & Use in Your Script
|
|
154
157
|
|
|
155
158
|
```typescript
|
|
156
|
-
import { action } from '@dsf/core/action
|
|
157
|
-
import { BaseScript } from '@dsf/core/base-script';
|
|
159
|
+
import { action } from '@dsf/core/action';
|
|
158
160
|
import { getSelectedNode } from '@dsf/helpers/scene-helper';
|
|
159
161
|
import { MyDialog, MyDialogModel } from './my-dialog';
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
class MyDialogScript extends BaseScript {
|
|
163
|
-
protected run(): void {
|
|
163
|
+
action({ text: 'My Dialog Script' }, () => {
|
|
164
164
|
const model = new MyDialogModel();
|
|
165
165
|
const selectedNode = getSelectedNode();
|
|
166
166
|
|
|
@@ -185,10 +185,7 @@ class MyDialogScript extends BaseScript {
|
|
|
185
185
|
} else {
|
|
186
186
|
console.log('Dialog cancelled');
|
|
187
187
|
}
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
new MyDialogScript().exec();
|
|
188
|
+
});
|
|
192
189
|
```
|
|
193
190
|
|
|
194
191
|
### Core Concepts
|
|
@@ -325,15 +322,15 @@ This project uses **semantic-release** for automatic versioning and npm publishi
|
|
|
325
322
|
|
|
326
323
|
Use conventional commit messages to control version bumping:
|
|
327
324
|
|
|
328
|
-
- **`fix: description`** → Patch version bump (
|
|
325
|
+
- **`fix: description`** → Patch version bump (`x.y.z` → `x.y.(z+1)`)
|
|
329
326
|
- Bug fixes, patches, or minor improvements
|
|
330
327
|
- Example: `fix: resolve dialog builder layout issue`
|
|
331
328
|
|
|
332
|
-
- **`feat: description`** → Minor version bump (
|
|
329
|
+
- **`feat: description`** → Minor version bump (`x.y.z` → `x.(y+1).0`)
|
|
333
330
|
- New features or significant enhancements
|
|
334
331
|
- Example: `feat: add tree view builder component`
|
|
335
332
|
|
|
336
|
-
- **`BREAKING CHANGE: description`** → Major version bump (
|
|
333
|
+
- **`BREAKING CHANGE: description`** → Major version bump (`x.y.z` → `(x+1).0.0`)
|
|
337
334
|
- Add to commit body for breaking changes
|
|
338
335
|
- Example: `feat: refactor action decorator API\n\nBREAKING CHANGE: action() now requires explicit menu path`
|
|
339
336
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const ts = require('typescript');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const glob = require('glob');
|
|
5
5
|
|
|
6
|
-
const
|
|
6
|
+
const nameofActionFunction = 'action';
|
|
7
7
|
|
|
8
8
|
function getPartialPath(filePath) {
|
|
9
9
|
const fileInfo = path.parse(filePath);
|
|
@@ -35,95 +35,192 @@ uninstall(${data});
|
|
|
35
35
|
`;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
function literalValue(node) {
|
|
39
|
+
if (!node) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
44
|
+
return node.text;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (node.kind === ts.SyntaxKind.TrueKeyword) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (node.kind === ts.SyntaxKind.FalseKeyword) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (ts.isNumericLiteral(node)) {
|
|
56
|
+
return Number(node.text);
|
|
57
|
+
}
|
|
47
58
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const script = {
|
|
53
|
-
name: null,
|
|
54
|
-
text: fileInfo.name.replace('.dsa', ''),
|
|
55
|
-
filePath:
|
|
56
|
-
decorator.bundle === undefined
|
|
57
|
-
? getPartialPath(filePath)
|
|
58
|
-
: fileInfo.name.replace('.ts', ''),
|
|
59
|
-
menuPath: (() => {
|
|
60
|
-
const relativeDir = path.parse(getPartialPath(filePath)).dir;
|
|
61
|
-
return relativeDir && relativeDir !== '.'
|
|
62
|
-
? `${defaultMenuPath}${relativeDir}`
|
|
63
|
-
: defaultMenuPath.replace(/\/$/, '');
|
|
64
|
-
})(),
|
|
65
|
-
description: fileInfo.name.replace('.dsa', ''),
|
|
66
|
-
group: stringOrDefault(decorator.group, undefined),
|
|
67
|
-
shortcut: stringOrDefault(decorator.shortcut),
|
|
68
|
-
toolbar: stringOrDefault(decorator.toolbar, undefined),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const icon = filePath.replace('.ts', '.png');
|
|
72
|
-
if (fs.existsSync(icon)) {
|
|
73
|
-
script.icon =
|
|
74
|
-
decorator.bundle === undefined
|
|
75
|
-
? `${getPartialPath(filePath)}.png`
|
|
76
|
-
: fileInfo.name.replace('.dsa', '.dsa.png');
|
|
59
|
+
if (ts.isPrefixUnaryExpression(node) && ts.isNumericLiteral(node.operand)) {
|
|
60
|
+
if (node.operator === ts.SyntaxKind.MinusToken) {
|
|
61
|
+
return -Number(node.operand.text);
|
|
77
62
|
}
|
|
78
63
|
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
if (typeof decorator.menuPath === 'boolean') {
|
|
82
|
-
script.menuPath = decorator.menuPath === true ? script.menuPath : '';
|
|
83
|
-
} else {
|
|
84
|
-
script.menuPath = stringOrDefault(decorator.menuPath, script.menuPath);
|
|
85
|
-
}
|
|
86
|
-
script.menuPath = script.menuPath.replace(
|
|
87
|
-
'#{defaultMenuPath}',
|
|
88
|
-
defaultMenuPath
|
|
89
|
-
);
|
|
90
|
-
script.shortcut = decorator.shortcut;
|
|
64
|
+
if (node.operator === ts.SyntaxKind.PlusToken) {
|
|
65
|
+
return Number(node.operand.text);
|
|
91
66
|
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function objectLiteralToObject(node) {
|
|
73
|
+
if (!node || !ts.isObjectLiteralExpression(node)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const result = {};
|
|
92
78
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
let bundleScriptFilePath = path.join(
|
|
112
|
-
path.parse(filePath).dir,
|
|
113
|
-
packageInstallerFilePath
|
|
114
|
-
);
|
|
115
|
-
fs.writeFileSync(bundleScriptFilePath, bundleScriptContent);
|
|
116
|
-
|
|
117
|
-
bundleScriptContent = generateUninstallerTemplate(
|
|
118
|
-
JSON.stringify(container.scripts, null, 4)
|
|
119
|
-
);
|
|
120
|
-
bundleScriptFilePath = path.join(
|
|
121
|
-
path.parse(filePath).dir,
|
|
122
|
-
packageUninstallerFilePath
|
|
123
|
-
);
|
|
124
|
-
fs.writeFileSync(bundleScriptFilePath, bundleScriptContent);
|
|
79
|
+
node.properties.forEach((property) => {
|
|
80
|
+
if (!ts.isPropertyAssignment(property)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const name = ts.isIdentifier(property.name)
|
|
85
|
+
? property.name.text
|
|
86
|
+
: ts.isStringLiteral(property.name)
|
|
87
|
+
? property.name.text
|
|
88
|
+
: null;
|
|
89
|
+
|
|
90
|
+
if (!name) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const value = literalValue(property.initializer);
|
|
95
|
+
if (value !== undefined) {
|
|
96
|
+
result[name] = value;
|
|
125
97
|
}
|
|
126
98
|
});
|
|
99
|
+
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getCallName(expression) {
|
|
104
|
+
if (ts.isIdentifier(expression)) {
|
|
105
|
+
return expression.text;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (ts.isPropertyAccessExpression(expression)) {
|
|
109
|
+
return expression.name.text;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function findTopLevelActionCall(content, filePath) {
|
|
116
|
+
const sourceFile = ts.createSourceFile(
|
|
117
|
+
filePath,
|
|
118
|
+
content,
|
|
119
|
+
ts.ScriptTarget.Latest,
|
|
120
|
+
true,
|
|
121
|
+
ts.ScriptKind.TS
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
for (const statement of sourceFile.statements) {
|
|
125
|
+
if (!ts.isExpressionStatement(statement)) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const expression = statement.expression;
|
|
130
|
+
if (!ts.isCallExpression(expression)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (getCallName(expression.expression) !== nameofActionFunction) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return expression;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function processScript(filePath, container, defaultMenuPath) {
|
|
145
|
+
const fileInfo = path.parse(filePath);
|
|
146
|
+
const content = fs.readFileSync(filePath, 'utf-8').toString();
|
|
147
|
+
const actionCall = findTopLevelActionCall(content, filePath);
|
|
148
|
+
|
|
149
|
+
if (!actionCall) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const decorator = objectLiteralToObject(actionCall.arguments[0]) ?? {};
|
|
154
|
+
|
|
155
|
+
const script = {
|
|
156
|
+
name: null,
|
|
157
|
+
text: fileInfo.name.replace('.dsa', ''),
|
|
158
|
+
filePath:
|
|
159
|
+
decorator.bundle === undefined
|
|
160
|
+
? getPartialPath(filePath)
|
|
161
|
+
: fileInfo.name.replace('.ts', ''),
|
|
162
|
+
menuPath: (() => {
|
|
163
|
+
const relativeDir = path.parse(getPartialPath(filePath)).dir;
|
|
164
|
+
return relativeDir && relativeDir !== '.'
|
|
165
|
+
? `${defaultMenuPath}${relativeDir}`
|
|
166
|
+
: defaultMenuPath.replace(/\/$/, '');
|
|
167
|
+
})(),
|
|
168
|
+
description: fileInfo.name.replace('.dsa', ''),
|
|
169
|
+
group: stringOrDefault(decorator.group, undefined),
|
|
170
|
+
shortcut: stringOrDefault(decorator.shortcut),
|
|
171
|
+
toolbar: stringOrDefault(decorator.toolbar, undefined),
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const icon = filePath.replace('.ts', '.png');
|
|
175
|
+
if (fs.existsSync(icon)) {
|
|
176
|
+
script.icon =
|
|
177
|
+
decorator.bundle === undefined
|
|
178
|
+
? `${getPartialPath(filePath)}.png`
|
|
179
|
+
: fileInfo.name.replace('.dsa', '.dsa.png');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
script.text = stringOrDefault(decorator.text, script.text);
|
|
183
|
+
if (typeof decorator.menuPath === 'boolean') {
|
|
184
|
+
script.menuPath = decorator.menuPath === true ? script.menuPath : '';
|
|
185
|
+
} else {
|
|
186
|
+
script.menuPath = stringOrDefault(decorator.menuPath, script.menuPath);
|
|
187
|
+
}
|
|
188
|
+
script.menuPath = script.menuPath.replace(
|
|
189
|
+
'#{defaultMenuPath}',
|
|
190
|
+
defaultMenuPath
|
|
191
|
+
);
|
|
192
|
+
script.shortcut = decorator.shortcut;
|
|
193
|
+
|
|
194
|
+
console.log(`Adding script: ${script.text}`, script);
|
|
195
|
+
container.scripts.push(script);
|
|
196
|
+
|
|
197
|
+
if (decorator.bundle !== undefined) {
|
|
198
|
+
let packageInstallerFilePath = `Install.dsa.ts`;
|
|
199
|
+
let packageUninstallerFilePath = `Uninstall.dsa.ts`;
|
|
200
|
+
|
|
201
|
+
if (decorator.bundle !== true) {
|
|
202
|
+
packageInstallerFilePath = `Install ${decorator.bundle}.dsa.ts`;
|
|
203
|
+
packageUninstallerFilePath = `Uninstall ${decorator.bundle}.dsa.ts`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let bundleScriptContent = generateInstallerTemplate(
|
|
207
|
+
JSON.stringify(container.scripts, null, 4)
|
|
208
|
+
);
|
|
209
|
+
let bundleScriptFilePath = path.join(
|
|
210
|
+
path.parse(filePath).dir,
|
|
211
|
+
packageInstallerFilePath
|
|
212
|
+
);
|
|
213
|
+
fs.writeFileSync(bundleScriptFilePath, bundleScriptContent);
|
|
214
|
+
|
|
215
|
+
bundleScriptContent = generateUninstallerTemplate(
|
|
216
|
+
JSON.stringify(container.scripts, null, 4)
|
|
217
|
+
);
|
|
218
|
+
bundleScriptFilePath = path.join(
|
|
219
|
+
path.parse(filePath).dir,
|
|
220
|
+
packageUninstallerFilePath
|
|
221
|
+
);
|
|
222
|
+
fs.writeFileSync(bundleScriptFilePath, bundleScriptContent);
|
|
223
|
+
}
|
|
127
224
|
}
|
|
128
225
|
|
|
129
226
|
function processScripts(paths, container, defaultMenuPath) {
|
package/package.json
CHANGED
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
text?: string
|
|
3
|
-
description?: string
|
|
4
|
-
icon?: string
|
|
5
|
-
menuPath?: string | boolean
|
|
6
|
-
toolbar?: string
|
|
7
|
-
sort?: number
|
|
8
|
-
group?: string
|
|
9
|
-
shortcut?: string
|
|
10
|
-
bundle?: string | boolean
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const action = (action?: CustomActionDefinition) => {
|
|
14
|
-
return (target: Function) => {
|
|
15
|
-
}
|
|
16
|
-
}
|
|
1
|
+
export { ActionDefinition, action } from './action';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { debug, error, raise } from '@dsf/common/log';
|
|
2
|
+
|
|
3
|
+
export class ActionDefinition {
|
|
4
|
+
text?: string
|
|
5
|
+
description?: string
|
|
6
|
+
icon?: string
|
|
7
|
+
menuPath?: string | boolean
|
|
8
|
+
toolbar?: string
|
|
9
|
+
sort?: number
|
|
10
|
+
group?: string
|
|
11
|
+
shortcut?: string
|
|
12
|
+
bundle?: string | boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ActionCallback = () => void
|
|
16
|
+
type ActionRunnable = { [key: string]: unknown }
|
|
17
|
+
type ActionConstructor = new (...args: any[]) => any
|
|
18
|
+
type ActionTarget = ActionCallback | ActionRunnable | ActionConstructor
|
|
19
|
+
|
|
20
|
+
const isFunction = (value: unknown): value is Function => typeof value === 'function'
|
|
21
|
+
|
|
22
|
+
const isConstructorTarget = (target: ActionTarget): target is ActionConstructor => {
|
|
23
|
+
if (!isFunction(target)) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const prototype = (target as ActionConstructor).prototype as ActionRunnable | undefined
|
|
28
|
+
return !!prototype && (typeof prototype.run === 'function' || typeof prototype.exec === 'function')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const invokeRunnable = (target: ActionRunnable) => {
|
|
32
|
+
if (typeof target.run === 'function') {
|
|
33
|
+
target.run()
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (typeof target.exec === 'function') {
|
|
38
|
+
target.exec()
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new Error('Action target must expose run() or exec().')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function action(definition: ActionDefinition, target: ActionTarget): void {
|
|
46
|
+
const scriptName = definition?.text || 'Unnamed Script'
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const runnable = isConstructorTarget(target)
|
|
50
|
+
? new target()
|
|
51
|
+
: target
|
|
52
|
+
|
|
53
|
+
const announceExecution = !isFunction(runnable) && runnable.anounceExecution === false
|
|
54
|
+
? false
|
|
55
|
+
: true
|
|
56
|
+
|
|
57
|
+
if (announceExecution) {
|
|
58
|
+
debug(`=== Running script "${scriptName}" ===`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isFunction(runnable)) {
|
|
62
|
+
runnable()
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
invokeRunnable(runnable)
|
|
67
|
+
} catch (err) {
|
|
68
|
+
error(`There was an error while running the script "${scriptName}"`)
|
|
69
|
+
raise(err)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { debug } from '@dsf/common/log';
|
|
2
|
-
import { action } from '@dsf/core/action
|
|
3
|
-
import { BaseScript } from '@dsf/core/base-script';
|
|
2
|
+
import { action } from '@dsf/core/action';
|
|
4
3
|
import { info } from '@dsf/helpers/message-box-helper';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
info('Hello World!');
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
new HelloWorldScript().exec();
|
|
5
|
+
action({ text: 'Hello World' }, () => {
|
|
6
|
+
debug('Hello World!');
|
|
7
|
+
info('Hello World!');
|
|
8
|
+
})
|
|
@@ -1,52 +1,47 @@
|
|
|
1
1
|
import { debug, dump } from '@dsf/common/log';
|
|
2
|
-
import { action } from '@dsf/core/action
|
|
3
|
-
import { BaseScript } from '@dsf/core/base-script';
|
|
2
|
+
import { action } from '@dsf/core/action';
|
|
4
3
|
import { error } from '@dsf/helpers/message-box-helper';
|
|
5
4
|
import { getNodes, getSelectedNode } from '@dsf/helpers/scene-helper';
|
|
6
5
|
import { SampleDialog, SampleDialogModel } from './sample-dialog';
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
error('Please select a node.')
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let model = new SampleDialogModel()
|
|
19
|
-
model.nodes$.value = sceneNodes
|
|
20
|
-
|
|
21
|
-
model.nodeLabel$.connect((label) => {
|
|
22
|
-
if (label === model.selectedNode$.value.getLabel()) return
|
|
23
|
-
model.selectedNode$.value.setLabel(label)
|
|
24
|
-
model.nodes$.value = getNodes()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
let dialog = new SampleDialog(model)
|
|
28
|
-
|
|
29
|
-
model.selectedNode$.connect((node) => {
|
|
30
|
-
if (!node) return
|
|
31
|
-
debug(`Selected Node: ${node.getLabel()}`)
|
|
32
|
-
node.select(true)
|
|
33
|
-
model.nodeLabel$.value = node.getLabel()
|
|
34
|
-
model.showNode$.value = node.isVisible()
|
|
35
|
-
model.hideNode$.value = !node.isVisible()
|
|
36
|
-
})
|
|
37
|
-
dialog.onNodeVisibilityChanged = (node, visible) => {
|
|
38
|
-
node.setVisible(visible)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
model.selectedNode$.value = selectedNode
|
|
42
|
-
|
|
43
|
-
if (!dialog.run()) {
|
|
44
|
-
debug(`Dialog Cancelled`)
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
debug(`Dialog Closed`)
|
|
49
|
-
dump(model)
|
|
7
|
+
action({ text: 'Sample Dialog' }, () => {
|
|
8
|
+
let sceneNodes = getNodes()
|
|
9
|
+
let selectedNode = getSelectedNode()
|
|
10
|
+
if (!selectedNode) {
|
|
11
|
+
error('Please select a node.')
|
|
12
|
+
return
|
|
50
13
|
}
|
|
51
|
-
|
|
52
|
-
new
|
|
14
|
+
|
|
15
|
+
let model = new SampleDialogModel()
|
|
16
|
+
model.nodes$.value = sceneNodes
|
|
17
|
+
|
|
18
|
+
model.nodeLabel$.connect((label) => {
|
|
19
|
+
if (label === model.selectedNode$.value.getLabel()) return
|
|
20
|
+
model.selectedNode$.value.setLabel(label)
|
|
21
|
+
model.nodes$.value = getNodes()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
let dialog = new SampleDialog(model)
|
|
25
|
+
|
|
26
|
+
model.selectedNode$.connect((node) => {
|
|
27
|
+
if (!node) return
|
|
28
|
+
debug(`Selected Node: ${node.getLabel()}`)
|
|
29
|
+
node.select(true)
|
|
30
|
+
model.nodeLabel$.value = node.getLabel()
|
|
31
|
+
model.showNode$.value = node.isVisible()
|
|
32
|
+
model.hideNode$.value = !node.isVisible()
|
|
33
|
+
})
|
|
34
|
+
dialog.onNodeVisibilityChanged = (node, visible) => {
|
|
35
|
+
node.setVisible(visible)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
model.selectedNode$.value = selectedNode
|
|
39
|
+
|
|
40
|
+
if (!dialog.run()) {
|
|
41
|
+
debug(`Dialog Cancelled`)
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
debug(`Dialog Closed`)
|
|
46
|
+
dump(model)
|
|
47
|
+
})
|