Skip to content

Commit aa92984

Browse files
authored
Merge branch 'main' into feat/dyn-shader-updates
2 parents 538d4c6 + c429102 commit aa92984

File tree

135 files changed

+1111
-433
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+1111
-433
lines changed

NOTICE

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
This component contains software that is Copyright (c) 2023 Comcast.
1+
This component contains software that is Copyright 2023 Comcast Cable Communications Management, LLC.
22
The component is licensed to you under the Apache License, Version 2.0 (the "License").
33
You may not use the component except in compliance with the License.
4-

examples/common/AppCoreExtension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* If not stated otherwise in this file or this component's LICENSE file the
33
* following copyright and licenses apply:
44
*
5-
* Copyright 2023 Comcast
5+
* Copyright 2023 Comcast Cable Communications Management, LLC.
66
*
77
* Licensed under the Apache License, Version 2.0 (the License);
88
* you may not use this file except in compliance with the License.

examples/common/Character.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* If not stated otherwise in this file or this component's LICENSE file the
33
* following copyright and licenses apply:
44
*
5-
* Copyright 2023 Comcast
5+
* Copyright 2023 Comcast Cable Communications Management, LLC.
66
*
77
* Licensed under the Apache License, Version 2.0 (the License);
88
* you may not use this file except in compliance with the License.

examples/common/Component.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type {
2+
INode,
3+
INodeWritableProps,
4+
RendererMain,
5+
} from '@lightningjs/renderer';
6+
7+
export class Component {
8+
readonly node: INode;
9+
10+
constructor(
11+
readonly renderer: RendererMain,
12+
nodeProps: Partial<INodeWritableProps>,
13+
) {
14+
this.node = renderer.createNode({
15+
...nodeProps,
16+
});
17+
}
18+
19+
get x() {
20+
return this.node.x;
21+
}
22+
23+
set x(x: number) {
24+
this.node.x = x;
25+
}
26+
27+
get y() {
28+
return this.node.y;
29+
}
30+
31+
set y(y: number) {
32+
this.node.y = y;
33+
}
34+
35+
get width() {
36+
return this.node.width;
37+
}
38+
39+
set width(width: number) {
40+
this.node.width = width;
41+
}
42+
43+
get height() {
44+
return this.node.height;
45+
}
46+
47+
set height(height: number) {
48+
this.node.height = height;
49+
}
50+
}

examples/common/CoreWorker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* If not stated otherwise in this file or this component's LICENSE file the
33
* following copyright and licenses apply:
44
*
5-
* Copyright 2023 Comcast
5+
* Copyright 2023 Comcast Cable Communications Management, LLC.
66
*
77
* Licensed under the Apache License, Version 2.0 (the License);
88
* you may not use this file except in compliance with the License.

