Skip to content

Commit 5f99f2c

Browse files
authored
Merge pull request #414 from dli7319/ui_panel_corner_radius
ui: Unify panel corner radius and use physical border width
2 parents b996314 + 6f302dc commit 5f99f2c

6 files changed

Lines changed: 31 additions & 24 deletions

File tree

samples/ui/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@
190190
// player row
191191
const playerRow = grid.addRow({weight: 1.0});
192192
const playerPanel = playerRow.addPanel({
193-
width: 1.2,
194-
height: 1.2,
193+
width: 1,
194+
height: 1,
195195
backgroundColor: '#21252baa',
196196
});
197197
const playerGrid = playerPanel.addGrid();

src/ui/core/Panel.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ export class Panel extends View implements Draggable, Partial<HasDraggingMode> {
7676
*/
7777
showHighlights = false;
7878

79+
/** The width of the interactive border, in meters. */
80+
borderWidth = 0.1;
81+
7982
/** The background color of the panel, expressed as a CSS color string. */
8083
backgroundColor = '#c2c2c255';
8184

@@ -123,8 +126,6 @@ export class Panel extends View implements Draggable, Partial<HasDraggingMode> {
123126
const isDraggable = options.draggable ?? this.draggable;
124127

125128
const useBorderlessShader = options.useBorderlessShader ?? !isDraggable;
126-
// Draggable panels have a larger geometry for interaction padding.
127-
const panelScale = useBorderlessShader ? 1.0 : 1.3;
128129
// Use SpatialPanelShader for SpatialPanel, while developers can choose
129130
// useBorderlessShader=false to disable the interactive border.
130131
const shader = useBorderlessShader ? SquircleShader : SpatialPanelShader;
@@ -147,8 +148,12 @@ export class Panel extends View implements Draggable, Partial<HasDraggingMode> {
147148
options.useDefaultPosition ?? this.useDefaultPosition;
148149
this.useBorderlessShader =
149150
options.useBorderlessShader ?? this.useBorderlessShader;
151+
this.borderWidth = options.borderWidth ?? this.borderWidth;
150152

151-
this.mesh = new PanelMesh(shader, this.backgroundColor, panelScale);
153+
this.mesh = new PanelMesh(shader, this.backgroundColor);
154+
if (this.mesh.uniforms.uBorderWidth) {
155+
this.mesh.uniforms.uBorderWidth.value = this.borderWidth;
156+
}
152157
this.add(this.mesh);
153158

154159
this.updateLayout();
@@ -321,13 +326,21 @@ export class Panel extends View implements Draggable, Partial<HasDraggingMode> {
321326
*/
322327
override updateLayout() {
323328
super.updateLayout();
324-
this.mesh.setAspectRatio(this.aspectRatio);
325329
const parentAspectRatio =
326330
this.isRoot || !this.parent ? 1.0 : (this.parent as View).aspectRatio;
327-
this.mesh.setWidthHeight(
328-
this.width * Math.max(parentAspectRatio, 1.0),
329-
this.height * Math.max(1.0 / parentAspectRatio, 1.0)
330-
);
331+
const layoutWidth = this.width * Math.max(parentAspectRatio, 1.0);
332+
const layoutHeight = this.height * Math.max(1.0 / parentAspectRatio, 1.0);
333+
334+
const effectiveBorderWidth = this.useBorderlessShader
335+
? 0.0
336+
: this.borderWidth;
337+
const meshWidth = layoutWidth + effectiveBorderWidth;
338+
const meshHeight = layoutHeight + effectiveBorderWidth;
339+
340+
const panelScale = Math.min(layoutWidth, layoutHeight);
341+
this.mesh.scale.set(meshWidth / panelScale, meshHeight / panelScale, 1.0);
342+
343+
this.mesh.setWidthHeight(meshWidth, meshHeight);
331344
this.mesh.renderOrder = this.renderOrder;
332345
}
333346

src/ui/core/PanelMesh.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ export class PanelMesh extends THREE.Mesh<
2929
* Creates an instance of PanelMesh.
3030
* @param shader - Shader for the panel mesh.
3131
* @param backgroundColor - The background color as a CSS string.
32-
* @param panelScale - The initial scale of the plane
3332
*/
34-
constructor(shader: Shader, backgroundColor?: string, panelScale = 1.0) {
33+
constructor(shader: Shader, backgroundColor?: string) {
3534
// Each mesh needs its own unique set of uniforms.
3635
const uniforms = THREE.UniformsUtils.clone(shader.uniforms);
3736

@@ -44,7 +43,7 @@ export class PanelMesh extends THREE.Mesh<
4443
side: THREE.DoubleSide,
4544
});
4645

47-
const geometry = new THREE.PlaneGeometry(panelScale, panelScale);
46+
const geometry = new THREE.PlaneGeometry(1.0, 1.0);
4847

4948
super(geometry, material);
5049

src/ui/core/PanelOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ export type PanelOptions = ViewOptions & {
1414
showHighlights?: boolean;
1515
useDefaultPosition?: boolean;
1616
useBorderlessShader?: boolean;
17+
borderWidth?: number;
1718
};

src/ui/shaders/SpatialPanelShader.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,6 @@ export const SpatialPanelShader = {
108108
}
109109
110110
void main(void) {
111-
vec2 size = uBoxSize * 1000.0;
112-
float radius = min(size.x, size.y) * (0.05 + uRadius);
113-
vec2 half_size = 0.5 * size;
114-
115111
// Distance to the outer edge of the round box in UV space (0-1)
116112
float distOuterUV = distRoundBox(vTexCoord * uBoxSize - uBoxSize * 0.5, uBoxSize * 0.5, uRadius);
117113

src/ui/shaders/SquircleShader.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,12 @@ export const SquircleShader = {
106106
#include <alphatest_fragment>
107107
#include <alphahash_fragment>
108108
#include <specularmap_fragment>
109-
vec2 size = uBoxSize * 1000.0;
110109
111-
// Calculates the adjusted radius based on box size.
112-
float radius = min(size.x, size.y) * (0.05 + uRadius);
113-
vec2 half_size = 0.5 * size;
110+
// Compute the distance from the rounded box edge in meters.
111+
float dist = distRoundBox(vUv * uBoxSize - uBoxSize * 0.5, uBoxSize * 0.5, uRadius);
114112
115-
// Compute the distance from the rounded box edge.
116-
float dist = distRoundBox(vUv * size - half_size, half_size, radius);
113+
// Antialiasing delta
114+
float aa = fwidth(dist) * 0.8;
117115
118116
// Use lerp for smooth color transition based on distance.
119117
vec4 colorInside = uBackgroundColor;
@@ -126,7 +124,7 @@ export const SquircleShader = {
126124
// Transparent black for outside.
127125
vec4 colorOutside = vec4(0.0, 0.0, 0.0, 0.0);
128126
129-
vec4 finalColor = mix(colorInside, colorOutside, smoothstep(0.0, 1.0, dist));
127+
vec4 finalColor = mix(colorInside, colorOutside, smoothstep(0.0, aa, dist));
130128
131129
// Return premultiplied alpha.
132130
gl_FragColor = uOpacity * finalColor.a * vec4(finalColor.rgb, 1.0);

0 commit comments

Comments
 (0)