Styling
first_graph drew bare boxes. The editor’s look is layered, and each layer is independent — reach for the smallest one that does the job: a canvas-wide theme, per-node tints, scoped style var / color brackets for one-off nodes, pin pivots that move the link-attach point onto the node edge, and a background draw list for custom art.
apply_daslang_node_editor_style(g_ed) // canvas theme (warm-dark + amber)
node(1, (color = float4(0.15, 0.35, 0.18, 0.78))) { // per-node background tint
text("Source")
pin(12, (kind = PinKind.Output, pivot_alignment = float2(1.0, 0.5))) { text("out ->") }
}
with_style_var(imgui_node_editor::StyleVar.NodeRounding, 10.0) { // scoped VAR
with_style_color(imgui_node_editor::StyleColor.NodeBorder, amber) { // scoped COLOR
node(3, (color = red)) { ... }
}
}
with_node_background_drawlist(3) $(var dl) { // custom art
let p = imgui_node_editor::GetNodePosition(3)
let s = imgui_node_editor::GetNodeSize(3)
dl |> add_rect_filled(p, float2(p.x + 5.0, p.y + s.y), rgba(255u, 90u, 90u, 220u))
}
Source: examples/tutorial/styling.das.
Walkthrough
1options gen2
2
3require imgui/imgui_harness
4require imgui/imgui_node_editor_boost_v2
5require imgui/imgui_node_editor_live
6require imgui/imgui_node_editor_theme_daslang
7
8// =============================================================================
9// TUTORIAL: styling — make nodes look the way you want.
10//
11// apply_daslang_node_editor_style(ed) -- canvas theme (warm-dark + amber)
12// node(id, (color = float4(r,g,b,a))) -- per-node background tint
13// pin(id, (kind=, pivot_alignment=)) -- where the link attaches on the pin
14// with_style_var(StyleVar.NodeRounding, 10) -- scoped style VAR around a node
15// with_style_color(StyleColor.NodeBorder, c) -- scoped style COLOR (composes with the var)
16// with_node_background_drawlist(id) $(var dl) -- raw drawing behind a node
17//
18// first_graph drew bare boxes. The editor's look is layered: a canvas-wide THEME,
19// per-node TINTS (the `color` arg), SCOPED style var/color brackets for one-off
20// nodes, pin PIVOTS that move the link-attach point onto the node edge, and a
21// background DRAW LIST for custom art. Each layer is independent — reach for the
22// smallest one that does the job.
23//
24// STANDALONE: daslang.exe modules/dasImguiNodeEditor/examples/tutorial/styling.das
25// LIVE: daslang-live modules/dasImguiNodeEditor/examples/tutorial/styling.das
26// =============================================================================
27
28var g_ed : imgui_node_editor::EditorContext? = null
29var g_seeded : bool = false
30
31def draw_editor() {
32 node_editor("graph", (editor = g_ed)) {
33 if (!g_seeded) {
34 imgui_node_editor::SetNodePosition(1, float2(80.0, 80.0))
35 imgui_node_editor::SetNodePosition(2, float2(360.0, 120.0))
36 imgui_node_editor::SetNodePosition(3, float2(660.0, 160.0))
37 g_seeded = true
38 }
39 // (1) A plain tint: the `color` arg fills the node background. Green for a source.
40 node(1, (color = float4(0.15, 0.35, 0.18, 0.78))) {
41 text("Source")
42 pin(12, (kind = PinKind.Output, pivot_alignment = float2(1.0, 0.5))) {
43 text("out ->")
44 }
45 }
46 // (2) Default look — no tint, square corners, default border. Inputs attach on
47 // the left edge (pivot x = 0), outputs on the right (x = 1); without a pivot the
48 // link springs from the pin label's center, which looks untidy on a multi-pin node.
49 // Every pin id is unique across the whole editor — 21/22 here, distinct from node 1's
50 // output 12 and node 3's input 31 (same-id pins silently merge into one).
51 node(2) {
52 text("Passthrough")
53 pin(21, (kind = PinKind.Input, pivot_alignment = float2(0.0, 0.5))) {
54 text("-> in")
55 }
56 pin(22, (kind = PinKind.Output, pivot_alignment = float2(1.0, 0.5))) {
57 text("out ->")
58 }
59 }
60 // (3) The showcase node: a red tint, PLUS scoped style brackets — rounded
61 // corners (a style VAR) and an amber border (a style COLOR). The two wrappers
62 // compose; each restores its previous value when the block ends.
63 with_style_var(imgui_node_editor::StyleVar.NodeRounding, 10.0) {
64 with_style_color(imgui_node_editor::StyleColor.NodeBorder, float4(0.910, 0.631, 0.227, 1.0)) {
65 node(3, (color = float4(0.40, 0.18, 0.18, 0.78))) {
66 text("Output")
67 pin(31, (kind = PinKind.Input, pivot_alignment = float2(0.0, 0.5))) {
68 text("-> in")
69 }
70 }
71 }
72 }
73 // A custom accent stripe down node 3's left edge. The node's draw channels only
74 // exist once it is fully built, so this runs AFTER the node block, reading the
75 // editor-owned geometry back (GetNodePosition / GetNodeSize).
76 with_node_background_drawlist(3) $(var dl) {
77 let p = imgui_node_editor::GetNodePosition(3)
78 let s = imgui_node_editor::GetNodeSize(3)
79 dl |> add_rect_filled(p, float2(p.x + 5.0, p.y + s.y), rgba(255u, 90u, 90u, 220u))
80 }
81 link(100, 12, 31)
82 }
83}
84
85[export]
86def init() {
87 harness_init("Styling", 1000, 600)
88 g_ed = create_node_editor()
89 apply_daslang_node_editor_style(g_ed) // warm-dark canvas + amber grid to match daslang's ImGui theme
90}
91
92[export]
93def update() {
94 if (!harness_begin_frame()) return
95 harness_new_frame()
96 let io & = unsafe(GetIO())
97 SetNextWindowPos(float2(0.0, 0.0), ImGuiCond.Always)
98 SetNextWindowSize(io.DisplaySize, ImGuiCond.Always)
99 let flags = (ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize |
100 ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar |
101 ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoSavedSettings |
102 ImGuiWindowFlags.NoBringToFrontOnFocus)
103 window(MAIN_WIN, (text = "Styling", closable = false, flags = flags)) {
104 draw_editor()
105 }
106 harness_end_frame()
107}
108
109[export]
110def shutdown() {
111 destroy_node_editor(g_ed)
112 harness_shutdown()
113}
114
115[export]
116def main() {
117 init()
118 while (!exit_requested()) {
119 update()
120 }
121 shutdown()
122}
Canvas theme
apply_daslang_node_editor_style(ed) (from imgui/imgui_node_editor_theme_daslang)
sets the canvas background, grid, and link colors to the warm-dark + amber palette that
matches daslang’s ImGui theme. It is one call at init and affects the whole editor —
the broadest styling layer.
Per-node tint
The color tuple arg on node(id, (color = float4(r, g, b, a))) fills that one node’s
background. Node 1 is green (a source), node 3 red (an output); node 2 passes no color
and keeps the editor default. This is the cheapest per-node knob — no scope, no restore.
Scoped style var + color
For properties that aren’t a node arg — corner rounding, border color — wrap the node in a
scoped bracket. with_style_var(StyleVar.NodeRounding, 10.0) rounds the corners;
with_style_color(StyleColor.NodeBorder, amber) recolors the border. They compose
(nest one inside the other), and each restores the previous value when its block ends, so
only the node inside is affected.
Pin pivots
pivot_alignment on a pin moves the point where links attach. float2(0.0, 0.5) is
the pin’s left edge (use it for inputs), float2(1.0, 0.5) the right edge (outputs).
Without a pivot the link springs from the pin label’s center, which looks untidy once a
node has several pins. (pivot_size and pivot_scale are the other two knobs — see
shader_graph.das.)
Background draw list
with_node_background_drawlist(id) $(var dl) { ... } hands you a draw list behind the
node for custom art — here a red accent stripe down node 3’s left edge. The node’s draw
channels only exist once it is fully built, so this runs after the node block,
reading the editor-owned geometry back with GetNodePosition / GetNodeSize.