DreamShaderLang
Tooling

Editor Tools

Every menu entry, toolbar button and context-menu action DreamShader registers, and the Material Content Browser tab in full.

Everything DreamShader adds to the Unreal editor lives in one editor-only module. This page is the map: what appears where, what each command actually does, and how the Material Content Browser tab works.

AspectValue
Implemented inthe DreamShaderEditor module, type Editor, loading phase Default
Registered byUToolMenus::RegisterStartupCallback at module startup
ToolMenu ownersDreamShaderEditor (bridge entries) · DreamShaderMaterialBrowser (browser entries)
Suppressed bythe -NoDreamShaderEditorBridge switch, and every commandlet run
Log categoryLogDreamShader

None of it exists in a packaged game — the module is editor-only, and the runtime DreamShader module carries no UI at all. Menu registration is idempotent, so a second registration pass adds nothing, and it is skipped entirely while the editor is shutting down.

What starts, and in what order

#StepSkipped when
1Running a commandlet: install the cook hook when -run= contains Cook and -cookworker is absent, then stop
2Bail out entirely-NoDreamShaderEditorBridge is on the command line
3Create and start the editor bridgeas above
4Register the Material Content Browser nomad tab and its menu entriesas above

The bridge's own startup then resets bridge.db, exports the three manifests, runs the VirtualFunction sync, queues a full scan, opens the preview WebSocket server on port 17864, registers the source-directory watcher, and installs the menus.

Tools menu

Tools ▸ DreamShader, extending LevelEditor.MainMenu.Tools, section DreamShader.

LabelTooltipIconEffect
Recompile DSM"Recompile all DreamShader .dsm and .dsf source files and refresh diagnostics."Icons.RefreshRebuilds the dependency graph and queues every project .dsm and .dsfbelow
Clean Generated Shaders"Delete Intermediate/DreamShader/GeneratedShaders and queue a full DreamShader recompile."Icons.DeleteDeletes every generated *.ush, then queues a full scan — below
Clean Persisted Generated Assets"Delete DreamShader-generated material assets that are saved on disk (they shadow in-memory material mode). Shows a confirmation with the full list; source files are untouched and regenerate in memory."Icons.DeleteDeletes on-disk assets carrying DreamShader provenance — below
Show In-Memory Materials"Show memory-only DreamShader materials in the Content Browser and asset pickers — needed when picking one as a material instance Parent or referencing it from a detail panel. While shown, an explicit Save on one would persist it to disk (the shadow warning and Clean command cover recovery)."(none)Toggle button over bShowInMemoryMaterialsInContentBrowserbelow
Open Dream Shader Workspace (VSCode) since 1.2.1"Open the configured DreamShader source workspace in VSCode, or Notepad if VSCode is unavailable."Icons.OpenInExternalEditorRe-exports the three manifests, rewrites the workspace file, launches it — VSCode and Rider
Material Content Browser since 1.5.0"Open the DreamShader Material Content Browser."ClassIcon.MaterialInvokes the DreamShaderMaterialBrowser nomad tab — below

The first five entries and the sixth are registered by two different startup callbacks into the same DreamShader section. Their relative order inside the section depends on registration order and is not guaranteed to be stable between editor runs.

Level Editor toolbar

Extending LevelEditor.LevelEditorToolBar.AssetsToolBar, section DreamShader. Two buttons, both duplicates of Tools-menu entries.

LabelTooltipIconEffect
DSM"Recompile all DreamShader .dsm and .dsf source files."Icons.RefreshIdentical to Recompile DSM
Open Dream Shader Workspace (VSCode)"Open the configured DreamShader source workspace in VSCode, or Notepad if VSCode is unavailable."Icons.OpenInExternalEditorIdentical to the Tools-menu entry

Window menu

The Material Content Browser registers a nomad tab, which puts it under Window ▸ Tools as well.

AspectValue
Tab idDreamShaderMaterialBrowser
Display nameMaterial Content Browser
Tooltip"Browse, manage, and create instances of project and DreamShader-generated materials."
IconClassIcon.Material
Workspace groupTools category
Tab roleETabRole::NomadTab

Content Browser context menus

Every entry is added into the stock GetAssetActions section of the per-class asset context menu.

Every DreamShader context-menu entry requires exactly one selected asset. With two or more assets selected the section is empty and nothing explains why. Right-click a single asset.

