• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / luma.gl / 17192022436

24 Aug 2025 06:02PM UTC coverage: 62.079% (-13.2%) from 75.234%
17192022436

Pull #2437

github

web-flow
Merge 562c391b0 into 8314ecefa
Pull Request #2437: test(engine): add ShaderPassRenderer test

956 of 1559 branches covered (61.32%)

Branch coverage included in aggregate %.

491 of 666 new or added lines in 7 files covered. (73.72%)

5291 existing lines in 117 files now uncovered.

23238 of 37414 relevant lines covered (62.11%)

3.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

12.39
/modules/engine/src/scenegraph/group-node.ts
1
// luma.gl
1✔
2
// SPDX-License-Identifier: MIT
1✔
3
// Copyright (c) vis.gl contributors
1✔
4

1✔
5
import {Matrix4, Vector3} from '@math.gl/core';
1✔
6
import {log} from '@luma.gl/core';
1✔
7
import {ScenegraphNode, ScenegraphNodeProps} from './scenegraph-node';
1✔
8

1✔
9
export type GroupNodeProps = ScenegraphNodeProps & {
1✔
10
  children?: ScenegraphNode[];
1✔
11
};
1✔
12

1✔
13
export class GroupNode extends ScenegraphNode {
1!
UNCOV
14
  children: ScenegraphNode[];
×
UNCOV
15

×
UNCOV
16
  constructor(children: ScenegraphNode[]);
×
UNCOV
17
  constructor(props?: GroupNodeProps);
×
UNCOV
18

×
UNCOV
19
  constructor(props: ScenegraphNode[] | GroupNodeProps = {}) {
×
UNCOV
20
    props = Array.isArray(props) ? {children: props} : props;
×
UNCOV
21
    const {children = []} = props;
×
UNCOV
22
    log.assert(
×
UNCOV
23
      children.every(child => child instanceof ScenegraphNode),
×
UNCOV
24
      'every child must an instance of ScenegraphNode'
×
UNCOV
25
    );
×
UNCOV
26
    super(props);
×
UNCOV
27
    this.children = children;
×
UNCOV
28
  }
×
UNCOV
29

×
UNCOV
30
  override getBounds(): [number[], number[]] | null {
×
UNCOV
31
    const result: [number[], number[]] = [
×
UNCOV
32
      [Infinity, Infinity, Infinity],
×
UNCOV
33
      [-Infinity, -Infinity, -Infinity]
×
UNCOV
34
    ];
×
UNCOV
35

×
UNCOV
36
    this.traverse((node, {worldMatrix}) => {
×
UNCOV
37
      const bounds = node.getBounds();
×
UNCOV
38
      if (!bounds) {
×
UNCOV
39
        return;
×
UNCOV
40
      }
×
UNCOV
41
      const [min, max] = bounds;
×
UNCOV
42
      const center = new Vector3(min).add(max).divide([2, 2, 2]);
×
UNCOV
43
      worldMatrix.transformAsPoint(center, center);
×
UNCOV
44
      const halfSize = new Vector3(max).subtract(min).divide([2, 2, 2]);
×
UNCOV
45
      worldMatrix.transformAsVector(halfSize, halfSize);
×
UNCOV
46

×
UNCOV
47
      for (let v = 0; v < 8; v++) {
×
UNCOV
48
        // Test all 8 corners of the box
×
UNCOV
49
        const position = new Vector3(v & 0b001 ? -1 : 1, v & 0b010 ? -1 : 1, v & 0b100 ? -1 : 1)
×
UNCOV
50
          .multiply(halfSize)
×
UNCOV
51
          .add(center);
×
UNCOV
52

×
UNCOV
53
        for (let i = 0; i < 3; i++) {
×
UNCOV
54
          result[0][i] = Math.min(result[0][i], position[i]);
×
UNCOV
55
          result[1][i] = Math.max(result[1][i], position[i]);
×
UNCOV
56
        }
×
UNCOV
57
      }
×
UNCOV
58
    });
×
UNCOV
59
    if (!Number.isFinite(result[0][0])) {
×
UNCOV
60
      return null;
×
UNCOV
61
    }
×
UNCOV
62
    return result;
×
UNCOV
63
  }
×
UNCOV
64

×
UNCOV
65
  override destroy(): void {
×
UNCOV
66
    this.children.forEach(child => child.destroy());
×
UNCOV
67
    this.removeAll();
×
UNCOV
68
    super.destroy();
×
UNCOV
69
  }
×
UNCOV
70

×
UNCOV
71
  // Unpacks arrays and nested arrays of children
×
UNCOV
72
  add(...children: (ScenegraphNode | ScenegraphNode[])[]): this {
×
UNCOV
73
    for (const child of children) {
×
UNCOV
74
      if (Array.isArray(child)) {
×
UNCOV
75
        this.add(...child);
×
UNCOV
76
      } else {
×
UNCOV
77
        this.children.push(child);
×
UNCOV
78
      }
×
UNCOV
79
    }
×
UNCOV
80
    return this;
×
UNCOV
81
  }
×
UNCOV
82

×
UNCOV
83
  remove(child: ScenegraphNode): this {
×
UNCOV
84
    const children = this.children;
×
UNCOV
85
    const indexOf = children.indexOf(child);
×
UNCOV
86
    if (indexOf > -1) {
×
UNCOV
87
      children.splice(indexOf, 1);
×
UNCOV
88
    }
×
UNCOV
89
    return this;
×
UNCOV
90
  }
×
UNCOV
91

×
UNCOV
92
  removeAll(): this {
×
UNCOV
93
    this.children = [];
×
UNCOV
94
    return this;
×
UNCOV
95
  }
×
UNCOV
96

×
UNCOV
97
  traverse(
×
UNCOV
98
    visitor: (node: ScenegraphNode, context: {worldMatrix: Matrix4}) => void,
×
UNCOV
99
    {worldMatrix = new Matrix4()} = {}
×
UNCOV
100
  ) {
×
UNCOV
101
    const modelMatrix = new Matrix4(worldMatrix).multiplyRight(this.matrix);
×
UNCOV
102

×
UNCOV
103
    for (const child of this.children) {
×
UNCOV
104
      if (child instanceof GroupNode) {
×
UNCOV
105
        child.traverse(visitor, {worldMatrix: modelMatrix});
×
UNCOV
106
      } else {
×
UNCOV
107
        visitor(child, {worldMatrix: modelMatrix});
×
UNCOV
108
      }
×
UNCOV
109
    }
×
UNCOV
110
  }
×
UNCOV
111
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc