@uemcp/server 1.3.0 → 1.5.0
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 +245 -0
- package/dist/index.mjs +7021 -1326
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,6 +94,37 @@ The MCP tool surface currently exposes:
|
|
|
94
94
|
- `list_data_layers`
|
|
95
95
|
- `set_data_layer_state`
|
|
96
96
|
- `load_wp_region`
|
|
97
|
+
- `get_asset_property`
|
|
98
|
+
- `set_asset_property`
|
|
99
|
+
- `array_property_op`
|
|
100
|
+
- `create_struct`
|
|
101
|
+
- `create_enum`
|
|
102
|
+
- `create_blueprint`
|
|
103
|
+
- `add_bp_variable`
|
|
104
|
+
- `add_bp_function`
|
|
105
|
+
- `add_bp_event`
|
|
106
|
+
- `add_bp_component`
|
|
107
|
+
- `add_bp_interface`
|
|
108
|
+
- `set_bp_default`
|
|
109
|
+
- `batch_edit`
|
|
110
|
+
- `import_asset`
|
|
111
|
+
- `reimport_asset`
|
|
112
|
+
- `set_import_settings`
|
|
113
|
+
- `get_import_job_status`
|
|
114
|
+
- `create_blackboard`
|
|
115
|
+
- `set_blackboard_keys`
|
|
116
|
+
- `create_eqs_query`
|
|
117
|
+
- `create_state_tree`
|
|
118
|
+
- `add_state_tree_state`
|
|
119
|
+
- `create_level_sequence`
|
|
120
|
+
- `add_sequence_binding`
|
|
121
|
+
- `add_sequence_track`
|
|
122
|
+
- `add_sequence_keys`
|
|
123
|
+
- `add_foliage_type`
|
|
124
|
+
- `paint_foliage`
|
|
125
|
+
- `create_sound_cue`
|
|
126
|
+
- `create_metasound`
|
|
127
|
+
- `set_metasound_graph`
|
|
97
128
|
|
|
98
129
|
## Project Identity
|
|
99
130
|
|
|
@@ -358,6 +389,220 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
|
|
|
358
389
|
- `load_wp_region` pins a bounding box into the editor through a loader adapter — the same mechanism the World Partition window uses when a human drags a loading region — and reports how many actors that brought into memory. The load is synchronous, so a box covering a large part of a big partitioned map blocks the editor while it runs: pin the area being worked on, not the whole world
|
|
359
390
|
- Pins are held by the bridge and released on `unpin_all`, and every pin is released when the bridge shuts down, so a session cannot silently accumulate loaded actors nobody can name any more
|
|
360
391
|
|
|
392
|
+
### `get_asset_property` / `set_asset_property` / `array_property_op`
|
|
393
|
+
|
|
394
|
+
- The asset-side counterpart to `get_actor_details` / `set_actor_property`: reflected reads and writes against an asset on disk rather than an actor in a level
|
|
395
|
+
- Values cross the wire as **ExportText**, the exact spelling the reader reports and the writer takes back, so a value read from one asset can be written straight into another without translation
|
|
396
|
+
- `propertyPath` walks structs, array elements and object references (`Modifiers[1].Magnitude`), and an `FPostProcessSettings`-style field also sets its `bOverride_` sibling — a write that skipped it would report success and change nothing anyone can see
|
|
397
|
+
- A Blueprint asset resolves to its **class defaults**, which is what the Class Defaults panel edits, rather than to the `UBlueprint` bookkeeping object that carries none of the user's properties
|
|
398
|
+
- `array_property_op` exists because an array cannot be written as one exported string without knowing the whole array. It reports `elementCount` after the operation, and an out-of-range index is refused **before** the transaction opens so a rejected request leaves no undo entry behind
|
|
399
|
+
- Every write leaves the package dirty rather than saving it, so a run of edits is one `save_asset`
|
|
400
|
+
|
|
401
|
+
### `create_struct` / `create_enum`
|
|
402
|
+
|
|
403
|
+
- User-defined types, authored through the engine's own `FStructureEditorUtils` / `FEnumEditorUtils` rather than by writing the asset — those utilities are what recompile every Blueprint that already referenced the type
|
|
404
|
+
- Field and variable types share **one type grammar** with the Blueprint tools: a `kind`, an optional `container` (`array`, `set`, `map`) and a `subtype` naming what the kind points at. A kind that names something in the project without a subtype is refused, because UE would otherwise produce a wildcard pin
|
|
405
|
+
- A fresh struct or enum arrives with one placeholder member so the asset is valid on disk; the requested members are added first and the placeholder removed afterwards, since neither utility will remove the last one
|
|
406
|
+
- `rebuiltAssets` reports what the editor recompiled because the type changed underneath it — empty for a brand-new type, which has no dependents yet
|
|
407
|
+
|
|
408
|
+
### `create_blueprint` / `add_bp_variable` / `add_bp_function` / `add_bp_event` / `add_bp_component` / `add_bp_interface` / `set_bp_default`
|
|
409
|
+
|
|
410
|
+
- Blueprint **authoring**, the write side of `get_blueprint_summary` / `get_blueprint_graph`. Every call leaves the Blueprint compiled and its package dirty: an uncompiled Blueprint reports the old member list to every reader, which makes the next tool call wrong
|
|
411
|
+
- `create_blueprint` reports the **generated class path** (`/Game/BP/BP_Foo.BP_Foo_C`), which is what `spawn_actor` and every class reference take — not the asset path
|
|
412
|
+
- `add_bp_variable` carries replication: `rep_notify` also authors the `OnRep_` handler graph, because a `CPF_RepNotify` variable whose handler does not exist fails to compile
|
|
413
|
+
- `add_bp_event` distinguishes `override` from `custom`. An override takes its signature from the parent, so declaring `inputs` on one is refused rather than silently discarded
|
|
414
|
+
- Batched calls report **per entry**: one variable that fails to resolve its type does not abort the other thirty-one
|
|
415
|
+
- `set_bp_default` writes the same reflected values `set_asset_property` does, against the generated class's CDO
|
|
416
|
+
|
|
417
|
+
### `batch_edit`
|
|
418
|
+
|
|
419
|
+
- The one level tool that is **all-or-nothing**. Every other batch reports per-item failures and keeps going; this one cancels its transaction on the first failure and leaves the level exactly as it was
|
|
420
|
+
- That is the point: ops address actors earlier ops created. A `spawn` binds a caller-supplied `handle`, and a later op addresses it as `handle:<name>` — a half-applied batch would leave the level in a state nobody described
|
|
421
|
+
- Ordered and heterogeneous: spawn, place, transform, set a property, attach, tag and destroy in one call, inside **one** `FScopedTransaction`, so a human presses Ctrl+Z once
|
|
422
|
+
- `handles` reports what each handle bound to, so the new actors are addressable afterwards. A rollback reports `failedIndex` and `failedError` and no handles, because none of them exist any more
|
|
423
|
+
- `dryRun` validates the shape of the batch only. An op addressing a handle can only be checked once the spawn that binds it has run, so anything further is a promise this call cannot keep
|
|
424
|
+
|
|
425
|
+
### `import_asset` / `reimport_asset` / `set_import_settings` / `get_import_job_status`
|
|
426
|
+
|
|
427
|
+
- Source asset import. An FBX of any real size runs far past the game thread budget, so both mutating requests return `state: 'accepted'` with an `importJobId`. Poll it with `get_import_job_status`, or wait with `wait_for_job` using `kind: 'import'`
|
|
428
|
+
- `pipeline: 'auto'` lets the editor route the file — **Interchange first, legacy factory where there is no translator**, which is the engine's own behaviour. `'interchange'` is refused up front for a file no translator claims, rather than quietly running the legacy factory instead; `'legacy_factory'` names the factory explicitly so Interchange cannot take over behind the caller's back
|
|
429
|
+
- Job results are **per source file**, and each one lists **every** asset it produced: a skeletal mesh import yields a mesh, a skeleton and a physics asset, and a caller that only heard about the mesh would leave the rest unreferenced
|
|
430
|
+
- `set_import_settings` stores a named preset. It is applied to the import factory that claims each source file, so a key that factory does not have is a **request error** rather than something dropped on the floor
|
|
431
|
+
- `get_import_job_status` is exposed as its own tool because the accept-then-poll shape needs somewhere to poll; it is not one of the tools the issues named, and it exists only to serve them
|
|
432
|
+
|
|
433
|
+
### `create_blackboard` / `set_blackboard_keys`
|
|
434
|
+
|
|
435
|
+
- Blackboard assets, the data half of a Behavior Tree
|
|
436
|
+
- An `object`, `class` or `enum` key **must** name its base type. Without it the key still appears in the editor and never matches anything at runtime, which is the failure these tools exist to prevent
|
|
437
|
+
- Inherited keys are counted and reported **separately** from local ones: a key that comes from the parent blackboard is not one this asset owns, and adding a local copy of it is exactly the mistake the split prevents
|
|
438
|
+
- `set_blackboard_keys` with `mode: 'replace'` drops the **local** keys only — an inherited key belongs to the parent asset and is not this request's to remove
|
|
439
|
+
|
|
440
|
+
### `create_eqs_query`
|
|
441
|
+
|
|
442
|
+
- Environment queries: one generator plus its tests, each with its own `purpose` (`filter`, `score`, or both), since a failing test either removes an item or merely scores it down
|
|
443
|
+
- Generator and test classes are resolved and their parameters written by reflection **before** the asset exists, so a typo leaves nothing behind in the content browser
|
|
444
|
+
- `eqsEnabled` reports whether the Environment Query editor is switched on. With it off the asset is still valid and still runs, but nothing in the editor will open it — reported rather than failed, and the response names where to turn it on (Editor Preferences → Experimental → AI → Environment Query Editor)
|
|
445
|
+
|
|
446
|
+
### `create_state_tree` / `add_state_tree_state`
|
|
447
|
+
|
|
448
|
+
- StateTree assets and their states. `supportedVersions` is reported on every answer, so an editor this plugin build cannot author StateTrees for says so instead of failing somewhere inside the compiler
|
|
449
|
+
- The schema decides which tasks and conditions the tree may hold at all, so an unresolvable one is refused before the asset exists
|
|
450
|
+
- Tasks and enter conditions are **script structs**, not classes, and are addressed as such; their parameters are written into the instanced struct's own memory by reflection
|
|
451
|
+
- `add_state_tree_state` compiles by default and reports `compiled` separately from the per-state results: a tree that was authored but not compiled reports `false` with no messages, which is a different thing from one that failed to compile
|
|
452
|
+
|
|
453
|
+
### `create_level_sequence` / `add_sequence_binding` / `add_sequence_track` / `add_sequence_keys`
|
|
454
|
+
|
|
455
|
+
- Sequencer authoring. **Every time on this surface is explicit**, because a sequence authored at the wrong rate is silently wrong rather than broken
|
|
456
|
+
- Frame rates cross the wire as the exact rationals Sequencer stores — 30000/1001 is not 29.97 — and `create_level_sequence` reports back both `displayRate` and `tickResolution`, since every frame number in `add_sequence_keys` resolves through them
|
|
457
|
+
- `add_sequence_keys` requires `timeUnit`: `'frames'` resolves through the display rate and `'seconds'` through the tick resolution. It reports `resolvedFrames`, which is the number that proves a seconds-based request converted correctly on a non-default rate
|
|
458
|
+
- A `possessable` binding names an actor in the level; a `spawnable` one needs a template, so it takes an actor to copy or a class to instance
|
|
459
|
+
- A `camera_cut` track belongs to the sequence itself; every other kind belongs to a binding, so `bindingId` is required for them. A `property` track is typed by the property it drives — bool, float and double properties are animatable, and anything else is refused rather than animated as the wrong type
|
|
460
|
+
|
|
461
|
+
### `add_foliage_type` / `paint_foliage`
|
|
462
|
+
|
|
463
|
+
- Foliage types and instance placement
|
|
464
|
+
- `mode: 'explicit'` places the transforms the caller supplies. `mode: 'region'` is a **rule the editor evaluates against the ground** — density over an area, traced downward, filtered by slope — which is the only shape that scales to the tens of thousands of instances a real pass produces
|
|
465
|
+
- A region takes a `randomSeed`, so the same call twice produces the same scatter and a painted region is reviewable rather than a one-off
|
|
466
|
+
- `attemptedCount`, `placedCount` and `skippedCount` are reported separately: a placement whose downward trace hit nothing, or hit ground outside the slope limits, is skipped rather than placed floating. `instanceCount` is the foliage actor's **total** for that type afterwards, so density can be checked against something absolute
|
|
467
|
+
|
|
468
|
+
### `create_sound_cue` / `create_metasound` / `set_metasound_graph`
|
|
469
|
+
|
|
470
|
+
- Audio authoring. Sound Cue nodes are addressed by **caller-supplied ids**, so connections can name nodes before the editor has created them
|
|
471
|
+
- `rootNodeId` must name one of the nodes in the same request, and a `wave_player` must name the wave it plays — both are refused up front rather than producing a cue that plays silence
|
|
472
|
+
- MetaSound documents are **never written directly**. The document format is versioned and migrated by the engine, so everything goes through `UMetaSoundBuilderSubsystem`, which is the only supported way to author one from code
|
|
473
|
+
- `set_metasound_graph` declares interface members, adds nodes by their registered class name and connects them. A connection whose data types do not match is reported with the builder's own refusal rather than left as a silently dead edge
|
|
474
|
+
|
|
475
|
+
### `generate_lods` / `generate_collision` / `convert_to_nanite`
|
|
476
|
+
|
|
477
|
+
- Static mesh optimization, all three through `UStaticMeshEditorSubsystem` so the mesh's render data is rebuilt and every component already placed in a level refreshes with it
|
|
478
|
+
- A mesh that is still compiling is refused rather than queued, because reduction settings written mid-build are overwritten by the build that was already running
|
|
479
|
+
- Triangle counts live in a mesh's render data, and reading that from the game thread finishes an in-flight build synchronously — which would spend the whole rebuild inside the request the editor is blocked on. `generate_lods` and `convert_to_nanite` therefore ask whether the mesh is still compiling first and report `rebuildPending` instead of counts: LOD triangle counts come back empty and the Nanite counts zero while it is true
|
|
480
|
+
- `generate_lods` takes one entry per LOD to build **below** the source mesh. LOD 0 is the mesh as authored and is never one of them, because the engine's own LOD array starts at the source mesh and reducing entry 0 would halve the full-detail mesh rather than add a level. `screenSize` goes on every entry or on none: the engine computes the whole ramp or takes all of it from the request
|
|
481
|
+
- `generate_collision` takes one of the engine's own simple shapes, or `convex` for a decomposition. `primitiveCount` reports the shapes the body setup actually holds afterwards, which for a convex decomposition is the hulls it produced — `hullCount` is what was asked for, not what came back. `convex` with `replaceExisting: false` is **refused**, because the engine's decomposition clears the existing simple collision whatever it is asked to do
|
|
482
|
+
- `convert_to_nanite` writes `fallbackPercentTriangles` and `keepPercentTriangles` separately, because they are different knobs: one is the non-Nanite fallback mesh, the other is what Nanite itself keeps. Supplying the fallback percentage also switches the mesh's fallback target to Percent Triangles, without which the builder resets it — so it is written only when the request carries it, and a call that only toggles Nanite leaves a hand-tuned fallback alone. `rebuildPending` is true where the mesh went back to compiling, so a caller knows the triangle counts it just read are provisional
|
|
483
|
+
|
|
484
|
+
### `create_material_instance` / `list_material_params` / `set_material_params` / `assign_material`
|
|
485
|
+
|
|
486
|
+
- Material instance authoring. Parameter writes go through `UMaterialEditingLibrary`, which also recompiles the instance's shader map — writing the override arrays by hand leaves the instance rendering with its old values
|
|
487
|
+
- `list_material_params` reports `overridden` per parameter, which is the difference between a value the instance sets and one it inherits from its parent. A caller that cannot see that difference cannot tell a deliberate override from a default
|
|
488
|
+
- `set_material_params` refuses a base material and says to make an instance first. Parameters on a base material belong to its graph, and writing them there changes every instance at once
|
|
489
|
+
- A parameter name is checked against the ones the material declares, and a wrong one is answered with the names it does expose. The engine's own `Set*ParameterValue` helpers always report failure, so their answer cannot be the test
|
|
490
|
+
- `assign_material` with no `componentName` writes to the actor's **root** mesh component, and refuses rather than guessing where the root is not a mesh and several mesh components are below it
|
|
491
|
+
- `assign_material` targets either an actor component or a mesh asset. A slot name that does not exist is answered with the slot names that do, rather than with a silent no-op on an out-of-range index
|
|
492
|
+
|
|
493
|
+
### `create_post_process_volume` / `set_post_process_settings` / `add_post_process_material`
|
|
494
|
+
|
|
495
|
+
- Post process authoring. Every setting in `FPostProcessSettings` is ignored unless its sibling `bOverride_<Name>` bool is true, so each write sets both and reports the override flags it turned on in `overridesSet`
|
|
496
|
+
- The same tool writes a volume's settings or a camera component's, because the settings struct is the same one; only the property prefix differs
|
|
497
|
+
- `add_post_process_material` verifies the material's domain is Post Process and **refuses a blendable-location mismatch rather than changing the material**: the blendable location lives on the material asset, so silently rewriting it would change every volume already using it. The location it compares against is read through the material interface, so a material instance that overrides its parent's location is judged on the one it actually renders at
|
|
498
|
+
- A bounded volume is given a cube brush sized by `extent`, because `AddActor` alone spawns the actor and no geometry: without a brush the volume encompasses nothing and affects no view. Every axis has to be positive and defaults to 200: the engine's cube builder refuses a non-positive dimension and returns nothing a caller can see, so the volume would come back shapeless under a response claiming it was applied
|
|
499
|
+
|
|
500
|
+
### `create_input_action` / `create_input_mapping_context` / `add_input_mapping`
|
|
501
|
+
|
|
502
|
+
- Enhanced Input authoring. An action's value type decides what triggers and modifiers make sense on it, so it is required rather than defaulted
|
|
503
|
+
- A key name is validated against the engine's registered key list, and an unknown one is answered with the closest matches rather than with a mapping that never fires
|
|
504
|
+
- Triggers and modifiers are instanced objects configured by class path plus params, which is the same shape the Enhanced Input details panel writes. A stack the engine refuses removes the mapping again rather than leaving a half-configured one
|
|
505
|
+
|
|
506
|
+
### `create_gameplay_effect` / `set_effect_modifiers` / `create_gameplay_cue`
|
|
507
|
+
|
|
508
|
+
- Gameplay Ability System effects, authored as **Blueprint classes** the way the content browser creates them, so they are editable afterwards by a person
|
|
509
|
+
- Effect tags go on the engine's tag components (`UAssetTagsGameplayEffectComponent`, `UTargetTagsGameplayEffectComponent`) rather than on the deprecated inline containers, which are ignored at runtime on every engine this plugin supports
|
|
510
|
+
- A tag that is not registered is refused with the tool that registers it (`create_gameplay_tag`) named, because an unregistered tag on an effect is silently inert
|
|
511
|
+
- `set_effect_modifiers` names attributes as `Set.Attribute`, and a modifier op maps onto the engine's own `EGameplayModOp` — `multiply` is `MultiplyAdditive`, which is what the effect editor means by it
|
|
512
|
+
|
|
513
|
+
### `create_attribute_set` / `create_gameplay_ability`
|
|
514
|
+
|
|
515
|
+
- `create_attribute_set` writes C++, because an attribute set has to be a native class: the accessor macros and the replication callbacks have no Blueprint equivalent. It writes a header and a source file, refuses to overwrite either, and reports `trigger_live_compile` as the tool that makes them real
|
|
516
|
+
- The generated class carries the target module's `_API` macro, without which another module that references the attribute accessors links against nothing. Its header includes `AbilitySystemComponent.h`, so a module whose `Build.cs` does not already depend on `GameplayAbilities` is told to add it — the compile fails on the first include otherwise, and a retry is refused because the generated files are already on disk
|
|
517
|
+
- A `className` that already names a loaded class is refused up front, for the same reason: the build would fail on a duplicate and leave the files behind
|
|
518
|
+
- `create_gameplay_ability` writes a Blueprint class under `UGameplayAbility` and configures its policies, tags and cost/cooldown effects through reflection. Those members are protected on the engine class, and reflection reaches them without this plugin splitting on engine version
|
|
519
|
+
|
|
520
|
+
### `create_behavior_tree` / `add_bt_node` / `add_bt_decorator` / `add_bt_service`
|
|
521
|
+
|
|
522
|
+
- Behaviour tree authoring. A behaviour tree's runtime is **generated from its editor graph**, so authoring one means authoring the graph — writing the runtime nodes directly produces a tree the editor immediately overwrites
|
|
523
|
+
- Child order is positional in the graph, so `childIndex` becomes a node position and the graph's own child ordering is rebuilt from it. That is the same thing dragging a node left or right in the editor does
|
|
524
|
+
- Decorators and services are subnodes of the node they guard, not siblings. `inverse` on a decorator sets `bInverseCondition`, which is the editor's "Not" checkbox
|
|
525
|
+
- Every successful batch ends with the graph regenerating the runtime tree, reported as `runtimeTreeRebuilt`, because a tree whose graph and runtime disagree runs the old behaviour
|
|
526
|
+
|
|
527
|
+
### `create_montage` / `set_montage_sections` / `add_anim_notify`
|
|
528
|
+
|
|
529
|
+
- Montage and notify authoring. A montage slot the skeleton does not declare is refused up front: the montage would be created, look correct in the editor and play nothing
|
|
530
|
+
- `set_montage_sections` refuses a section past the end of the montage, and reports `sectionCount` afterwards, because a section that never plays is indistinguishable from one that does until something tries to trigger it. A name the montage already has is refused too, because a jump to a name resolves to the first match and a second one would be unreachable
|
|
531
|
+
- Sections are sorted by time and given a section at 0 once written, the way Persona does after any section edit: the engine's own position lookups walk the array assuming ascending time
|
|
532
|
+
- `add_anim_notify` creates the notify track if it is missing and reports which tracks it created. A notify object, a notify state with a duration, and a bare named notify are all supported, because the three reach a graph in different ways
|
|
533
|
+
- Each notify is stamped with the trigger-time offset and a GUID the same way the engine's own notify paths are, because the offset decides which side of a frame boundary a notify at 0 or at play length fires on and the notify panel matches events by GUID
|
|
534
|
+
|
|
535
|
+
### `create_blend_space` / `set_blend_space_samples`
|
|
536
|
+
|
|
537
|
+
- Blend space authoring, one or two dimensional. The axis ranges are written through the asset's reflected `BlendParameters`, which is the only route the engine leaves open
|
|
538
|
+
- A sample outside an axis range, or one whose coordinates do not match the asset's dimensionality, is refused **before** the asset sees it: `UBlendSpace::AddSample` widens the axis to fit a sample before it validates one, which would quietly undo the ranges `create_blend_space` set
|
|
539
|
+
- A sample the asset refuses — a duplicate position, a skeleton or additive mismatch — is reported in `validationIssues` **with its coordinates**, because the coordinate is what has to change for the sample to land
|
|
540
|
+
- Every accepted batch re-runs the asset's triangulation, which is what the runtime samples: without it the samples are saved and `GetSamplesFromBlendInput` finds nothing until someone opens the asset
|
|
541
|
+
|
|
542
|
+
### `create_anim_blueprint` / `add_anim_state_machine` / `add_anim_state` / `add_anim_transition`
|
|
543
|
+
|
|
544
|
+
- Animation Blueprint authoring. A state machine is an editor graph like any other, so these tools place graph nodes and let the Blueprint compiler turn them into something that runs
|
|
545
|
+
- `add_anim_state_machine` renames the nested graph to the caller's machine name and reports it, because that name is what `add_anim_state` and `add_anim_transition` address
|
|
546
|
+
- A state with an `animationPath` gets a sequence player, or a blend space player where the path names a blend space, wired to its result pose; a state without one is left empty for the graph tools to fill
|
|
547
|
+
- The machine node is wired into the AnimGraph's output pose and the first state added becomes the machine's entry state, because a state machine that reaches neither compiles to the reference pose
|
|
548
|
+
- A transition with rule fields gets the comparison generated into its rule graph — a variable get, the matching Kismet comparison and the constant on its other pin, driving `bCanEnterTransition`. The comparison is chosen for the variable's own type, so an integer is not compared through the float overload. A transition with no rule has an empty rule graph, which never fires, and the response says so
|
|
549
|
+
|
|
550
|
+
### `create_ik_rig` / `create_ik_retargeter`
|
|
551
|
+
|
|
552
|
+
- IK rig and retargeter authoring, both through the engine's controllers so the assets are the same ones the IK editors produce
|
|
553
|
+
- A retarget chain whose bones are not on the mesh, or whose start bone is not an ancestor of its end bone, is refused with that rule stated rather than accepted and then ignored — the rig itself only checks that the two bones exist
|
|
554
|
+
- A chain name the rig already has is refused rather than silently renamed, because retargeting pairs chains by name and a renamed chain never pairs
|
|
555
|
+
- A chain's `goalName` creates a real IK goal on its end bone and connects it to the solver, since the chain field only records a name and nothing would otherwise exist for a solver to reach for
|
|
556
|
+
- `create_ik_retargeter` seeds the retargeter's op stack the way the engine's own factory does — both rigs first, then the default ops, because an op reads the rigs when it is added and assigning one afterwards does not revisit it. On 5.6+ the chain mappings live on those ops, and without them every mapping is refused. The mapping report is read back from the retargeter, so chains it auto-mapped are listed as mapped
|
|
557
|
+
- A mapping's `sourceChain` is checked against the source rig's own chains. The retargeter validates only the target side, so a misspelled source name is stored, echoed back as mapped, and leaves that limb in its reference pose
|
|
558
|
+
- `create_ik_retargeter` reports `unmappedSourceChains` and `unmappedTargetChains`. A chain with nothing mapped to it leaves that limb in its reference pose, which reads as a broken animation rather than an incomplete setup
|
|
559
|
+
|
|
560
|
+
### `create_widget_blueprint` / `add_widget` / `set_widget_slot` / `bind_widget_event`
|
|
561
|
+
|
|
562
|
+
- UMG authoring. A widget's slot type is decided by whichever panel took it, so `add_widget` and `set_widget_slot` **report the slot class** rather than taking it from the caller
|
|
563
|
+
- A name collision is refused rather than renamed: a caller who asked for `HealthBar` and silently got `HealthBar_1` would bind its events to the wrong widget. Anything under the widget tree counts, not just the widgets the designer lists: a discarded widget's move out of the tree is undoable, and an undone one back under the old name would otherwise be hit by the next construction — fatally where the classes differ
|
|
564
|
+
- A widget whose properties were refused is taken back out of the tree **and renamed into the transient package**, the way the designer's own delete path does: taking it out of its parent alone leaves the name taken under the widget tree, and the next attempt at the same name collides with the orphan
|
|
565
|
+
- `create_widget_blueprint` replaces a root panel the factory built from the project's Default Root Widget setting when it is not the `rootPanelClass` that was asked for
|
|
566
|
+
- Every widget is registered in the Blueprint's widget-GUID map, variable or not, because the 5.6+ widget compiler walks all of them and ensures on any that is missing
|
|
567
|
+
- `bind_widget_event` promotes the widget to a variable if it is not one, since a bound event node has nothing to point at otherwise, and reports that as `markedAsVariable`
|
|
568
|
+
- It spawns the event node itself rather than through the engine's bind helper, whose last act is to bring the Blueprint editor to focus: that would open the widget editor and build its designer preview inside the request, and steal the person's focus while it did it
|
|
569
|
+
|
|
570
|
+
### `render_sequence` / `get_render_job_status`
|
|
571
|
+
|
|
572
|
+
- Movie Render Queue rendering. A render takes minutes, so `render_sequence` **accepts the job and returns an id** rather than holding the bridge connection open, and `get_render_job_status` is where the outcome shows up
|
|
573
|
+
- A second render is refused while an executor exists, not merely while one reports rendering: the PIE executor only raises that flag once PIE has finished starting, and a second accept inside that window would delete the queue the first one has not read yet
|
|
574
|
+
- The editor's own Movie Render Queue is the one the MRQ window shows, so whatever a person left in it is copied aside before this job replaces it and put back when the render ends. "When it ends" means when the executor actually goes idle, not when it first reports finished: a failed pipeline raises that same event mid-render and the render keeps reading the queue afterwards
|
|
575
|
+
- `headless: true` renders in a separate process so the editor stays usable; otherwise the render runs through PIE in this editor, which is what the Movie Render Queue window does. A headless render with unsaved packages is refused up front, because the new-process executor asks to save first and that prompt would block the request
|
|
576
|
+
- `endFrame` is **exclusive**, which is how the Movie Render Queue builds its playback range: 0 to 100 renders frames 0 through 99
|
|
577
|
+
- EXR and ProRes output are resolved at runtime and their absence is reported, because ProRes ships in its own optional plugin
|
|
578
|
+
- Status reports the files **actually written under the output directory since the job started**, which is the only per-frame progress the pipeline exposes without owning the render. The list is capped at 50 paths while `writtenFileCount` stays the real total, because an image sequence writes one file per frame
|
|
579
|
+
|
|
580
|
+
### `spawn_niagara_system` / `set_niagara_params`
|
|
581
|
+
|
|
582
|
+
- Niagara placement and its user-exposed parameters. Placing into the level spawns a Niagara actor; attaching adds an instanced component to an existing actor, which is what survives a level save
|
|
583
|
+
- A socket the actor's root component does not have is refused before the component exists, because attaching to a missing socket silently places the effect at the component origin
|
|
584
|
+
- `set_niagara_params` reports **every user parameter the system has**. Niagara stores an override for a name the system does not declare and nothing ever reads it, so a misspelled parameter has to be refused here to be visible at all — and so does a `paramKind` that does not match the parameter's declared type, because Niagara resolves a user parameter by name and type together
|
|
585
|
+
- `object` writes go through the setter for the parameter's **declared** type — texture, render target, material, static mesh or plain object — since each setter builds its own typed variable and the wrong one lands an override the system never looks up. A data interface parameter is refused: it is configured on the system rather than assigned an asset
|
|
586
|
+
|
|
587
|
+
### `create_pcg_graph` / `run_pcg_generate`
|
|
588
|
+
|
|
589
|
+
- PCG graph authoring and generation. Nodes are addressed by caller-supplied ids so connections can name them before the graph exists, and `input` / `output` name the graph's own nodes
|
|
590
|
+
- An omitted pin name takes the default of the node it is on, not a fixed 'Out'/'In'. The graph's own Input and Output nodes carry the labels of the side they face inwards from — the Input node's only output pin is `In` and the Output node's only input pin is `Out` — so a fixed default would make the documented sampler wiring unreachable
|
|
591
|
+
- A connection the graph refuses is answered with the pins each node actually has, rather than with a graph that is missing an edge
|
|
592
|
+
- A graph whose nodes or edges were refused is taken back out, because a partially connected PCG graph runs as something other than what was asked for
|
|
593
|
+
- `run_pcg_generate` drives the PCG subsystem for up to `waitMs`, since a PCG graph executes across editor frames. That wait happens inside the blocking game-thread task the bridge abandons after 5 s, so `waitMs` is bounded at 3000: a longer wait would lose the response and leave the editor frozen for the remainder. `timedOut` says the counts are a snapshot; the generation keeps running in the editor either way
|
|
594
|
+
- `generatedActorCount` and `generatedInstanceCount` are reported because a caller that saw only `applied` with an empty-looking level would read a working graph as a failure
|
|
595
|
+
|
|
596
|
+
### `set_project_settings` / `set_default_gamemode`
|
|
597
|
+
|
|
598
|
+
- Project settings writes. Settings live on settings objects rather than in the config files, so every write goes through the settings object and is saved to whichever file that object declares — which is the part a raw ini edit gets wrong
|
|
599
|
+
- Which file that is comes from the settings class's own config flags, the way the editor's Settings panel picks it, and `configFilePath` reports the one actually used. A section that declares itself local to the project user, such as Rendering Overrides (Local), belongs in `Config/UserEngine.ini`: written into `DefaultEngine.ini` instead, the user layer loads after it and the change is silently gone on the next start
|
|
600
|
+
- The sections come from the engine's own settings registry rather than from a scan of `UDeveloperSettings` subclasses, because the core pages — Maps & Modes, Description, Input — are plain config objects that a class scan cannot see
|
|
601
|
+
- Only the **Project** container is writable. The Editor container holds a person's own preferences, which a tool has no business changing on their behalf
|
|
602
|
+
- Omitting `sectionName` lists the writable sections; omitting `properties` reports one section's current values. That is how a caller finds a property name instead of guessing an ini key
|
|
603
|
+
- `restartProperties` names the settings the engine reads once at startup. They are written correctly and still inert until the editor restarts, which is worth saying rather than leaving the caller to wonder
|
|
604
|
+
- `set_default_gamemode` writes the project default through `GameMapsSettings`, or a level override through that level's world settings. The pawn, controller, state and HUD classes are not settings — they live on the game mode class — so they are written onto its defaults and the Blueprint is recompiled. A **C++ game mode refuses them**: its class defaults are rebuilt from its constructor on every start, so the write would live only until the editor closed
|
|
605
|
+
|
|
361
606
|
## MCP Resources
|
|
362
607
|
|
|
363
608
|
Resources carry context a client can attach without spending a tool call and a model turn. Every one of them is served from in-memory state or the local filesystem: **a resource read never opens a bridge socket and never waits on the editor**, so an unreachable or absent editor produces a structured payload rather than a timeout.
|