Asset class extendedWhat appears
UMaterialsubmenu DreamShaderMaterial submenu
UMaterialFunctionsubmenu DreamShaderMaterial Function submenu
UMaterialFunctionMaterialLayerthe same Material Function submenu
UMaterialFunctionMaterialLayerBlendthe same Material Function submenu
UMaterialInstanceConstantflat entry Create DreamShader instance
UDreamShaderMaterialInstanceflat entry Create DreamShader instance

Menu names in Unreal are keyed on the exact class, so the instance entry is registered twice — once for the stock class and once for the DreamShader subclass.

EntryTooltipIconEffect
Create DreamShader instance since 1.5.0"Create a material instance that shares this material's compiled shader map."ClassIcon.MaterialInstanceConstantOpens the Create material instance dialog. The selection must cast to UMaterialInterface

Material submenu

Label DreamShader, tooltip "DreamShader actions for this Material.", icon Icons.Settings. Built only when the single selected asset is a UMaterial. One section, Decompiler:

EntryTooltipIconEffect
Export DSM since 1.3.5"Export this Material graph to a DreamShader .dsm source file."Icons.SaveDecompiles to DShader/Decompiled/Materials/…​.dsm and opens the file — Decompiler

Material Function submenu

Label DreamShader, tooltip "DreamShader actions for this Material Function.", icon Icons.Settings. Two sections.

Decompiler:

EntryTooltipIconEffect
Export DSF since 1.3.5"Export this Material Function graph to a DreamShader .dsf source file."Icons.SaveDecompiles to DShader/Decompiled/{Functions,Layers,LayerBlends}/…​.dsf and opens the file

VirtualFunction since 1.2.1 — its contents depend on whether a VirtualFunction declaration already names this asset. See VirtualFunction tools.

Material Editor toolbar

A dynamic entry in section DreamShader of AssetEditor.MaterialEditor.ToolBar since 1.2.1.

StepBehaviour
1Requires a valid UMaterialEditorMenuContext with a live IMaterialEditor
2Scans the objects being edited and stops at the first UMaterial, or failing that the first UMaterialFunction
3For a UMaterial: a combo button labelled DreamShader whose content is the Material submenu
4For a UMaterialFunction: a combo button labelled DreamShader whose content is the Material Function submenu
5Neither found ⇒ nothing is added to the toolbar

What each command does

Runtime substitutions in quoted messages are written {Placeholder}.

Recompile DSM

Rebuilds the material dependency graph, then stamps every project .dsm and .dsf into the pending queue with the current time. .dsm files under DShader/Packages are excluded; .dsf files there are not — see Packages. The queued files are then compiled by the debounce ticker exactly as if you had saved them.

Log: DreamShader queued a full .dsm/.dsf recompile scan.

Clean Generated Shaders

Deletes the generated .ush includes and queues a full scan.

BehaviourDetail
Safety guardrefuses to run when Generated Shader Directory is not inside the project's Intermediate/ directory
Deletion scopeonly *.ush files, recursively, one at a time. The directory itself is never removed
Flagsmissing files are tolerated; read-only files are deleted anyway
MessageSeverity
DreamShader refused to clean generated shaders: '{Directory}' is not inside the project Intermediate directory. Point DreamShaderSettings.GeneratedShaderDirectory back under Intermediate/ before cleaning.Warning
DreamShader deleted {Count} generated shader file(s) from '{Directory}'.Display
DreamShader cleaned generated shader includes and queued a full .dsm/.dsf recompile scan.Display

Clean Persisted Generated Assets

Finds and deletes DreamShader-generated assets that exist on disk, because a saved asset shadows the memory-only material generated from the same source.

AspectValue
Search scopethe asset registry, package paths /Game, recursive paths, recursive classes
ClassesUMaterial, UMaterialFunction, UDreamShaderMaterialInstance
Gate 1the package must exist on disk
Gate 2the package must carry non-empty DreamShader.SourceFile metadata
Deletionthe standard editor delete flow, with its confirmation dialog and reference check
After deletionevery source file is regenerated in memory immediately, so references resolve without an editor restart

Because the filter is provenance-based, hand-authored materials are never touched — while orphans whose source file was deleted or renamed still qualify.

