How-To: Use Your Own Node Widget Class
Goal (optional): build skill tree nodes on your widget base class - your project's button base, a CommonUI button, anything - instead of subclassing this plugin's UCrimsonSkillTreeWidget_Node. You keep whatever your base already gives you (focus handling, styling, pooling, analytics) and lose nothing from the skill tree.
UCrimsonSkillTreeWidget_Node is a perfectly good default and is what Quick Start does - it already implements everything below. Come here only when you want your nodes to inherit from something else.1. Implement the contract
A node is anything that is a UUserWidget and implements `ICrimsonSkillTreeNodeWidget`. That is the whole requirement - there is no base class to inherit and no registration step.
| Function | You must | What it is for |
|---|---|---|
InitializeSkillNode(Node) | Implement it | The host hands you the data node once, right after spawn. Store it, bind OnNodeStateChanged to stay reactive, and paint the initial look. |
GetSkillNodeConnectionAnchorInset() | Only if your shape does not fill its slot | Inset from the slot rect to the visible shape, so connection lines meet the shape edge instead of the padding. Defaults to zero. |
InitializeSkillNode and nothing else.In your Widget Blueprint: Class Settings -> Interfaces -> Add -> Crimson Skill Tree Node Widget. Initialize Skill Node then appears in the My Blueprint panel under Interfaces - double-click to implement it.
- In Initialize Skill Node, promote the
In Node Datapin to a variable (e.g.SkillNodeData). - From that variable, Bind Event to On Node State Changed and route it to a custom event that repaints your visuals.
- Call that repaint event once immediately, so the node starts in the right state instead of waiting for the first change.
- To act on the node, call Request Skill Node Action (from
Crimson Skill Tree UI Statics) with your stored node and an action type.
2. Assign it
Nothing changes here - your class appears wherever a node widget class is picked, because those pickers filter by the interface, not by a base class. Precedence is per-node override, then node-type tag map, then the asset default.
| Where | Effect |
|---|---|
GraphConfig.DefaultNodeWidgetClass | Every node in the tree |
GraphConfig.NodeTypeToWidgetClassMap | Every node carrying a given NodeTypeTag |
| A Visual node's Preview Widget Class | That one node only |
3. Set the anchor inset as a class default
If your node's visible shape is smaller than its slot - a hexagon or a circle inside padding - set ConnectionAnchorInset so lines meet the shape. It must be a class default (EditDefaultsOnly), because the Visual Graph reads it off the Class Default Object to draw editor-side connections. A value that depends on per-instance runtime state will make the editor and the game disagree about where lines attach.
4. What you take over
The convenience base does a few extra things for free. On your own base you own them - each is a few lines, and none is required for the tree to work.
| Behaviour | On your own widget |
|---|---|
| Reactivity | You bind OnNodeStateChanged yourself (step 1) |
| Tooltips | Spawn whatever tooltip you like on hover - there is no required tooltip type |
| Hover visuals | NativeOnMouseEnter / NativeOnMouseLeave, or your base's own hover/focus hooks |
| Requesting actions | UCrimsonSkillTreeUIStatics::RequestSkillNodeAction |
Worked example
UCrimsonCoreSkillTreeNodeButton (in the CrimsonCore plugin) is exactly this pattern: it derives from UCrimsonButtonBase rather than from any CrimsonSkillTree class, and gets gamepad focus, navigation and per-input-method styling from that base - none of which the plugin's own node base provides. It reports selection and activation outward and lets the owning screen decide what a press means, which is the recommended split.
RequestSkillNodeAction directly from the widget. Which action a press maps to - activate, increment, refund - is a game rule that depends on the node's current state, and keeping it in one place stops the mouse and gamepad paths from drifting apart.See also: How-To: Display the Skill Tree (hosting the graph and wiring input), How-To: Drive Node Actions (what the manager does with a request), and the API Reference entry for ICrimsonSkillTreeNodeWidget.