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