ToastCause
No persisted DreamShader-generated assets found.nothing matched
Deleted {Deleted} of {Total} persisted generated asset(s).after the delete flow

Show In-Memory Materials

Flips bShowInMemoryMaterialsInContentBrowser and writes it straight to the project's DefaultEngine.ini. It then walks every live UDreamShaderMaterialInstance whose package is newly created and broadcasts asset creation or removal, so tiles appear or disappear immediately rather than at the next re-enumeration.

ToastCondition
Showing {Count} in-memory material(s) in the Content Browser and asset pickers.turned on
Hidden {Count} in-memory material(s) from the Content Browser and asset pickers.turned off

While memory-only materials are shown they also appear in save pickers, and an explicit Save writes one to disk. The saved copy then shadows the in-memory material for that path. Recover with Clean Persisted Generated Assets; use Materialize when you actually want a file.

The Project page of the Material Content Browser carries a checkbox for the same global setting. The checkbox early-outs when the value is unchanged and shows no toast; the menu entry always toasts. The menu entry's check mark is read live from the settings object, so changing the value in Project Settings updates it.

Open Dream Shader Workspace (VSCode)

Re-exports material-expressions.json, settings.json and substrate-builtins.json, rewrites DShader/DreamShader.code-workspace, and then launches it through a three-step fallback chain — VSCode, the OS default editor, Notepad. The discovery order, the exact file contents and the "this file is rewritten from scratch" warning are on VSCode and Rider.

Material Content Browser

A dockable tab with two pages: one for browsing the project's materials and instancing them, one for the DreamShader source files and their generated assets.

AspectValue
Kindnomad tab
PagesProject (index 0, active by default) · Dream Shader Gen (index 1)
Sincesince 1.5.0

Opening it

RoutePath
Tools menuTools ▸ DreamShader ▸ Material Content Browser
Window menuWindow ▸ Tools ▸ Material Content Browser

The tab is registered only when the editor bridge starts, so -NoDreamShaderEditorBridge removes both routes.

The root widget is a header bar of two radio-style check boxes over a widget switcher. Only the checked transition is honoured, so re-clicking the page you are already on does nothing. The two pages keep independent state, and switching refreshes neither.

Project page

A horizontal splitter: the asset picker takes 0.62 of the width, the details panel 0.38.

Asset picker

AspectValue
ClassesUMaterial, UMaterialInstanceConstant
Recursive classesyes — this is what includes UDreamShaderMaterialInstance
Package paths/Game, recursive
Initial viewTile
Selection modesingle
Draggingallowed
Class columnhidden
Engine contentnever force-shown
Path in column viewshown
Double-clickopens the asset in its editor
Empty state"No materials found under /Game."

Header controls

ControlLabelEffect
ButtonCreate instanceOpens the Create material instance dialog for the selected asset. With nothing selected it raises the toast Select a material to create an instance of. and opens no window
Status text(dynamic)Selected: {Asset} when something is selected, otherwise Select a material, then create an instance.
CheckboxShow in-memory materialsWrites bShowInMemoryMaterialsInContentBrowser to DefaultEngine.ini and re-broadcasts asset creation or removal for every newly created in-memory instance

Details panel

Empty state: "Select a material to see its inheritance and settings." The thumbnail is 96×96, drawn from a 16-entry pool refreshed by a 0.05 s timer.

ButtonTooltipVisible when
Create instancealways
Openalways
Materialize"Write this memory-only material (and its base) to disk."only when the selected material is memory-only; collapsed otherwise
Info rowValue
Basethe name of the material's base material, or -
Domainthe base material's material-domain display name
Blend modethe base material's blend-mode display name
Storagememory-only (not saved) or on disk
Sourcethe .dsm path recorded on a UDreamShaderMaterialInstance, or -
SectionContents
Inheritancethe parent chain, root first, built by walking each instance's parent upward. Every row is a clickable link that re-targets the panel. Rows are indented four spaces per level behind a prefix; ancestors are drawn in blue, the selected material in the default foreground
Child instances (N)material instance constants whose parent is the selected material. Empty state: "No loaded child instances."

Child instances scans only instances that are currently loaded in the editor. An instance that exists on disk but has not been loaded does not appear, and the count is not a reference count. Load the asset, or use the Content Browser's Reference Viewer, for the complete picture.

Dream Shader Gen page

