Fab packages and separate plugins

Pulse Foundation comes into a project in one of two ways. Both run the same code; they differ in where the plugins come from and how they are updated.

Way Comes from Pulse Foundation Updates
Fab package Fab, installed with the Epic Games Launcher Inside the package of the Pulse plugin, with renamed modules (PulseSkill_PulseFoundation, …) and its content under /PulseSkill/Foundation Through Fab; every update brings its own Pulse Foundation
Separate plugins Pulse HUB (or a Git checkout) Its own plugin PulseFoundation next to the Pulse plugins In the editor with Pulse HUB

Use one way per project, never both.

Fab packages

Fab builds every plugin on its own, so a Pulse plugin on Fab carries its own copy of Pulse Foundation. The package builder renames the modules of that copy (prefix <Plugin>_), moves its content to /<Plugin>/Foundation and writes PulseBundle.json into the root of the package.

Everything keeps its usual names:

  • Assets and Blueprints that refer to /Script/PulseFoundation... classes or /PulseFoundation/... assets load through redirects in the package config (Config/Default<Plugin>.ini).
  • C++: includes and types stay the same, but a module that uses Pulse Foundation names the renamed modules in its Build.cs, for example PulseSkill_PulseFoundation and PulseSkill_PulseFoundationUI instead of PulseFoundation and PulseFoundationUI. The linker needs these direct dependencies; a public dependency of PulseSkill only passes on the include paths. When a project switches to separate plugins, Pulse HUB changes the names back.
  • Project settings of Pulse Foundation are stored under the renamed module, for example [/Script/PulseSkill_PulseFoundationUI.PulseUISettings] instead of [/Script/PulseFoundationUI.PulseUISettings]. Project Settings writes the right section. When a project switches to separate plugins, Pulse HUB rewrites these sections.

Only one copy per project

A project can use the Fab package of one Pulse plugin. The Fab packages of two Pulse plugins bring two copies of Pulse Foundation, and only one copy can run:

  • C++ projects stop the build with a message that names both copies, before the compiler runs.
  • The editor (Blueprint projects, prebuilt binaries) starts. The first copy is active: the separate plugin if it is there, otherwise the package of the plugin that comes first by name. The other copies register nothing global: no settings pages, tabs, menus, console commands, cheats or gameplay debugger categories. A notice and the log (LogPulseFoundation) name the copies. The plugin that brought an inactive copy does not work properly.

To fix it, disable all but one of the packages in Edit > Plugins, or switch to separate plugins with Pulse HUB: it reports your Fab purchases from the Epic Games Launcher, and once they are confirmed it installs the separate plugins in the same versions.

Switching to separate plugins

Assets saved while a Fab package was in use keep working after the switch. The separate Pulse Foundation redirects the names of every Pulse Fab package back to its own (DefaultPulseFoundation.ini, block between luq-bundle-exclude-begin and luq-bundle-exclude-end):

  • /Script/PulseSkill_PulseFoundationUI and the other renamed modules to /Script/PulseFoundationUI and so on;
  • /PulseSkill/Foundation/... to /PulseFoundation/....

The package builder removes this block from Fab packages.

Suggestion of Pulse HUB

When a Pulse plugin came as a Fab package and Pulse HUB is not enabled, the editor suggests Pulse HUB a few seconds after it starts: updates in the editor, extras like bridges and MCP tools, and several Pulse plugins in one project. The notice has three buttons:

  • Get Pulse HUB opens the page of Pulse HUB (free).
  • Learn More opens this page.
  • Don’t Show Again turns the notice off.

You can also turn it off in Editor Preferences > Pulse > Foundation > Workflow > Suggest Pulse HUB at Startup (per user). The notice does not show in commandlets, unattended runs, automation tests or while playing, and not when Pulse HUB is enabled. When several copies of Pulse Foundation are enabled, the conflict notice shows instead.

For plugin code

Distribution/PulseDistribution.h (namespace Pulse::Foundation) tells which copy the code runs in:

Function Returns
GetHostPluginName() PulseFoundation, or the plugin of the Fab package, e.g. PulseSkill
GetModuleName(), GetModulePrefix() PulseFoundation and an empty prefix, or PulseSkill_PulseFoundation and PulseSkill_
IsBundled() True inside a Fab package
GetContentRoot(), MakeContentPath(Path) /PulseFoundation, or /PulseSkill/Foundation; the full path of a Pulse Foundation asset
GetEnabledCopies(), IsActiveCopy(), HasCopyConflict() The copies of Pulse Foundation among the enabled plugins and whether this one runs
  • Build paths of Pulse Foundation assets with MakeContentPath instead of writing /PulseFoundation/....
  • Find the plugin of Pulse Foundation with GetHostPluginName() instead of the name PulseFoundation.
  • The module interfaces (IPulseFoundation::Get(), IPulseFoundationEditor::Get(), …) find their module by its real name, so they work in both ways.
  • A new Pulse plugin with a Fab package gets its lines in the reverse redirect block of DefaultPulseFoundation.ini and in the product list of the spec PulseFoundation.Distribution.

PulseFoundation plugin documentation.

This site uses Just the Docs, a documentation theme for Jekyll.