Skip to content

Commit 46f81fb

Browse files
committed
fix(reconciler): manage specular adding/removing
1 parent 2fe490b commit 46f81fb

File tree

4 files changed

+65
-59
lines changed

4 files changed

+65
-59
lines changed

packages/library/src/components/hosts/GridHost.tsx

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,8 @@ import { inventory } from '../../core/inventory';
66
import type { Vector2WithInfo } from '@babylonjs/gui';
77
import type { Observable } from '@babylonjs/core';
88

9-
type GridElement = {
10-
type: 'row' | 'column';
11-
index: number;
12-
props: React.PropsWithChildren<RowProps | ColumnProps>;
13-
linkedGrid: GridType;
14-
parent: BabylonEntity<GridType> | GridElement;
15-
};
16-
179
type GridConstructor = {
18-
new (...args: any[]): GridType;
10+
new (...args: any[]): any;
1911
};
2012

2113
function handleEvents(props: RowProps | ColumnProps, element: any) {
@@ -29,86 +21,94 @@ function handleEvents(props: RowProps | ColumnProps, element: any) {
2921
});
3022
}
3123

24+
type AugmentedGrid = BabylonEntity<
25+
GridType & {
26+
type: 'row' | 'column';
27+
props: RowProps | ColumnProps;
28+
siblingIndex: number;
29+
}
30+
>;
31+
3232
export class GridHost {
33-
static createInstance(type: string, Class: any, props: RowProps | ColumnProps, rootContainer: RootContainer) {
33+
static createInstance(type: 'row' | 'column', Class: any, props: RowProps | ColumnProps, rootContainer: RootContainer) {
34+
const scene = rootContainer.scene;
35+
3436
const Grid = inventory.get('grid')?.[0] as GridConstructor;
35-
const nestedGrid: GridType = new Grid();
36-
37-
const element = {
38-
linkedGrid: nestedGrid,
39-
type,
40-
index: -1,
41-
props,
42-
handlers: {
43-
addChild: GridHost.addChild,
44-
removeChild: GridHost.removeChild,
45-
commitUpdate: GridHost.commitUpdate,
46-
},
47-
parent: null,
37+
const nestedGrid = new Grid();
38+
nestedGrid.uniqueId = scene.getUniqueId();
39+
40+
nestedGrid.type = type;
41+
nestedGrid.props = props;
42+
nestedGrid.handlers = {
43+
addChild: GridHost.addChild,
44+
removeChild: GridHost.removeChild,
45+
commitUpdate: GridHost.commitUpdate,
4846
};
47+
nestedGrid.parent = null;
4948

5049
handleEvents(props, nestedGrid);
51-
return element;
50+
51+
return nestedGrid;
5252
}
5353

54-
static addChild(parentInstance: BabylonEntity<GridType> | GridElement, child: GridElement): void {
54+
static addChild(parentInstance: AugmentedGrid | BabylonEntity<GridType>, child: AugmentedGrid, context: any): void {
5555
const { type, props } = child;
5656
const { isPixel } = props;
57+
const { siblingIndex } = context;
5758

58-
const grid: GridType = (parentInstance as GridElement).linkedGrid ?? parentInstance;
59-
const parentName = grid.name || 'grid';
59+
const parentName = parentInstance.name || 'grid';
6060

6161
if (type === 'row') {
6262
const { height } = props as RowProps;
63-
grid.addRowDefinition(height, isPixel);
6463

65-
const rowIndex = grid.rowCount - 1;
66-
child.linkedGrid.name = `${parentName}-row-${rowIndex}`;
67-
grid.addControl(child.linkedGrid, rowIndex, 0);
64+
parentInstance.addRowDefinition(height, isPixel);
6865

69-
child.index = rowIndex;
70-
} else if (type === 'column') {
66+
const rowIndex = siblingIndex;
67+
child.name = `${parentName}-row-${rowIndex}`;
68+
parentInstance.addControl(child, rowIndex, 0);
69+
} else {
7170
const { width } = props as ColumnProps;
72-
grid.addColumnDefinition(width, isPixel);
71+
parentInstance.addColumnDefinition(width, isPixel);
7372

74-
const colIndex = grid.columnCount - 1;
75-
child.linkedGrid.name = `${parentName}-col-${colIndex}`;
76-
grid.addControl(child.linkedGrid, 0, colIndex);
77-
78-
child.index = colIndex;
73+
const colIndex = siblingIndex;
74+
child.name = `${parentName}-col-${colIndex}`;
75+
parentInstance.addControl(child, 0, colIndex);
7976
}
8077

81-
// save parent to operate on it in commitUpdate
78+
// info for in commitUpdate
8279
child.parent = parentInstance;
80+
child.siblingIndex = siblingIndex;
8381
}
8482

85-
static removeChild(parentInstance: BabylonEntity<GridType> | GridElement, child: GridElement): void {
86-
const { type, index } = child;
87-
const grid: GridType = (parentInstance as GridElement).linkedGrid ?? parentInstance;
83+
static removeChild(parentInstance: AugmentedGrid | BabylonEntity<GridType>, child: AugmentedGrid, context: any): void {
84+
const { type } = child;
85+
const { siblingIndex } = context;
86+
87+
parentInstance.removeControl(child);
8888

8989
if (type === 'row') {
90-
grid.removeRowDefinition(index);
90+
parentInstance.removeRowDefinition(siblingIndex);
9191
} else if (type === 'column') {
92-
grid.removeColumnDefinition(index);
92+
parentInstance.removeColumnDefinition(siblingIndex);
9393
}
9494
}
9595

9696
static prepareUpdate(): UpdatePayload {
9797
return {};
9898
}
9999

100-
static commitUpdate(instance: GridElement, updatePayload: UpdatePayload): void {
101-
const { type, index, parent } = instance;
100+
static commitUpdate(instance: AugmentedGrid, updatePayload: UpdatePayload): void {
101+
const { type, siblingIndex, parent } = instance;
102102
const { isPixel } = updatePayload as RowProps | ColumnProps;
103103

104-
const grid: GridType = (parent as GridElement).linkedGrid ?? parent;
104+
const grid = parent as AugmentedGrid | BabylonEntity<GridType>;
105105

106106
if (type === 'row') {
107107
const { height } = updatePayload as RowProps;
108-
grid.setRowDefinition(index, height, isPixel);
108+
grid.setRowDefinition(siblingIndex, height, isPixel);
109109
} else if (type === 'column') {
110110
const { width } = updatePayload as ColumnProps;
111-
grid.setColumnDefinition(index, width, isPixel);
111+
grid.setColumnDefinition(siblingIndex, width, isPixel);
112112
}
113113
}
114114
}

packages/library/src/components/hosts/GuiHost.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { type GuiHostProps, type GuiTriggerable, GuiTriggers } from '@props';
44
import { TransformKeysMap } from '@constants';
55
import ObjectUtils from '@utils/ObjectUtils';
66
import guiConstructors from '../../_generated/babylon.gui.constructors';
7-
import type { Vector2WithInfo, GUI3DManager, Control, Container, Button3D } from '@babylonjs/gui';
7+
import type { Vector2WithInfo, GUI3DManager, Control, Container, Button3D, Grid } from '@babylonjs/gui';
88
import type { Observable } from '@babylonjs/core';
99

1010
// required for git hook (otherwise it can't resolve the augmented JSXElements)
@@ -104,10 +104,9 @@ export class GuiHost {
104104
if (isInstanceOf(parentInstance, 'Button3D') && !isInstanceOf(parentInstance, 'HolographicButton')) {
105105
(parentInstance as unknown as Button3D).content = child;
106106
} else {
107-
// @ts-expect-error - linkedGrid is not a part of the Control interface, but it is used in Grid
108-
const grid = parentInstance.linkedGrid;
109-
if (grid && grid.addControl) {
110-
grid.addControl(child, 0, 0);
107+
// @ts-expect-error - type is not a part of Grid
108+
if (parentInstance.type === 'row' || parentInstance.type === 'column') {
109+
(parentInstance as Grid).addControl?.(child, 0, 0);
111110
} else {
112111
// ensure that addControl function exists (parentInstance could be transformNode)
113112
parentInstance.addControl?.(child);

packages/library/src/reconciler.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function removeChild(parentInstance: Instance | RootContainer, child: Instance)
4141
const index = parentInstance.children.findIndex(item => item.entity!.uniqueId === child.entity!.uniqueId);
4242
parentInstance.children.splice(index, 1);
4343
//@ts-ignore
44-
child.entity.handlers?.removeChild?.(parentInstance.entity, child.entity);
44+
child.entity.handlers?.removeChild?.(parentInstance.entity, child.entity, { siblingIndex: index });
4545
const disposeMaterialsAndTextures = shouldDisposeMaterialsAndTextures(child);
4646
child.entity!.dispose?.(false, disposeMaterialsAndTextures);
4747
}
@@ -176,8 +176,15 @@ function mountBabylonEntity(parent: Instance | RootContainer, child: Instance, i
176176
instantiateBabylonEntity(_parent);
177177
}
178178

179+
let siblingIndex = -1;
180+
try {
181+
siblingIndex = parent.children.findIndex(item => item.entity!.uniqueId === child.entity!.uniqueId);
182+
} catch (error) {
183+
// silent error
184+
}
185+
179186
// TODO: decouple handlers and Babylon.js entity
180-
child.entity!.handlers?.addChild?.(_parent.entity!, child.entity!);
187+
child.entity!.handlers?.addChild?.(_parent.entity!, child.entity!, { siblingIndex });
181188
if (child.babylonPackage === BabylonPackages.CORE) {
182189
if (isParentNeeded(child.entity!)) {
183190
try {

packages/library/src/types/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ export type BabylonProps<Props, ConstructorProps, Element> = {
5555
export type BabylonEntity<T = unknown> = Pick<Node, 'name' | 'uniqueId' | 'dispose'> & {
5656
parent?: unknown;
5757
handlers?: Partial<{
58-
addChild(parentInstance: BabylonEntity<T> | RootContainer, child: BabylonEntity<T>): void;
59-
removeChild(parentInstance: BabylonEntity<T> | undefined, child: BabylonEntity<T>): void;
58+
addChild(parentInstance: BabylonEntity<T> | RootContainer, child: BabylonEntity<T>, context?: any): void;
59+
removeChild(parentInstance: BabylonEntity<T> | undefined, child: BabylonEntity<T>, context?: any): void;
6060
prepareUpdate(): UpdatePayload;
6161
commitUpdate(instance: BabylonEntity<T>, updatePayload: UpdatePayload): void;
6262
}>;

0 commit comments

Comments
 (0)