A horizontal splitter: the source list takes 0.6 of the width, the preview pane 0.4. Thumbnails come from an 8-entry pool refreshed by a 0.05 s timer.

Header controls and filters

ControlLabel / hintEffect
ButtonRefreshRe-runs the whole refresh pipeline. Tooltip: "Rescan the source directory and recompute status."
ButtonCompile all"Force-recompile every .dsm/.dsf source (in memory)." — see Compile actions
Search boxhint Search sourcesCase-insensitive substring filter matched against the display name only — not the path, not the status
CheckboxErrors onlyKeeps only items with status compile error or unresolved
CheckboxHide functionsDrops every .dsf and .dsh item
Counter{Visible} / {Total}Subdued text at the right of the bar; counts items, so a .dsh header contributes one row

The page lists .dsm, .dsh and .dsf sources found recursively under the configured source directory. Everything under DShader/Packages is excluded — including package headers and function files, which therefore never appear here.

Status values

StatusGlyphLabelMeaning
UpToDate greenup to dateThe generated asset exists and its stored source hash matches the current source
Stale amberstaleThe generated asset exists but its stored hash differs from the current source
NeverCompiled greynot compiledNo object exists at the resolved object path. Detail: No generated asset at {ObjectPath}
Error redcompile errorA compile through this page failed, or diagnostics.json reports an error for this file
Function bluefunction / headerThe item is a .dsf or .dsh. Detail: "Function library / header. Recompiles the materials that import it."
Unresolved redunresolvedThe source could not be read, could not be parsed, or declares no top-level Shader block

Each row draws the status glyph — whose tooltip is the status detail — then the file name, then a subdued sub-label. For .dsf and .dsh items the sub-label reads function · used by {N} material(s).

Refresh pipeline

#Step
1Enumerate .dsm, .dsh and .dsf under the source directory, excluding DShader/Packages, and sort
2Rebuild the material dependency graph to fill each header's and function's dependent count
3Recompute every item's status
4Clear the selection — the list is rebuilt, so the previously selected item no longer exists
5Overlay errors read from diagnostics.json
6Re-apply the search box and the two filter check boxes
7Rebuild the preview pane

Status per item:

#StepFailure
1.dsf / .dsh short-circuitfunction / header
2Resolve the generated asset's object path from Name= and Root=unresolved
3Look the object up without loading itnot compiled
4Load the prepared source, with import directives inlinedunresolved
5Hash the prepared source and compare against the asset's recorded source file and hashmismatch ⇒ stale

Step 2 reads the file and strips every import line before parsing — import lines carry no top-level block and would confuse block detection — then resolves the asset destination as described on Asset Paths.

MessageCause
Failed to read DreamShader source '{File}'.the file could not be read
{File}: {ParserError}the file did not parse
{File}: this file does not define a top-level Shader block.the parse produced no Shader

Because step 3 is a non-loading lookup, a material that exists on disk but has not been loaded in this session reports not compiled until something loads it.

Error overlay

Errors on this page are read straight out of <Project>/Saved/DreamShader/Bridge/diagnostics.json, not from the bridge's in-memory store — the page is deliberately decoupled from the bridge internals.

RuleDetail
Accepted severitiesan empty severity, or error compared case-insensitively
FormattingL{Line}:{Column} {Message} when the line is greater than zero, otherwise just the message
Per fileonly the first accepted diagnostic is kept
Effecta matching item's status is overwritten to compile error

A file with five errors shows one here. The Output Log and the editor extension have the full list; the plugin emits exactly one severity — error — so no warning or hint ever reaches this page.

Compile actions

Both actions generate in memory and force a rebuild, ignoring the source-hash cache.

ActionScopeProgress UIToast
Compile allevery listed item except .dsh headers — .dsf files are includeda modal slow task titled "Compiling all DreamShader sources...", one frame per fileCompiled {Count} source(s), {Failed} failed — success only when {Failed} is 0
Compile (preview pane)the selected itemnoneCompiled {File} / Failed to compile {File}

Headers are skipped by Compile all because their dependents are already in the target set. A failed single compile also logs Material Content Browser compile failed: {Message} at Error level and pins the message onto the item, so the preview pane shows why.

Preview pane

Empty state: "Select a source file to preview its material."

