davinci-resolve-mcp 2.33.0 → 2.33.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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/docs/SKILL.md +8 -2
- package/docs/authoring/setting-files/README.md +152 -0
- package/docs/authoring/setting-files/references/category-patterns.md +780 -0
- package/docs/authoring/setting-files/references/controls.md +259 -0
- package/docs/authoring/setting-files/references/format.md +568 -0
- package/docs/authoring/setting-files/references/gotchas.md +168 -0
- package/docs/authoring/setting-files/references/thumbnails.md +106 -0
- package/install.py +1 -1
- package/package.json +1 -1
- package/src/granular/common.py +1 -1
- package/src/server.py +67 -3
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
# Category Patterns
|
|
2
|
+
|
|
3
|
+
Every category hooks into Resolve slightly differently. This file shows the **minimum viable skeleton** for each, and what changes between them. Start with the shape that matches your target category, then modify.
|
|
4
|
+
|
|
5
|
+
## 1. Edit Effect (clip filter)
|
|
6
|
+
|
|
7
|
+
**Role:** pixel filter applied to a single clip. Reads the clip, writes a processed version.
|
|
8
|
+
|
|
9
|
+
**Hook:** exactly one `MainInput1` connected to the internal "entry" node's `Input` parameter.
|
|
10
|
+
|
|
11
|
+
```lua
|
|
12
|
+
{
|
|
13
|
+
Tools = ordered() {
|
|
14
|
+
MyEffect = GroupOperator {
|
|
15
|
+
Inputs = ordered() {
|
|
16
|
+
MainInput1 = InstanceInput {
|
|
17
|
+
SourceOp = "Blur1",
|
|
18
|
+
Source = "Input",
|
|
19
|
+
},
|
|
20
|
+
Strength = InstanceInput {
|
|
21
|
+
SourceOp = "Blur1",
|
|
22
|
+
Source = "XBlurSize",
|
|
23
|
+
Default = 5,
|
|
24
|
+
MinScale = 0,
|
|
25
|
+
MaxScale = 100,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
Outputs = {
|
|
29
|
+
MainOutput1 = InstanceOutput {
|
|
30
|
+
SourceOp = "Blur1",
|
|
31
|
+
Source = "Output",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
Tools = ordered() {
|
|
35
|
+
Blur1 = Blur {
|
|
36
|
+
Inputs = {
|
|
37
|
+
Filter = Input { Value = FuID { "Fast Gaussian" } },
|
|
38
|
+
XBlurSize = Input { Value = 5 },
|
|
39
|
+
LockXY = Input { Value = 1 },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
ActiveTool = "MyEffect",
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Install path:** `Templates/Edit/Effects/`.
|
|
50
|
+
|
|
51
|
+
## 2. Edit Transition
|
|
52
|
+
|
|
53
|
+
**Role:** blends between two clips over a duration.
|
|
54
|
+
|
|
55
|
+
**Hook:** two MainInputs — `MainInput1` (Background, the outgoing clip) and `MainInput2` (Foreground, the incoming clip). Both feed a `Dissolve` or `Merge` node.
|
|
56
|
+
|
|
57
|
+
**Progress animation:** driven by a `LUTLookup` reading `FuID { "Duration" }` with an easing curve. Fusion automatically evaluates the curve across the transition length and outputs a 0→1 ramp.
|
|
58
|
+
|
|
59
|
+
```lua
|
|
60
|
+
{
|
|
61
|
+
Tools = ordered() {
|
|
62
|
+
MyTransition = GroupOperator {
|
|
63
|
+
Inputs = ordered() {
|
|
64
|
+
MainInput1 = InstanceInput {
|
|
65
|
+
SourceOp = "Dissolve1",
|
|
66
|
+
Source = "Background",
|
|
67
|
+
},
|
|
68
|
+
MainInput2 = InstanceInput {
|
|
69
|
+
SourceOp = "Dissolve1",
|
|
70
|
+
Source = "Foreground",
|
|
71
|
+
},
|
|
72
|
+
Softness = InstanceInput {
|
|
73
|
+
SourceOp = "Dissolve1",
|
|
74
|
+
Source = "DFTLumaRamp.Softness",
|
|
75
|
+
Default = 0.05,
|
|
76
|
+
MinScale = 0,
|
|
77
|
+
MaxScale = 1,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
Outputs = {
|
|
81
|
+
MainOutput1 = InstanceOutput {
|
|
82
|
+
SourceOp = "Dissolve1",
|
|
83
|
+
Source = "Output",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
Tools = ordered() {
|
|
87
|
+
Dissolve1 = Dissolve {
|
|
88
|
+
Inputs = {
|
|
89
|
+
Operation = Input { Value = FuID { "DFTDissolve" } },
|
|
90
|
+
Mix = Input {
|
|
91
|
+
SourceOp = "ProgressCurve",
|
|
92
|
+
Source = "Value",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
ProgressCurve = LUTLookup {
|
|
97
|
+
Inputs = {
|
|
98
|
+
Source = Input { Value = FuID { "Duration" } },
|
|
99
|
+
Curve = Input { Value = FuID { "Easing" } },
|
|
100
|
+
EaseIn = Input { Value = FuID { "Cubic" } },
|
|
101
|
+
EaseOut = Input { Value = FuID { "Cubic" } },
|
|
102
|
+
Lookup = Input {
|
|
103
|
+
SourceOp = "ProgressCurveLookup",
|
|
104
|
+
Source = "Value",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
ProgressCurveLookup = LUTBezier {
|
|
109
|
+
KeyColorSplines = {
|
|
110
|
+
[0] = {
|
|
111
|
+
[0] = { 0, RH = { 0.333, 0.333 }, Flags = { Linear = true } },
|
|
112
|
+
[1] = { 1, LH = { 0.666, 0.666 }, Flags = { Linear = true } }
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
SplineColor = { Red = 255, Green = 255, Blue = 255 },
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
ActiveTool = "MyTransition",
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Install path:** `Templates/Edit/Transitions/`.
|
|
125
|
+
|
|
126
|
+
**Transition operations worth knowing (for `Dissolve.Operation`):**
|
|
127
|
+
|
|
128
|
+
| FuID | Effect |
|
|
129
|
+
|------|--------|
|
|
130
|
+
| `DFTDissolve` | Straight cross-dissolve |
|
|
131
|
+
| `DFTLumaRamp` | Wipe driven by the `Map` input's luma — lets you shape the wipe with any image |
|
|
132
|
+
| `DFTAdditiveDissolve` | Additive blend |
|
|
133
|
+
|
|
134
|
+
`DFTLumaRamp` is the workhorse for wipes: pipe a gradient or shape into `Map` and you get a controllable wipe. Box Wipe and most stock transitions use this pattern.
|
|
135
|
+
|
|
136
|
+
## 3. Edit Title
|
|
137
|
+
|
|
138
|
+
**Role:** text generator with stretched animation.
|
|
139
|
+
|
|
140
|
+
**Hooks:** no MainInput. Wraps a `TextPlus` node. Internal animation is piped through a `KeyStretcher` so it stretches to the clip's actual duration.
|
|
141
|
+
|
|
142
|
+
```lua
|
|
143
|
+
{
|
|
144
|
+
Tools = ordered() {
|
|
145
|
+
MyTitle = GroupOperator {
|
|
146
|
+
Inputs = ordered() {
|
|
147
|
+
Input1 = InstanceInput { SourceOp = "Text", Source = "StyledText" },
|
|
148
|
+
Input2 = InstanceInput { SourceOp = "Text", Source = "Font", ControlGroup = 2 },
|
|
149
|
+
Input3 = InstanceInput { SourceOp = "Text", Source = "Style", ControlGroup = 2 },
|
|
150
|
+
Size = InstanceInput { SourceOp = "Text", Source = "Size", Default = 0.08 },
|
|
151
|
+
Pos = InstanceInput { SourceOp = "Text", Source = "Center", Name = "Position" },
|
|
152
|
+
Red = InstanceInput { SourceOp = "Text", Source = "Red", Name = "Color", ControlGroup = 10, Default = 1 },
|
|
153
|
+
Green = InstanceInput { SourceOp = "Text", Source = "Green", Name = "Color", ControlGroup = 10, Default = 1 },
|
|
154
|
+
Blue = InstanceInput { SourceOp = "Text", Source = "Blue", Name = "Color", ControlGroup = 10, Default = 1 },
|
|
155
|
+
Alpha = InstanceInput { SourceOp = "Text", Source = "Alpha", Name = "Color", ControlGroup = 10, Default = 1 },
|
|
156
|
+
},
|
|
157
|
+
Outputs = {
|
|
158
|
+
MainOutput1 = InstanceOutput {
|
|
159
|
+
SourceOp = "Stretcher",
|
|
160
|
+
Source = "Result",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
Tools = ordered() {
|
|
164
|
+
Text = TextPlus {
|
|
165
|
+
Inputs = {
|
|
166
|
+
GlobalOut = Input { Value = 500 },
|
|
167
|
+
Width = Input { Value = 1920 },
|
|
168
|
+
Height = Input { Value = 1080 },
|
|
169
|
+
UseFrameFormatSettings = Input { Value = 1 },
|
|
170
|
+
StyledText = Input { Value = "SAMPLE" },
|
|
171
|
+
Font = Input { Value = "Open Sans" },
|
|
172
|
+
Style = Input { Value = "Bold" },
|
|
173
|
+
Size = Input { Value = 0.08 },
|
|
174
|
+
VerticalJustificationNew = Input { Value = 3 },
|
|
175
|
+
HorizontalJustificationNew = Input { Value = 3 },
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
Stretcher = KeyStretcher {
|
|
179
|
+
Inputs = {
|
|
180
|
+
Keyframes = Input {
|
|
181
|
+
SourceOp = "Text",
|
|
182
|
+
Source = "Output",
|
|
183
|
+
},
|
|
184
|
+
SourceEnd = Input { Value = 119 },
|
|
185
|
+
StretchStart = Input { Value = 10 },
|
|
186
|
+
StretchEnd = Input { Value = 100 },
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
ActiveTool = "MyTitle",
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Install path:** `Templates/Edit/Titles/`.
|
|
197
|
+
|
|
198
|
+
Key details:
|
|
199
|
+
|
|
200
|
+
- `MainOutput1` pulls `Source = "Result"` from the `KeyStretcher` (not `"Output"` — that's the unstretched pixels).
|
|
201
|
+
- Animation on the `TextPlus` (via `BezierSpline` inputs for Alpha, Size, Color, etc.) gets stretched to match the clip length by `KeyStretcher`.
|
|
202
|
+
- Stock titles often expose *many* text controls (font, style, size, tracking, line spacing, V/H anchor, color, background color). Copy the pattern from `Edit/Titles/Background Reveal.setting` if you want the full treatment.
|
|
203
|
+
|
|
204
|
+
## 4. Edit Generator
|
|
205
|
+
|
|
206
|
+
**Role:** pure pixel source. No input clip — just produces an image.
|
|
207
|
+
|
|
208
|
+
**Hooks:** no MainInput. One `MainOutput1`.
|
|
209
|
+
|
|
210
|
+
```lua
|
|
211
|
+
{
|
|
212
|
+
Tools = ordered() {
|
|
213
|
+
MyGenerator = GroupOperator {
|
|
214
|
+
Inputs = ordered() {
|
|
215
|
+
Detail = InstanceInput {
|
|
216
|
+
SourceOp = "Noise1",
|
|
217
|
+
Source = "Detail",
|
|
218
|
+
Default = 5,
|
|
219
|
+
MinScale = 0,
|
|
220
|
+
MaxScale = 10,
|
|
221
|
+
},
|
|
222
|
+
Scale = InstanceInput {
|
|
223
|
+
SourceOp = "Noise1",
|
|
224
|
+
Source = "XScale",
|
|
225
|
+
Default = 10,
|
|
226
|
+
MinScale = 1,
|
|
227
|
+
MaxScale = 50,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
Outputs = {
|
|
231
|
+
MainOutput1 = InstanceOutput {
|
|
232
|
+
SourceOp = "Noise1",
|
|
233
|
+
Source = "Output",
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
Tools = ordered() {
|
|
237
|
+
Noise1 = FastNoise {
|
|
238
|
+
Inputs = {
|
|
239
|
+
Width = Input { Value = 1920 },
|
|
240
|
+
Height = Input { Value = 1080 },
|
|
241
|
+
UseFrameFormatSettings = Input { Value = 1 },
|
|
242
|
+
Detail = Input { Value = 5 },
|
|
243
|
+
XScale = Input { Value = 10 },
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
ActiveTool = "MyGenerator",
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Install path:** `Templates/Edit/Generators/`.
|
|
254
|
+
|
|
255
|
+
## 5. Fusion Tool
|
|
256
|
+
|
|
257
|
+
**Role:** pixel filter applied on the Fusion page. Reads an upstream image, writes a processed version. Functionally identical to an Edit Effect but installed on the Fusion page.
|
|
258
|
+
|
|
259
|
+
**Hook:** `GroupOperator` with `MainInput1` wired to the first internal node's `Input`. Internal nodes can carry `UserControls` on sub-nodes — those controls surface automatically without needing to be re-declared as `InstanceInput`. The duplicate-top-level-node artifact: nodes referenced from inside the group also appear again at the outer top level of the file (a serialization quirk) — do not try to remove them.
|
|
260
|
+
|
|
261
|
+
```lua
|
|
262
|
+
{
|
|
263
|
+
Tools = ordered() {
|
|
264
|
+
MyFusionTool = GroupOperator {
|
|
265
|
+
Inputs = ordered() {
|
|
266
|
+
MainInput1 = InstanceInput {
|
|
267
|
+
SourceOp = "Transform1",
|
|
268
|
+
Source = "Input",
|
|
269
|
+
},
|
|
270
|
+
Magnitude = InstanceInput {
|
|
271
|
+
SourceOp = "Expr1",
|
|
272
|
+
Source = "n1",
|
|
273
|
+
Name = "Overall Magnitude",
|
|
274
|
+
Default = 0.5,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
Outputs = {
|
|
278
|
+
MainOutput1 = InstanceOutput {
|
|
279
|
+
SourceOp = "Transform1",
|
|
280
|
+
Source = "Output",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
Tools = ordered() {
|
|
284
|
+
Expr1 = Custom {
|
|
285
|
+
-- drives transform amounts
|
|
286
|
+
},
|
|
287
|
+
Transform1 = Transform {
|
|
288
|
+
Inputs = {
|
|
289
|
+
Input = Input { SourceOp = "...", Source = "Output" },
|
|
290
|
+
-- ...
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
-- serialization artifact: inner nodes appear here too
|
|
296
|
+
Transform1 = Transform { -- ...
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
ActiveTool = "MyFusionTool",
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Install path:** `Templates/Fusion/Tools/`.
|
|
304
|
+
|
|
305
|
+
**Key details:**
|
|
306
|
+
|
|
307
|
+
- Structure is identical to an Edit Effect — `GroupOperator` + `MainInput1` + `MainOutput1`.
|
|
308
|
+
- Sub-nodes can have `UserControls` blocks (e.g., `RangeControl` pairs on `Shake` nodes) that surface in the inspector without needing extra `InstanceInput` declarations.
|
|
309
|
+
- The top-level `Tools` block will contain duplicate entries for inner nodes — this is normal and required by Resolve's serializer; do not delete them.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## 6. Fusion Background
|
|
314
|
+
|
|
315
|
+
**Role:** pure 3D pixel source — no input clip, produces a rendered image. Backgrounds are typically full 3D scene pipelines, not 2D procedural generators.
|
|
316
|
+
|
|
317
|
+
**Hook:** two valid shapes exist in the stock library. (a) Wrapped: a `GroupOperator` with no `MainInput` and a single output (either `MainOutput1` or `Output1`) sourced from a `Renderer3D`. (b) Unwrapped: raw top-level nodes with `ActiveTool` pointing to the terminal `Renderer3D`. The canonical pipeline is `Shape3D → [Bender3D / Transform3D] → Merge3D → Camera3D → Renderer3D`.
|
|
318
|
+
|
|
319
|
+
```lua
|
|
320
|
+
-- Wrapped variant (e.g., Blue Rays.setting)
|
|
321
|
+
{
|
|
322
|
+
Tools = ordered() {
|
|
323
|
+
MyBackground = GroupOperator {
|
|
324
|
+
Inputs = ordered() {
|
|
325
|
+
Color = InstanceInput {
|
|
326
|
+
SourceOp = "Shape3D1",
|
|
327
|
+
Source = "MtlStdInputs.Diffuse.Color.Red",
|
|
328
|
+
ControlGroup = 1,
|
|
329
|
+
Default = 0.08,
|
|
330
|
+
},
|
|
331
|
+
-- more color / glow controls ...
|
|
332
|
+
},
|
|
333
|
+
Outputs = {
|
|
334
|
+
MainOutput1 = InstanceOutput {
|
|
335
|
+
SourceOp = "Renderer3D1",
|
|
336
|
+
Source = "Output",
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
Tools = ordered() {
|
|
340
|
+
Shape3D1 = Shape3D { -- geometry source
|
|
341
|
+
Inputs = { Shape = Input { Value = FuID { "SurfaceCylinderInputs" } } },
|
|
342
|
+
},
|
|
343
|
+
Merge3D1 = Merge3D { Inputs = { SceneInput1 = Input { SourceOp = "Shape3D1", Source = "Output" } } },
|
|
344
|
+
Camera3D1 = Camera3D { },
|
|
345
|
+
Renderer3D1 = Renderer3D {
|
|
346
|
+
Inputs = {
|
|
347
|
+
SceneInput = Input { SourceOp = "Merge3D1", Source = "Output" },
|
|
348
|
+
Width = Input { Value = 1920 },
|
|
349
|
+
Height = Input { Value = 1080 },
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
ActiveTool = "MyBackground",
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
-- Unwrapped variant (e.g., Bender.setting): raw nodes at top level
|
|
359
|
+
-- ActiveTool = "Renderer3D1_2" -- Resolve previews this node
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Install path:** `Templates/Fusion/Backgrounds/`.
|
|
363
|
+
|
|
364
|
+
**Key details:**
|
|
365
|
+
|
|
366
|
+
- No `MainInput` — these are pure sources.
|
|
367
|
+
- Wrapped files may use either `MainOutput1` or `Output1` for the group output. `MainOutput1` is preferred for consistency with Edit categories; `Output1` also works.
|
|
368
|
+
- Unwrapped files have no `GroupOperator` at all. `ActiveTool` must point to the `Renderer3D` so Resolve knows what to preview in the browser.
|
|
369
|
+
- The minimum 3D pipeline is `Shape3D → Merge3D → Camera3D → Renderer3D`. Lights (`LightPoint`, `AmbientLight`) are added into the `Merge3D` as additional scene inputs.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## 7. Fusion Generator
|
|
374
|
+
|
|
375
|
+
**Role:** 3D geometry generator, not a 2D pixel source. Unlike Edit Generators (which wrap `FastNoise` or similar 2D nodes), Fusion Generators produce 3D geometry and expose their `MainInput` slots as **material** inputs, not image inputs.
|
|
376
|
+
|
|
377
|
+
**Hook:** `GroupOperator` with `MainInput1`…`N` wired to `MaterialInput` on `Shape3D` nodes (one per geometry part). The output is a rendered image from a `Renderer3D`.
|
|
378
|
+
|
|
379
|
+
```lua
|
|
380
|
+
{
|
|
381
|
+
Tools = ordered() {
|
|
382
|
+
MyGenerator = GroupOperator {
|
|
383
|
+
Inputs = ordered() {
|
|
384
|
+
MainInput1 = InstanceInput {
|
|
385
|
+
SourceOp = "Shape3D1",
|
|
386
|
+
Source = "MaterialInput",
|
|
387
|
+
Name = "Outer Material",
|
|
388
|
+
},
|
|
389
|
+
MainInput2 = InstanceInput {
|
|
390
|
+
SourceOp = "Shape3D2",
|
|
391
|
+
Source = "MaterialInput",
|
|
392
|
+
Name = "Inner Material",
|
|
393
|
+
},
|
|
394
|
+
-- geometry controls (radius, height, subdivision, etc.)
|
|
395
|
+
OutRadius = InstanceInput {
|
|
396
|
+
SourceOp = "Shape3D1",
|
|
397
|
+
Source = "SurfaceCylinderInputs.Radius",
|
|
398
|
+
Name = "Outer Radius",
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
Outputs = {
|
|
402
|
+
MainOutput1 = InstanceOutput {
|
|
403
|
+
SourceOp = "Renderer3D1",
|
|
404
|
+
Source = "Output",
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
Tools = ordered() {
|
|
408
|
+
Shape3D1 = Shape3D { Inputs = { Shape = Input { Value = FuID { "SurfaceCylinderInputs" } } } },
|
|
409
|
+
Shape3D2 = Shape3D { -- ...
|
|
410
|
+
},
|
|
411
|
+
Merge3D1 = Merge3D { Inputs = { SceneInput1 = Input { SourceOp = "Shape3D1", Source = "Output" },
|
|
412
|
+
SceneInput2 = Input { SourceOp = "Shape3D2", Source = "Output" } } },
|
|
413
|
+
Camera3D1 = Camera3D { },
|
|
414
|
+
Renderer3D1 = Renderer3D { Inputs = { SceneInput = Input { SourceOp = "Merge3D1", Source = "Output" } } },
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
ActiveTool = "MyGenerator",
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
**Install path:** `Templates/Fusion/Generators/`.
|
|
423
|
+
|
|
424
|
+
**Key details:**
|
|
425
|
+
|
|
426
|
+
- `MainInput1`…`MainInputN` are **material** connections (wired to `Shape3D.MaterialInput`), not image inputs. Users plug in Shader presets or `MtlBlinn` materials, not video clips.
|
|
427
|
+
- Each geometry part that should accept a custom material needs its own `MainInputN` slot.
|
|
428
|
+
- The file still renders a preview image via `Renderer3D` — `MainOutput1` sources from it.
|
|
429
|
+
- Geometry controls (radius, height, subdivision) are surfaced as `InstanceInput` entries targeting the specific `Shape3D` sub-parameters.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 8. Fusion How To
|
|
434
|
+
|
|
435
|
+
**Role:** pedagogical comp — illustrates a technique, not a reusable tool. Not designed to be wired into a user's timeline.
|
|
436
|
+
|
|
437
|
+
**Hook:** no standard I/O. Typically nested `GroupOperator` wrappers that output via `Output1` (not `MainOutput1`). `ActiveTool` points to an intermediate node the author wants to highlight, not the final output.
|
|
438
|
+
|
|
439
|
+
```lua
|
|
440
|
+
{
|
|
441
|
+
Tools = ordered() {
|
|
442
|
+
Group2 = GroupOperator {
|
|
443
|
+
-- No Inputs block (no MainInput1)
|
|
444
|
+
Outputs = {
|
|
445
|
+
Output1 = InstanceOutput {
|
|
446
|
+
SourceOp = "Merge3D2",
|
|
447
|
+
Source = "Output",
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
ViewInfo = GroupInfo {
|
|
451
|
+
Flags = {
|
|
452
|
+
AllowPan = false,
|
|
453
|
+
GridSnap = true,
|
|
454
|
+
AutoSnap = true,
|
|
455
|
+
RemoveRouters = true,
|
|
456
|
+
},
|
|
457
|
+
-- ...
|
|
458
|
+
},
|
|
459
|
+
Tools = ordered() {
|
|
460
|
+
-- full scene graph demonstrating the technique
|
|
461
|
+
-- inner groups also use Output1, not MainOutput1
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
ActiveTool = "BrightnessContrast1", -- intermediate node, pedagogically interesting
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Install path:** `Templates/Fusion/How To/`.
|
|
470
|
+
|
|
471
|
+
**Key details:**
|
|
472
|
+
|
|
473
|
+
- No `MainInput1` / `MainOutput1`. These files are not filters or sources — they are demonstrations.
|
|
474
|
+
- All files in this category share a single `_default.png` / `_default@2x.png` thumbnail pair (no per-file thumbnails).
|
|
475
|
+
- Output ports use `Output1`, not `MainOutput1`.
|
|
476
|
+
- `ActiveTool` is set to the node the author wants to draw attention to (e.g., a `BrightnessContrast` or `MatteControl` mid-graph), not necessarily the terminal output.
|
|
477
|
+
- Multiple `ActiveTool` entries can appear if the file contains nested groups that each declare one — the outermost one wins.
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## 9. Fusion Lens Flare
|
|
482
|
+
|
|
483
|
+
**Role:** HotSpot-based lens flare preset. Unlike every other category, the root node is a raw `HotSpot` — not a `GroupOperator`. A single `.setting` file ships as multiple switchable preset variants stored inside `CustomData.AltSettings9`.
|
|
484
|
+
|
|
485
|
+
**The AltSettings9 preset-bank pattern:** `CustomData.AltSettings9` is a numbered `Settings` block. Each numbered entry is a complete `HotSpot` configuration. `CurrentSettings` on the outer `HotSpot` indicates which preset is currently active (1-based). This is how the Effects Library browser shows multiple "variants" for a single flare file.
|
|
486
|
+
|
|
487
|
+
```lua
|
|
488
|
+
{
|
|
489
|
+
Tools = ordered() {
|
|
490
|
+
Lens_Flare_V01 = HotSpot {
|
|
491
|
+
CtrlWZoom = false,
|
|
492
|
+
NameSet = true,
|
|
493
|
+
CustomData = {
|
|
494
|
+
AltSettings9 = {
|
|
495
|
+
-- preset variant 1
|
|
496
|
+
Tools = ordered() {
|
|
497
|
+
HotSpot1 = HotSpot {
|
|
498
|
+
Inputs = {
|
|
499
|
+
Input = Input {
|
|
500
|
+
SourceOp = "Background1", -- feed a background image here
|
|
501
|
+
Source = "Output",
|
|
502
|
+
},
|
|
503
|
+
PrimaryCenter = Input { Value = { 0.26, 0.62 } },
|
|
504
|
+
HotSpotSize = Input { Value = 0.52 },
|
|
505
|
+
Red = Input { SourceOp = "HotSpot1Red", Source = "Value" },
|
|
506
|
+
Green = Input { SourceOp = "HotSpot1Green", Source = "Value" },
|
|
507
|
+
Blue = Input { SourceOp = "HotSpot1Blue", Source = "Value" },
|
|
508
|
+
-- BezierSpline nodes drive color over angle
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
-- BezierSpline color-curve nodes ...
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
-- AltSettings9[2], [3], ... for additional presets
|
|
515
|
+
},
|
|
516
|
+
-- outer HotSpot mirrors the active preset's inputs:
|
|
517
|
+
Inputs = {
|
|
518
|
+
-- same structure as HotSpot1 above
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
ActiveTool = "Lens_Flare_V01",
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Install path:** `Templates/Fusion/Lens Flares/`.
|
|
527
|
+
|
|
528
|
+
**Key details:**
|
|
529
|
+
|
|
530
|
+
- Root node is `HotSpot`, not `GroupOperator`. There is no `MainInput1` or `MainOutput1`.
|
|
531
|
+
- Background image feeds via `HotSpot.Input` (not `MainInput1`).
|
|
532
|
+
- Preset variants live in `CustomData.AltSettings9` as numbered entries. `CurrentSettings = N` (on the outer `HotSpot`) selects the active preset.
|
|
533
|
+
- BezierSpline nodes inside each preset drive color tints over the flare's angular position.
|
|
534
|
+
- The outer `HotSpot` (at the `Tools` level) mirrors the currently-active preset's inputs — it is what Resolve renders.
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
## 10. Fusion Motion Graphic
|
|
539
|
+
|
|
540
|
+
**Role:** standalone animated graphic — title card, lower third, animated element. Ships as raw top-level nodes with no `GroupOperator` wrapper. Users get the full node graph dropped into their comp.
|
|
541
|
+
|
|
542
|
+
**Hook:** no wrapper. `ActiveTool` must point to the **terminal composite node** (usually a `Merge`) — Resolve uses it to determine what the browser preview renders. Thumbnails follow a distinct convention: `wide.png` / `wide@2x.png` plus `small.active.png`.
|
|
543
|
+
|
|
544
|
+
```lua
|
|
545
|
+
{
|
|
546
|
+
Tools = ordered() {
|
|
547
|
+
Background1 = Background {
|
|
548
|
+
Inputs = {
|
|
549
|
+
Width = Input { Value = 1920 },
|
|
550
|
+
Height = Input { Value = 1080 },
|
|
551
|
+
UseFrameFormatSettings = Input { Value = 1 },
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
TextPlus1 = TextPlus {
|
|
555
|
+
Inputs = {
|
|
556
|
+
StyledText = Input { Value = "SAMPLE" },
|
|
557
|
+
-- animation via BezierSpline inputs ...
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
RectangleMask1 = RectangleMask { Inputs = { -- ...
|
|
561
|
+
} },
|
|
562
|
+
Merge10 = Merge {
|
|
563
|
+
Inputs = {
|
|
564
|
+
Background = Input { SourceOp = "Background1", Source = "Output" },
|
|
565
|
+
Foreground = Input { SourceOp = "TextPlus1", Source = "Output" },
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
-- PublishNumber, Shake, BezierSpline nodes also appear at top level
|
|
569
|
+
},
|
|
570
|
+
ActiveTool = "Merge10",
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
**Install path:** `Templates/Fusion/Motion Graphics/`.
|
|
575
|
+
|
|
576
|
+
**Key details:**
|
|
577
|
+
|
|
578
|
+
- No `GroupOperator` wrapper — the entire node graph is exposed at the top level.
|
|
579
|
+
- `ActiveTool` must be the terminal `Merge` (or equivalent composite). Resolve uses this to render the browser thumbnail and insert the comp correctly.
|
|
580
|
+
- Can use any Fusion node: `PublishNumber`, `Shake`, `BezierSpline`, `TextPlus`, `Merge`, `Background`, `RectangleMask`, etc. There is no I/O contract.
|
|
581
|
+
- Thumbnail files use `wide.png` / `wide@2x.png` + `small.active.png` naming — different from Backgrounds (which use `large.png`).
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## 11. Fusion Particle
|
|
586
|
+
|
|
587
|
+
**Role:** particle system preset. Root node is a raw `pEmitter`. Multiple preset variants (e.g., different emitter configurations) are stored inside `CustomData.Settings` on the outer `pEmitter`, with `CurrentSettings = N` selecting the active one.
|
|
588
|
+
|
|
589
|
+
**Hook:** minimum working pipeline is `pEmitter → pRender → [Merge3D with Camera3D] → Renderer3D`. The `pRender` node is required to convert the particle stream into a renderable image; omitting it results in an invisible output.
|
|
590
|
+
|
|
591
|
+
```lua
|
|
592
|
+
{
|
|
593
|
+
Tools = ordered() {
|
|
594
|
+
pEmitter1 = pEmitter {
|
|
595
|
+
CurrentSettings = 1,
|
|
596
|
+
CustomData = {
|
|
597
|
+
Settings = {
|
|
598
|
+
[1] = {
|
|
599
|
+
Tools = ordered() {
|
|
600
|
+
pEmitter1 = pEmitter {
|
|
601
|
+
Inputs = {
|
|
602
|
+
Number = Input { Value = 100 },
|
|
603
|
+
Style = Input { Value = FuID { "ParticleStyleBitmap" } },
|
|
604
|
+
-- ["ParticleStyle.Size"] = Input { Value = 0.08 },
|
|
605
|
+
-- region, spin, color-over-life, etc.
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
-- [2] = { ... } additional presets
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
Inputs = {
|
|
614
|
+
-- mirrors active preset inputs
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
pRender1 = pRender {
|
|
618
|
+
Inputs = {
|
|
619
|
+
SceneInput = Input { SourceOp = "pEmitter1", Source = "Output" },
|
|
620
|
+
Width = Input { Value = 1920 },
|
|
621
|
+
Height = Input { Value = 1080 },
|
|
622
|
+
},
|
|
623
|
+
},
|
|
624
|
+
Camera3D1 = Camera3D { },
|
|
625
|
+
Merge3D1 = Merge3D {
|
|
626
|
+
Inputs = {
|
|
627
|
+
SceneInput1 = Input { SourceOp = "pRender1", Source = "Output" },
|
|
628
|
+
SceneInput2 = Input { SourceOp = "Camera3D1", Source = "Output" },
|
|
629
|
+
},
|
|
630
|
+
},
|
|
631
|
+
Renderer3D1 = Renderer3D {
|
|
632
|
+
Inputs = { SceneInput = Input { SourceOp = "Merge3D1", Source = "Output" } },
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
ActiveTool = "Renderer3D1",
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
**Install path:** `Templates/Fusion/Particles/`.
|
|
640
|
+
|
|
641
|
+
**Key details:**
|
|
642
|
+
|
|
643
|
+
- Root node is `pEmitter`, not `GroupOperator`.
|
|
644
|
+
- `pRender` is mandatory — it converts the particle stream to an image that `Renderer3D` can process. Without it the output is invisible.
|
|
645
|
+
- Preset variants live in `CustomData.Settings` (numbered from 1). `CurrentSettings = N` selects the active one. This is the same preset-bank pattern as Lens Flares, but uses `Settings` instead of `AltSettings9`.
|
|
646
|
+
- `ActiveTool` points to `Renderer3D` (the terminal rendered output), not the `pEmitter`.
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## 12. Fusion Shader
|
|
651
|
+
|
|
652
|
+
**Role:** 3D material (shader) preset. Designed to be plugged into a `Shape3D.MaterialInput` or used standalone with its own preview geometry. Root node is a `GroupOperator`.
|
|
653
|
+
|
|
654
|
+
**Hook:** `GroupOperator` with no `MainInput`. Output is `Output1` (not `MainOutput1`). The output can carry either (a) a rendered image (`Source = "Output"` from a `Renderer3D` inside the group — for standalone preview) or (b) a raw material (`Source = "MaterialOutput"` from a material node — for direct plug-in to another Shape3D). The `Anisotropic.setting` uses option (a): it wraps its own `Shape3D + Renderer3D` so the shader can be previewed directly. The `GroupInfo.Flags` block (`AllowPan`, `GridSnap`, etc.) is present in Shader group operators and typically absent in Edit effects.
|
|
655
|
+
|
|
656
|
+
```lua
|
|
657
|
+
{
|
|
658
|
+
Tools = ordered() {
|
|
659
|
+
MyShader = GroupOperator {
|
|
660
|
+
CtrlWZoom = false,
|
|
661
|
+
NameSet = true,
|
|
662
|
+
Inputs = ordered() {
|
|
663
|
+
Comments = Input { Value = "Apply to any shape; requires lights." },
|
|
664
|
+
},
|
|
665
|
+
Outputs = {
|
|
666
|
+
Output1 = InstanceOutput {
|
|
667
|
+
SourceOp = "Renderer3D1", -- option (a): rendered preview
|
|
668
|
+
Source = "Output",
|
|
669
|
+
-- OR, for a raw material output:
|
|
670
|
+
-- SourceOp = "MtlBlinn1",
|
|
671
|
+
-- Source = "MaterialOutput",
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
ViewInfo = GroupInfo {
|
|
675
|
+
Flags = {
|
|
676
|
+
AllowPan = false,
|
|
677
|
+
GridSnap = true,
|
|
678
|
+
AutoSnap = true,
|
|
679
|
+
RemoveRouters = true,
|
|
680
|
+
},
|
|
681
|
+
-- ...
|
|
682
|
+
},
|
|
683
|
+
Tools = ordered() {
|
|
684
|
+
MtlBlinn1 = MtlBlinn { Inputs = { -- material properties
|
|
685
|
+
} },
|
|
686
|
+
BumpMap1 = BumpMap { Inputs = { Input = Input { SourceOp = "...", Source = "Output" } } },
|
|
687
|
+
Shape3D1 = Shape3D { Inputs = { MaterialInput = Input { SourceOp = "MtlBlinn1", Source = "MaterialOutput" } } },
|
|
688
|
+
Merge3D1 = Merge3D { Inputs = { SceneInput1 = Input { SourceOp = "Shape3D1", Source = "Output" } } },
|
|
689
|
+
Renderer3D1 = Renderer3D { Inputs = { SceneInput = Input { SourceOp = "Merge3D1", Source = "Output" } } },
|
|
690
|
+
},
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
ActiveTool = "MyShader",
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Install path:** `Templates/Fusion/Shaders/`.
|
|
698
|
+
|
|
699
|
+
**Key details:**
|
|
700
|
+
|
|
701
|
+
- Output field is `Output1`, not `MainOutput1`.
|
|
702
|
+
- Two output modes: rendered image (`Source = "Output"` from `Renderer3D`) or raw material (`Source = "MaterialOutput"` from a material node). Choose based on how the user will consume it: standalone preview vs. plug-in to another Shape3D.
|
|
703
|
+
- `GroupInfo.Flags` block with `AllowPan`, `GridSnap`, `AutoSnap`, `RemoveRouters` is characteristic of Shader groups — it controls the group's internal canvas behavior.
|
|
704
|
+
- No `MainInput` — shaders do not accept upstream images.
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## 13. Fusion Styled Text
|
|
709
|
+
|
|
710
|
+
**Role:** per-character animated text preset. Unlike Edit Titles (which use `KeyStretcher`), Styled Text presets are raw node trees with no `GroupOperator` wrapper. They are defined by two nodes that do not appear in any other category: `StyledTextFollower` and `PublishNumber`.
|
|
711
|
+
|
|
712
|
+
**Hook:** no wrapper. `ActiveTool` points to the primary `TextPlus` node (e.g., `"Text1_2"`), not the terminal `Merge`. `PublishNumber` nodes share scalar or color values across multiple `TextPlus` nodes. `StyledTextFollower` drives per-character follower animations.
|
|
713
|
+
|
|
714
|
+
```lua
|
|
715
|
+
{
|
|
716
|
+
Tools = ordered() {
|
|
717
|
+
Background6 = Background {
|
|
718
|
+
Inputs = {
|
|
719
|
+
Width = Input { Value = 1920 },
|
|
720
|
+
Height = Input { Value = 1080 },
|
|
721
|
+
UseFrameFormatSettings = Input { Value = 1 },
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
Publish1_2 = PublishNumber { Inputs = { Value = Input { Value = 0.8 } } },
|
|
725
|
+
Publish2_2 = PublishNumber { Inputs = { Value = Input { Value = 0.2 } } },
|
|
726
|
+
Follower1_2 = StyledTextFollower {
|
|
727
|
+
Inputs = {
|
|
728
|
+
-- per-character timing / offset controls
|
|
729
|
+
},
|
|
730
|
+
},
|
|
731
|
+
Text1_2 = TextPlus {
|
|
732
|
+
Inputs = {
|
|
733
|
+
StyledText = Input { Value = "SAMPLE" },
|
|
734
|
+
Red1 = Input { SourceOp = "Publish1_2", Source = "Value" },
|
|
735
|
+
Green1 = Input { SourceOp = "Publish2_2", Source = "Value" },
|
|
736
|
+
-- animation splines, TV / SoftGlow effects piped in ...
|
|
737
|
+
},
|
|
738
|
+
},
|
|
739
|
+
TV1_2 = TV { Inputs = { Input = Input { SourceOp = "Text1_2", Source = "Output" } } },
|
|
740
|
+
SoftGlow1 = SoftGlow { Inputs = { Input = Input { SourceOp = "TV1_2", Source = "Output" } } },
|
|
741
|
+
Merge12 = Merge {
|
|
742
|
+
Inputs = {
|
|
743
|
+
Background = Input { SourceOp = "Background6", Source = "Output" },
|
|
744
|
+
Foreground = Input { SourceOp = "SoftGlow1", Source = "Output" },
|
|
745
|
+
},
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
ActiveTool = "Text1_2",
|
|
749
|
+
}
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
**Install path:** `Templates/Fusion/Styled Text/`.
|
|
753
|
+
|
|
754
|
+
**Key details:**
|
|
755
|
+
|
|
756
|
+
- No `GroupOperator` — the full node tree is raw at the top level.
|
|
757
|
+
- `StyledTextFollower` and `PublishNumber` are the defining nodes. An author who omits them produces something that looks nothing like the stock library.
|
|
758
|
+
- `ActiveTool` points to the primary `TextPlus` (e.g., `"Text1_2"`), not the terminal `Merge` — this is the opposite convention from Motion Graphics.
|
|
759
|
+
- `PublishNumber` nodes share values (color channels, scalar parameters) across multiple `TextPlus` nodes so a single "Color" slider controls all text elements at once.
|
|
760
|
+
- `BezierSpline` inputs on `TextPlus` (alpha, size, tracking) provide the per-character animation timing.
|
|
761
|
+
|
|
762
|
+
---
|
|
763
|
+
|
|
764
|
+
## Role → Shape Cheat Sheet
|
|
765
|
+
|
|
766
|
+
| Role | Wrap in GroupOperator? | MainInput1 | MainInput2 | MainOutput1 source | Output field |
|
|
767
|
+
|------|-----------------------|------------|------------|---------------------|-------------|
|
|
768
|
+
| Edit Effect | Yes | Required → `Input` of first node | — | Terminal node | `Output` |
|
|
769
|
+
| Edit Transition | Yes | Required → `Background` | Required → `Foreground` | Dissolve/Merge | `Output` |
|
|
770
|
+
| Edit Title | Yes | — | — | KeyStretcher | `Result` |
|
|
771
|
+
| Edit Generator | Yes | — | — | Terminal node | `Output` |
|
|
772
|
+
| Fusion Tool | Yes | Required → `Input` of first node | Optional | Terminal node | `Output` |
|
|
773
|
+
| Fusion Background | Yes (wrapped) or No (unwrapped) | — | — | `Renderer3D` | `MainOutput1` or `Output1`; unwrapped: `ActiveTool` on `Renderer3D` |
|
|
774
|
+
| Fusion Generator | Yes | Material → `Shape3D.MaterialInput` | Material → `Shape3D.MaterialInput` | `Renderer3D` | `MainOutput1` |
|
|
775
|
+
| Fusion How To | Yes (nested groups) | — | — | Intermediate node of interest | `Output1` |
|
|
776
|
+
| Fusion Lens Flare | No — raw `HotSpot` at top | — | — | — | `HotSpot.Input` for background; no `MainOutput1` |
|
|
777
|
+
| Fusion Motion Graphic | No — raw top-level nodes | — | — | Terminal `Merge` | `ActiveTool` on `Merge` |
|
|
778
|
+
| Fusion Particle | No — raw `pEmitter` at top | — | — | `Renderer3D` | `ActiveTool` on `Renderer3D` |
|
|
779
|
+
| Fusion Shader | Yes | — | — | `Renderer3D` (preview) or material node | `Output1` |
|
|
780
|
+
| Fusion Styled Text | No — raw top-level nodes | — | — | Primary `TextPlus` | `ActiveTool` on `TextPlus` |
|