Skip to content

Commit 2708858

Browse files
refactor(ui): eliminate closure allocations in event callbacks
Replace lambda closures with static lambdas and state parameters to avoid heap allocations in RegisterCallback calls. Updated 6 component files: - JBreadcrumb: static methods with state parameters - JCard: instance methods - JStack: static lambda with tuple state - JToggle: static lambdas with state parameters - JObjectField: instance methods + static lambdas with state - JTextField: static lambdas with state parameters This improves performance by eliminating 14 closure allocations across the UI toolkit components using C#9 static lambda support. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
1 parent 0f001e3 commit 2708858

6 files changed

Lines changed: 87 additions & 72 deletions

File tree

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Form/JObjectField.cs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ public JObjectField(Type objectType, bool allowSceneObjects = true)
7070
_objectField.style.marginBottom = 0;
7171
_objectField.style.height = 22;
7272

73-
_objectField.RegisterCallback<AttachToPanelEvent>(evt =>
74-
{
75-
ApplyInternalStyles();
76-
});
73+
_objectField.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
7774

7875
Add(_objectField);
7976
}
@@ -104,15 +101,15 @@ private void ApplyInternalStyles()
104101
input.style.alignItems = Align.Center;
105102

106103
// Hover effect
107-
input.RegisterCallback<MouseEnterEvent>(e =>
104+
input.RegisterCallback<MouseEnterEvent, VisualElement>(static (_, element) =>
108105
{
109-
input.style.backgroundColor = Tokens.Colors.BgHover;
110-
});
106+
element.style.backgroundColor = Tokens.Colors.BgHover;
107+
}, input);
111108

112-
input.RegisterCallback<MouseLeaveEvent>(e =>
109+
input.RegisterCallback<MouseLeaveEvent, VisualElement>(static (_, element) =>
113110
{
114-
input.style.backgroundColor = Tokens.Colors.BgSurface;
115-
});
111+
element.style.backgroundColor = Tokens.Colors.BgSurface;
112+
}, input);
116113
}
117114

118115
// Style the object display container (icon + label)
@@ -177,6 +174,11 @@ public void RegisterValueChangedCallback(EventCallback<ChangeEvent<Object>> call
177174
{
178175
_objectField.RegisterValueChangedCallback(callback);
179176
}
177+
178+
private void OnAttachToPanel(AttachToPanelEvent evt)
179+
{
180+
ApplyInternalStyles();
181+
}
180182
}
181183

182184
/// <summary>
@@ -215,14 +217,16 @@ public JObjectField(bool allowSceneObjects = true)
215217
_objectField.style.marginBottom = 0;
216218
_objectField.style.height = 22;
217219

218-
_objectField.RegisterCallback<AttachToPanelEvent>(evt =>
219-
{
220-
ApplyInternalStyles();
221-
});
220+
_objectField.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
222221

223222
Add(_objectField);
224223
}
225224

225+
private void OnAttachToPanel(AttachToPanelEvent evt)
226+
{
227+
ApplyInternalStyles();
228+
}
229+
226230
private void ApplyInternalStyles()
227231
{
228232
// Style the input container
@@ -249,15 +253,15 @@ private void ApplyInternalStyles()
249253
input.style.alignItems = Align.Center;
250254

251255
// Hover effect
252-
input.RegisterCallback<MouseEnterEvent>(e =>
256+
input.RegisterCallback<MouseEnterEvent, VisualElement>(static (_, element) =>
253257
{
254-
input.style.backgroundColor = Tokens.Colors.BgHover;
255-
});
258+
element.style.backgroundColor = Tokens.Colors.BgHover;
259+
}, input);
256260

257-
input.RegisterCallback<MouseLeaveEvent>(e =>
261+
input.RegisterCallback<MouseLeaveEvent, VisualElement>(static (_, element) =>
258262
{
259-
input.style.backgroundColor = Tokens.Colors.BgSurface;
260-
});
263+
element.style.backgroundColor = Tokens.Colors.BgSurface;
264+
}, input);
261265
}
262266

263267
// Style the object display container (icon + label)

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Form/JTextField.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ public JTextField(string initialValue = "", string placeholder = "")
6262
style.alignSelf = Align.Center;
6363