This pane's image is a static asset thumbnail, 160×160, of the already-generated material. It is not the streaming renderer, it does not update while you type, and it has no mesh or camera control. The live preview is the WebSocket surface described under Previews, and it is driven by the editor extension, not by this tab.

The placeholder tile reads "function library" for .dsf / .dsh items and "not compiled yet" otherwise. The material is resolved by loading the object path, and only for non-function items.

ButtonTooltipShown when
Compile"Force-recompile this source (in memory)."always
Create instance"Create a material instance of this material."the item is not a function or header
Open material"Open the generated material asset."the material resolved
Materialize"Write this memory-only material (and its base) to disk."the material resolved and it is memory-only
Open source"Open the .dsm/.dsf in your preferred editor."always

Below the buttons: the file name in large text, the status glyph and label, the absolute source path in small text, used by {N} material(s) for functions and headers, and — only for compile error and unresolved — the error detail in red.

Create instance on an item that was never compiled first force-compiles it and re-resolves the object. If it is still missing, the toast reads Compile {File} first.

Create material instance

Reached from the Project page button, the details panel, the Gen page preview pane, and the Content Browser entry Create DreamShader instance.

AspectValue
Window titleCreate material instance
Size480×240, modal, not resizable through minimize or maximize
FieldKindDefault
Parentread-only textthe parent material's name
Nametext boxMI_<ParentName>, uniquified against existing assets
Foldertext boxthe parent's folder plus the Material Instance Subfolder setting (Instances by default); an empty subfolder puts the instance alongside the parent
Browse...buttonopens a folder picker titled "Choose a destination folder"
Open the instance after creatingcheckboxchecked
Cancel / Createbuttons
GuardError
No parent materialNo parent material was provided.
Empty name or empty folderProvide a name and a destination folder.
The parent is memory-onlyforwards the Materialize error
An asset already exists at the target pathAn asset already exists at {PackageName}.
The package could not be createdFailed to create package {PackageName}.
The object could not be createdFailed to create the material instance object.
The package could not be savedGenerated DreamShader asset '{Path}' could not be saved.
The parent died between opening and confirmingThe parent material is no longer available. — the window closes

On success the toast reads Created {Name} — the asset name from the Name box, not the object path — and the window closes. On failure the error is toasted and the window stays open, so the name or folder can be corrected.

DetailBehaviour
Created classa plain UMaterialInstanceConstant, not a UDreamShaderMaterialInstance
Object flagsRF_Public | RF_Standalone
Parent assignmentset editor-only, followed by a post-edit change and an asset-created broadcast
Save failure rollbackthe half-created object is un-broadcast, stripped of its flags, renamed into the transient package without redirectors, marked as garbage, and the package's dirty flag is cleared — so it cannot survive GC, appear in the Content Browser, be persisted by Save All, or block a same-name retry

Instancing a memory-only parent materializes the parent first, so a child instance never references a transient object.

Materialize

Materialize writes a memory-only material, and the hidden base it wraps, to disk.

RuleDetail
"Memory-only" testthe material's package carries the newly-created package flag
Already on diskreturned unchanged — the action is a no-op
Requirementthe material must be a UDreamShaderMaterialInstance with a recorded source file path
Implementationre-runs generation for that source file with force on and transient off, then reloads the object at the same object path
MessageCause
This material is memory-only and has no DreamShader source file to materialize from.the material is not a DreamShader instance, or records no source path
Failed to materialize the material to disk: {Error}generation failed
Materialized the material but could not reload it at {ObjectPath}.generation succeeded but the object did not reload
Materialized {Name} to disksuccess — the details panel re-targets the persisted asset

The Gen page's Materialize button deliberately re-resolves the material by object path when clicked, rather than holding the pointer captured when the pane was built, so a delete or a garbage collection between build and click cannot crash it. The whole memory-only model is on In-memory Materials.

Previews

Two different renderers exist, and they are easy to confuse.

Gen page thumbnailOne-shot previewStreaming preview
What it isa plain 160×160 engine asset thumbnaila rendered PNG plus preview.jsona live PNG stream over WebSocket
Triggered byselecting an item in the Gen pagea previewMaterial request file, or a WebSocket message with stream falsea previewMaterial WebSocket message with stream true (the default)
Waits for shader compilationn/ayes — which is why it can block the editor brieflyno
Camera controlnonerequest-file path: no. WebSocket path: yesyes, through previewControl
Sincesince 1.5.0since 1.5.0