examples/common/PageContainer.ts

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import type { INode, ITextNode, RendererMain } from '@lightningjs/renderer';
2+
import { Component } from './Component.js';
3+
import { loadStorage, saveStorage } from '../common/LocalStorage.js';
4+
5+
interface PageContainerLocalStorageData {
6+
curPage: number;
7+
}
8+
9+
const TITLE_FONT_SIZE = 40;
10+
const PADDING = 20;
11+
12+
interface PageContainerProps {
13+
x?: number;
14+
y?: number;
15+
width?: number;
16+
height?: number;
17+
parent?: INode | null;
18+
color?: number;
19+
20+
//
21+
testName?: string;
22+
title?: string;
23+
}
24+
25+
export class PageContainer extends Component {
26+
private titleNode: ITextNode;
27+
private pageNumberNode: ITextNode;
28+
private curPageNode: INode | null = null;
29+
private curPageIndex = -1;
30+
private pageConstructors: ((page: INode) => Promise<void>)[] = [];
31+
private testName?: string;
32+
33+
constructor(renderer: RendererMain, props: PageContainerProps) {
34+
super(renderer, {
35+
x: props.x,
36+
y: props.y,
37+
color: props.color ?? 0x00000000,
38+
width: props.width,
39+
height: props.height,
40+
parent: props.parent,
41+
});
42+
43+
this.titleNode = renderer.createTextNode({
44+
fontFamily: 'Ubuntu',
45+
fontSize: TITLE_FONT_SIZE,
46+
x: PADDING,
47+
y: PADDING,
48+
parent: renderer.root,
49+
text: props.title ?? '',
50+
});
51+
52+
this.testName = props.testName;
53+
54+
this.pageNumberNode = renderer.createTextNode({
55+
fontFamily: 'Ubuntu',
56+
fontSize: 30,
57+
x: PADDING,
58+
y: this.node.height - 30 - PADDING,
59+
parent: renderer.root,
60+
});
61+
}
62+
63+
pushPage(pageConstructor: (page: INode) => Promise<void>) {
64+
this.pageConstructors.push(pageConstructor);
65+
}
66+
67+
finalizePages() {
68+
if (this.curPageIndex === -1 && this.pageConstructors.length > 0) {
69+
const { testName } = this;
70+
let pageNum = 0;
71+
if (testName) {
72+
const savedState = loadStorage<PageContainerLocalStorageData>(
73+
`${testName}-PageContainer`,
74+
);
75+
if (
76+
savedState &&
77+
savedState.curPage &&
78+
savedState.curPage < this.pageConstructors.length
79+
) {
80+
pageNum = savedState.curPage;
81+
}
82+
}
83+
this.setPage(pageNum).catch(console.error);
84+
}
85+
}
86+
87+
async setPage(pageIndex: number) {
88+
this.pageNumberNode.text = `Page ${pageIndex + 1}/${
89+
this.pageConstructors.length
90+
}`;
91+
this.curPageIndex = pageIndex;
92+
93+
if (this.curPageNode) {
94+
this.curPageNode.destroy();
95+
this.curPageNode = null;
96+
}
97+
98+
this.curPageNode = this.renderer.createNode({
99+
x: PADDING,
100+
y: TITLE_FONT_SIZE + PADDING,
101+
color: 0x00000000,
102+
width: this.contentWidth,
103+
height: this.contentHeight,
104+
parent: this.node,
105+
});
106+
107+
const { testName } = this;
108+
if (testName) {
109+
saveStorage<PageContainerLocalStorageData>(`${testName}-PageContainer`, {
110+
curPage: pageIndex,
111+
});
112+
}
113+
114+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
115+
await this.pageConstructors[pageIndex]!(this.curPageNode);
116+
}
117+
118+
bindWindowKeys() {
119+
window.addEventListener('keydown', (e) => {
120+
const numPages = this.pageConstructors.length;
121+
if (e.key === 'ArrowLeft') {
122+
const newPageIndex = (this.curPageIndex + numPages - 1) % numPages;
123+
this.setPage(newPageIndex).catch(console.error);
124+
} else if (e.key === 'ArrowRight') {
125+
const newPageIndex = (this.curPageIndex + 1) % numPages;
126+
this.setPage(newPageIndex).catch(console.error);
127+
}
128+
});
129+
// Once we've bound keys for the first time, turn this method into a noop
130+
this.bindWindowKeys = () => {
131+
/* noop */
132+
};
133+
}
134+
135+
get contentHeight() {
136+
return this.node.height - TITLE_FONT_SIZE - PADDING * 2;
137+
}
138+
139+
get contentWidth() {
140+
return this.node.width - PADDING * 2;
141+
}
142+
143+
get padding() {
144+
return PADDING;
145+
}
146+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import type { INode } from '@lightningjs/renderer';
2+
import { PageContainer } from './PageContainer.js';
3+
import { assertTruthy } from '@lightningjs/renderer/utils';
4+
5+
const HEADER_FONT_SIZE = 30;
6+
const PADDING = 20;
7+
8+
export type RowConstructor = (pageNode: INode) => Promise<INode>;
9+
export type RowContentConstructor = (rowNode: INode) => Promise<number>;
10+
11+
export interface TestRow {
12+
title: string;
13+
content: RowContentConstructor;
14+
}
15+
16+
function createPageConstructor(curPageRowConstructors: RowConstructor[]) {
17+
return async function (
18+
rowConstructors: RowConstructor[],
19+
pageNode: INode,
20+
): Promise<void> {
21+
let curY = 0;
22+
for (const rowConstructor of rowConstructors) {
23+
const rowNode = await rowConstructor(pageNode);
24+
rowNode.y = curY;
25+
curY += rowNode.height;
26+
}
27+
}.bind(null, curPageRowConstructors);
28+
}
29+
30+
export async function paginateTestRows(
31+
pageContainer: PageContainer,
32+
testRows: TestRow[],
33+
) {
34+
const renderer = pageContainer.renderer;
35+
assertTruthy(renderer.root);
36+
let pageCurY = 0;
37+
let curPageRowConstructors: RowConstructor[] = [];
38+
let curRowIndex = 0;
39+
for (const testRow of testRows) {
40+
const isLastRow = curRowIndex === testRows.length - 1;
41+
let newRowConstructor: RowConstructor | null = async (pageNode: INode) => {
42+
const rowContainer = renderer.createNode({
43+
x: 0,
44+
y: pageCurY,
45+
width: pageContainer.contentWidth,
46+
height: 0,
47+
color: 0x00000000,
48+
parent: pageNode,
49+
});
50+
const rowHeaderNode = renderer.createTextNode({
51+
fontFamily: 'Ubuntu',
52+
fontSize: HEADER_FONT_SIZE,
53+
y: PADDING,
54+
parent: rowContainer,
55+
});
56+
const rowNode = renderer.createNode({
57+
y: HEADER_FONT_SIZE + PADDING * 2,
58+
width: pageContainer.contentWidth,
59+
height: 0,
60+
color: 0x00000000,
61+
parent: rowContainer,
62+
});
63+
const rowHeight = await testRow.content(rowNode);
64+
rowNode.height = rowHeight;
65+
rowHeaderNode.text = testRow.title;
66+
rowContainer.height = HEADER_FONT_SIZE + PADDING * 2 + rowNode.height;
67+
return rowContainer;
68+
};
69+
// Construct the row just to get its height
70+
const tmpRowContainer = await newRowConstructor(renderer.root);
71+
// curPageRowConstructors.push(newRowConstructor);
72+
// If it fits, add it to the current page
73+
const itFits =
74+
pageCurY + tmpRowContainer.height <= pageContainer.contentHeight;
75+
if (itFits) {
76+
curPageRowConstructors.push(newRowConstructor);
77+
pageCurY += tmpRowContainer.height;
78+
newRowConstructor = null;
79+
}
80+
// If it doesn't fit OR it's the last row, add the current page to the page container and start a new page
81+
if (!itFits || isLastRow) {
82+
const pageConstructor = createPageConstructor(curPageRowConstructors);
83+
pageContainer.pushPage(pageConstructor);
84+
85+
pageCurY = tmpRowContainer.height;
86+
curPageRowConstructors = [];
87+
if (newRowConstructor) {
88+
curPageRowConstructors.push(newRowConstructor);
89+
}
90+
91+
if (isLastRow && !itFits) {
92+
const pageConstructor = createPageConstructor(curPageRowConstructors);
93+
pageContainer.pushPage(pageConstructor);
94+
}
95+
}
96+
tmpRowContainer.parent = null;
97+
tmpRowContainer.destroy();
98+
curRowIndex++;
99+
}
100+
pageContainer.finalizePages();
101+
}

examples/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* If not stated otherwise in this file or this component's LICENSE file the
33
* following copyright and licenses apply:
44
*
5-
* Copyright 2023 Comcast
5+
* Copyright 2023 Comcast Cable Communications Management, LLC.
66
*
77
* Licensed under the Apache License, Version 2.0 (the License);
88
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)