6464
// Access the internal input element and style it
65-
_textField.RegisterCallback<AttachToPanelEvent>(evt =>
65+
_textField.RegisterCallback<AttachToPanelEvent, JTextField>(static (_, field) =>
6666
{
67-
ApplyInternalStyles();
68-
});
67+
field.ApplyInternalStyles();
68+
}, this);
6969

7070
// Apply container styles
7171
_textField.style.flexGrow = 1;
@@ -118,21 +118,21 @@ private void ApplyInternalStyles()
118118
textInput.style.fontSize = Tokens.FontSize.Sm;
119119

120120
// Focus state
121-
_textField.RegisterCallback<FocusInEvent>(e =>
121+
_textField.RegisterCallback<FocusInEvent, VisualElement>(static (_, input) =>
122122
{
123-
textInput.style.borderTopColor = Tokens.Colors.BorderFocus;
124-
textInput.style.borderRightColor = Tokens.Colors.BorderFocus;
125-
textInput.style.borderBottomColor = Tokens.Colors.BorderFocus;
126-
textInput.style.borderLeftColor = Tokens.Colors.BorderFocus;
127-
});
123+
input.style.borderTopColor = Tokens.Colors.BorderFocus;
124+
input.style.borderRightColor = Tokens.Colors.BorderFocus;
125+
input.style.borderBottomColor = Tokens.Colors.BorderFocus;
126+
input.style.borderLeftColor = Tokens.Colors.BorderFocus;
127+
}, textInput);
128128

129-
_textField.RegisterCallback<FocusOutEvent>(e =>
129+
_textField.RegisterCallback<FocusOutEvent, VisualElement>(static (_, input) =>
130130
{
131-
textInput.style.borderTopColor = Tokens.Colors.BorderSubtle;
132-
textInput.style.borderRightColor = Tokens.Colors.BorderSubtle;
133-
textInput.style.borderBottomColor = Tokens.Colors.BorderSubtle;
134-
textInput.style.borderLeftColor = Tokens.Colors.BorderSubtle;
135-
});
131+
input.style.borderTopColor = Tokens.Colors.BorderSubtle;
132+
input.style.borderRightColor = Tokens.Colors.BorderSubtle;
133+
input.style.borderBottomColor = Tokens.Colors.BorderSubtle;
134+
input.style.borderLeftColor = Tokens.Colors.BorderSubtle;
135+
}, textInput);
136136
}
137137

138138
// Hide the label if present

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Form/JToggle.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,15 @@ public JToggle(bool initialValue = false)
115115
RegisterCallback<ClickEvent>(OnClick);
116116

117117
// Hover effect
118-
RegisterCallback<MouseEnterEvent>(e =>
118+
RegisterCallback<MouseEnterEvent, JToggle>(static (_, toggle) =>
119119
{
120-
style.opacity = 0.9f;
121-
});
120+
toggle.style.opacity = 0.9f;
121+
}, this);
122122

123-
RegisterCallback<MouseLeaveEvent>(e =>
123+
RegisterCallback<MouseLeaveEvent, JToggle>(static (_, toggle) =>
124124
{
125-
style.opacity = 1f;
126-
});
125+
toggle.style.opacity = 1f;
126+
}, this);
127127
}
128128

129129
private void OnClick(ClickEvent evt)

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Layout/JCard.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,8 @@ public JCard() : base("j-card")
5151
style.marginBottom = Tokens.Spacing.Lg;
5252

5353
// Register hover effect for elevated glass
54-
RegisterCallback<MouseEnterEvent>(evt =>
55-
{
56-
style.backgroundColor = Tokens.Colors.BgElevated;
57-
style.borderTopColor = Tokens.Colors.BorderHover;
58-
style.borderLeftColor = Tokens.Colors.BorderHover;
59-
});
60-
61-
RegisterCallback<MouseLeaveEvent>(evt =>
62-
{
63-
style.backgroundColor = Tokens.Colors.BgSurface;
64-
style.borderTopColor = Tokens.Colors.BorderLight;
65-
style.borderLeftColor = Tokens.Colors.BorderLight;
66-
});
54+
RegisterCallback<MouseEnterEvent>(OnMouseEnter);
55+
RegisterCallback<MouseLeaveEvent>(OnMouseLeave);
6756
}
6857

6958
/// <summary>
@@ -97,5 +86,20 @@ public JCard Compact()
9786
style.paddingLeft = Tokens.Spacing.MD;
9887
return this;
9988
}
89+
90+
// Static event handlers to avoid closure allocation
91+
private void OnMouseEnter(MouseEnterEvent evt)
92+
{
93+
style.backgroundColor = Tokens.Colors.BgElevated;
94+
style.borderTopColor = Tokens.Colors.BorderHover;
95+
style.borderLeftColor = Tokens.Colors.BorderHover;
96+
}
97+
98+
private void OnMouseLeave(MouseLeaveEvent evt)
99+
{
100+
style.backgroundColor = Tokens.Colors.BgSurface;
101+
style.borderTopColor = Tokens.Colors.BorderLight;
102+
style.borderLeftColor = Tokens.Colors.BorderLight;
103+
}
100104
}
101105
}

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Layout/JStack.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ private void SetGap(GapSize gap)
9494
};
9595

9696
// Apply gap using margin on children when added
97-
RegisterCallback<AttachToPanelEvent>(evt => ApplyChildGaps(gapValue));
97+
RegisterCallback<AttachToPanelEvent, (JStack stack, float gap)>(static (_, state) =>
98+
{
99+
state.stack.ApplyChildGaps(state.gap);
100+
}, (this, gapValue));
98101
}
99102

100103
private void ApplyChildGaps(float gapValue)

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Navigation/JBreadcrumb.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -164,23 +164,8 @@ public void Build()
164164
JTheme.ApplyTransition(label);
165165

166166
// Hover effect for last item
167-
label.RegisterCallback<MouseEnterEvent>(evt =>
168-
{
169-
label.style.backgroundColor = Tokens.Colors.BgHover;
170-
label.style.borderTopColor = Tokens.Colors.BorderHover;
171-
label.style.borderBottomColor = Tokens.Colors.BorderHover;
172-
label.style.borderLeftColor = Tokens.Colors.BorderHover;
173-
label.style.borderRightColor = Tokens.Colors.BorderHover;
174-
});
175-
176-
label.RegisterCallback<MouseLeaveEvent>(evt =>
177-
{
178-
label.style.backgroundColor = Tokens.Colors.BgElevated;
179-
label.style.borderTopColor = Tokens.Colors.Border;
180-
label.style.borderBottomColor = Tokens.Colors.Border;
181-
label.style.borderLeftColor = Tokens.Colors.Border;
182-
label.style.borderRightColor = Tokens.Colors.Border;
183-
});
167+
label.RegisterCallback<MouseEnterEvent, Label>(OnLastItemMouseEnter, label);
168+
label.RegisterCallback<MouseLeaveEvent, Label>(OnLastItemMouseLeave, label);
184169
}
185170
else
186171
{
@@ -215,5 +200,24 @@ public static JBreadcrumb FromPath(params string[] path)
215200
var breadcrumb = new JBreadcrumb();
216201
return breadcrumb.SetPath(path);
217202
}
203+
204+
// Static event handlers to avoid closure allocation
205+
private static void OnLastItemMouseEnter(MouseEnterEvent evt, Label label)
206+
{
207+
label.style.backgroundColor = Tokens.Colors.BgHover;
208+
label.style.borderTopColor = Tokens.Colors.BorderHover;
209+
label.style.borderBottomColor = Tokens.Colors.BorderHover;
210+
label.style.borderLeftColor = Tokens.Colors.BorderHover;
211+
label.style.borderRightColor = Tokens.Colors.BorderHover;
212+
}
213+
214+
private static void OnLastItemMouseLeave(MouseLeaveEvent evt, Label label)
215+
{
216+
label.style.backgroundColor = Tokens.Colors.BgElevated;
217+
label.style.borderTopColor = Tokens.Colors.Border;
218+
label.style.borderBottomColor = Tokens.Colors.Border;
219+
label.style.borderLeftColor = Tokens.Colors.Border;
220+
label.style.borderRightColor = Tokens.Colors.Border;
221+
}
218222
}
219223
}

0 commit comments

Comments
 (0)