Only .dsm can be previewed; a .dsf or .dsh is rejected with DreamShader preview only supports .dsm material files: '{File}'. The material is always compiled transiently — a preview never writes an asset.

AspectValue
Endpointws://127.0.0.1:17864, loopback only; a non-loopback client is refused
Sizewidth / height default 512, clamped to [64, 2048]
Frame rateframeRate default 2.0, clamped to [0.25, 60.0]; <= 0 disables streaming
Meshesplane, cube, cylinder, shaderball, and sphere as the silent fallback for anything else
Orbit defaultsyaw -157.5, pitch -11.25 — Unreal's own scene-thumbnail defaults
OutputPNGs under Saved/DreamShader/Bridge/Preview/, plus preview.json

The mesh and the two orbit angles are written onto the material asset's own scene thumbnail info — the same fields the native Material Editor's preview-shape button and drag-to-orbit viewport write. A preview render therefore changes the shape and camera the Content Browser tile and the Material Editor viewport use for that material. An unknown mesh name is accepted silently and renders a sphere; check the mesh echoed back in preview.json to see what was actually used.

There is no pitch clamp on the plugin side — the editor extension clamps to roughly ±89° before sending, and a client that does not will flip the camera over. Motion blur, anti-aliasing and dynamic screen percentage are off, alpha is forced opaque, and a UI-domain material is always drawn on a plane. The client half of this protocol is on VSCode and Rider.

VirtualFunction tools

The actions that generate, open and refresh a VirtualFunction block for an existing UMaterialFunction asset.

AspectValue
Attaches toUMaterialFunction, UMaterialFunctionMaterialLayer, UMaterialFunctionMaterialLayerBlend
Writes<SourceDirectory>/VirtualFunctions/<Name>.dsh, UTF-8 without BOM
Sincesince 1.2.0 the declaration · since 1.2.1 the menu · since 1.2.2 reuse, OpenVirtualFunction and the startup sync

The section is built fresh on every right-click. Before building it, the editor searches every project source file for a VirtualFunction declaration whose resolved asset matches the selection — and the entries you get depend on the answer.

Declaration exists?Entries
yesOpenVirtualFunction — opens the file at the declaration's line and column · Copy Virtual Function Reference — copies a call built from the declared name, not the asset name
noCopyVirtualFunction — copies the whole declaration · CreateVirtualFunction — writes it to a new .dsh and opens it · CopyVirtualFunctionCall — copies a call example

The lookup re-enumerates and re-lexes every .dsm, .dsh and .dsf outside DShader/Packages, from disk, on every right-click of a Material Function asset. The cost scales with the number of project source files and is paid before the menu appears. There is no cache, and no way to disable it short of -NoDreamShaderEditorBridge, which removes the menu entirely.

CreateVirtualFunction on an asset that already has a declaration silently redirects to OpenVirtualFunction. It never writes a duplicate file, and the toast reads Opened VirtualFunction definition: {File}, not a "created" message.

The file name is <sanitized MaterialFunction name>.dsh, or <sanitized name>_<crc32 of the object path>.dsh on collision, with the CRC in eight lowercase hex digits. A .dsh written here is picked up by the source-directory watcher like any other header, so the materials importing it recompile automatically. The generated declaration carries Options.Asset = Path(Game|Engine|Plugins.<Name>, "…") — see Asset References — one Inputs entry per function input, and one Outputs entry per output. Copied call examples always end with OutputIndex=0, even for a single-output function.

The startup sync service

Once per editor session, at bridge startup, DreamShader re-reads every VirtualFunction declaration in the project, rebuilds it from the live asset, and writes the file back when the text changed.

There is no watcher for this. Editing a UMaterialFunction's inputs or outputs does not refresh the declaration, and neither does saving the .dsh. Declarations are re-synchronized only on the next editor start.

AspectBehaviour
Scanned filesevery .dsm, .dsh and .dsf under the source directory, excluding DShader/Packages
Keyword matchingthe bare word VirtualFunction, matched case-sensitively, with identifier-boundary checks
Skipped regionsquoted strings with \ escapes, // line comments and /* */ block comments
Validationeach extracted block is re-parsed and must yield exactly one VirtualFunction whose Options.Asset resolves
Comparisonon normalized text — CRLF and CR become LF, then the whole text is trimmed — so line-ending differences never trigger a rewrite
Write-backthe whole file, UTF-8 without BOM

Sync problems are published as diagnostics with stage virtualFunctionSync, code virtual-function-sync and severity error; the full list is in the diagnostics index. Reporting logs: DreamShader refreshed {Count} VirtualFunction definition(s) in '{File}'. and DreamShader scanned {Scanned} VirtualFunction definition(s), refreshed {Refreshed}, reported {Issues} issue(s).

Bridge artifacts

The editor writes a set of files under <Project>/Saved/DreamShader/Bridge/ for external tooling to read. Three of them are catalogues exported at bridge startup and again on every Open Dream Shader Workspace; the rest are produced as work happens.

ArtifactContents
material-expressions.jsonthe reflected UMaterialExpression catalogue — schema DreamShader.MaterialExpressions, version 1, one entry per class with className, pathName, defaultOutputType, properties[], inputs[] and outputs[]. This is what powers UE.Expression completion since 1.2.10
substrate-builtins.jsonthe Substrate.* catalogue — schema DreamShader.SubstrateBuiltins, version 1, with qualifiedName, className, outputType, isSubstrateOutput, curated parameters[] and a snippet. Below UE 5.4 it carries an empty array, "supported": false and "unsupportedReason"
settings.jsonthe ShadingModel / BlendMode / MaterialDomain alias tables — schema DreamShader.Settings, version 1. See Enum Values
diagnostics.json, diagnostics/all current diagnostics, aggregated and sharded per file
bridge.dba SQLite mirror of the diagnostics and the three manifests, deleted at startup and shutdown
preview.json, Preview/*.pngone-shot preview results
Requests/*.jsonthe inbound request directory, polled every 0.1 s and deleted on read

Every manifest carries a generatedAt ISO-8601 UTC timestamp. Only diagnostics.json is ever read back by the plugin — the Gen page reads it. The schemas and the request protocol are covered from the consumer's side on VSCode and Rider.

Disabling the integration

UnrealEditor.exe "<Project>.uproject" -NoDreamShaderEditorBridge

The switch is parsed as a bare command-line parameter, so -NoDreamShaderEditorBridge is the only accepted spelling. When present, StartupModule returns before creating anything.

DisabledStill active
The editor bridge — file watcher and auto-compile-on-save, the debounce queue, the diagnostics store and all three sinks, bridge.db, the request-file poller, the VirtualFunction startup sync, the post-engine-init in-memory generation of all sources, the settings watcherThe runtime DreamShader module — parser, generator, settings object, UDreamShaderMaterialInstance
The preview WebSocket server on port 17864, and the whole preview rendererThe commandlet, which never uses the bridge
Every menu, toolbar and context-menu entry on this pageAssets already generated and saved on disk
The Material Content Browser tab registration — the tab cannot be opened at all
The three exported manifests, and DreamShader.code-workspace regeneration

A commandlet run reaches the same state by a different route: the module returns early whenever it detects a commandlet process, installing only the cook-time materialization hook, and only when -run= contains Cook and -cookworker is absent.

Notes

  • Four VirtualFunction entry labels are CamelCase with no spaces — OpenVirtualFunction, CopyVirtualFunction, CreateVirtualFunction, CopyVirtualFunctionCall — while the fifth reads Copy Virtual Function Reference. The inconsistency is in the shipped labels.
  • Toasts raised by the bridge expire after 4 seconds; toasts raised from the Dream Shader Gen page after 3.5 seconds.
  • The editor never writes a per-material .uasset on its own. Persisting happens at cook, through the commandlet, or through an explicit Materialize.
  • Changing Default Compiler Backend in Project Settings regenerates every source file in memory and raises a toast when persisted assets would shadow the result. No other settings property triggers a reaction.

Example

Launch the editor with the integration off, then do the same work headlessly:

# No menus, no watcher, no bridge.
& "$Engine\Binaries\Win64\UnrealEditor.exe" "I:\Project\Project.uproject" -NoDreamShaderEditorBridge

# The commandlet is unaffected by the switch.
& "$Engine\Binaries\Win64\UnrealEditor-Cmd.exe" "I:\Project\Project.uproject" `
    -run=DreamShader compile -All -Force -unattended -nopause -nosplash -stdout -log

Where next

On this page