@dcl/react-ecs 7.17.1-21217092165.commit-1c2ff72 → 7.17.1-21366395728.commit-ada88b6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calcOnViewport, getScaleCtx } from '../utils';
|
|
1
|
+
import { calcOnViewport, getScaleCtx, getUiScaleFactor } from '../utils';
|
|
2
2
|
const parseFont = {
|
|
3
3
|
'sans-serif': 0 /* Font.F_SANS_SERIF */,
|
|
4
4
|
serif: 1 /* Font.F_SERIF */,
|
|
@@ -39,7 +39,7 @@ export function getFontSize(fontSize) {
|
|
|
39
39
|
return undefined;
|
|
40
40
|
if (typeof fontSize === 'string')
|
|
41
41
|
return { fontSize: calcOnViewport(fontSize) };
|
|
42
|
-
return { fontSize };
|
|
42
|
+
return { fontSize: fontSize * getUiScaleFactor() };
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Scales a font size depending on a context's width/height
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { calcOnViewport } from '../utils';
|
|
1
|
+
import { calcOnViewport, getUiScaleFactor } from '../utils';
|
|
2
2
|
function capitalize(value) {
|
|
3
3
|
return `${value[0].toUpperCase()}${value.slice(1, value.length)}`;
|
|
4
4
|
}
|
|
@@ -14,6 +14,9 @@ function isVw(val) {
|
|
|
14
14
|
function isVh(val) {
|
|
15
15
|
return typeof val === 'string' && val.endsWith('vh');
|
|
16
16
|
}
|
|
17
|
+
function scalePixelValue(value) {
|
|
18
|
+
return value * getUiScaleFactor();
|
|
19
|
+
}
|
|
17
20
|
function parsePositionUnit(val) {
|
|
18
21
|
function getValue(key, value) {
|
|
19
22
|
return Number(value.slice(0, value.indexOf(key)));
|
|
@@ -25,13 +28,13 @@ function parsePositionUnit(val) {
|
|
|
25
28
|
return [0, 3 /* YGUnit.YGU_AUTO */];
|
|
26
29
|
}
|
|
27
30
|
if (typeof val === 'number' || (typeof val === 'string' && !isNaN(Number(val)))) {
|
|
28
|
-
return [Number(val), 1 /* YGUnit.YGU_POINT */];
|
|
31
|
+
return [scalePixelValue(Number(val)), 1 /* YGUnit.YGU_POINT */];
|
|
29
32
|
}
|
|
30
33
|
if (isPercent(val)) {
|
|
31
34
|
return [getValue('%', val), 2 /* YGUnit.YGU_PERCENT */];
|
|
32
35
|
}
|
|
33
36
|
if (isPoint(val)) {
|
|
34
|
-
return [getValue('px', val), 1 /* YGUnit.YGU_POINT */];
|
|
37
|
+
return [scalePixelValue(getValue('px', val)), 1 /* YGUnit.YGU_POINT */];
|
|
35
38
|
}
|
|
36
39
|
if (isVw(val) || isVh(val)) {
|
|
37
40
|
return [calcOnViewport(val), 1 /* YGUnit.YGU_POINT */];
|
package/dist/components/utils.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { engine, UiCanvasInformation as engineUiCanvasInformation } from '@dcl/ecs';
|
|
2
2
|
import { parseUiBackground } from './uiBackground';
|
|
3
3
|
import { parseUiTransform } from './uiTransform';
|
|
4
|
+
let uiScaleFactor = 1;
|
|
5
|
+
let uiScaleOwner = undefined;
|
|
4
6
|
/**
|
|
5
7
|
* @internal
|
|
6
8
|
*/
|
|
@@ -45,6 +47,34 @@ export function getScaleCtx(_engine = engine) {
|
|
|
45
47
|
const { width, height, devicePixelRatio } = canvasInfo;
|
|
46
48
|
return { width, height, ratio: devicePixelRatio };
|
|
47
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export function getUiScaleFactor() {
|
|
54
|
+
return uiScaleFactor;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export function setUiScaleFactor(nextScale, owner) {
|
|
60
|
+
if (!Number.isFinite(nextScale) || nextScale < 0)
|
|
61
|
+
return;
|
|
62
|
+
if (owner) {
|
|
63
|
+
// Mark ownership so only that system can reset the scale.
|
|
64
|
+
uiScaleOwner = owner;
|
|
65
|
+
}
|
|
66
|
+
uiScaleFactor = nextScale;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export function resetUiScaleFactor(owner) {
|
|
72
|
+
// Ignore resets from non-owners to avoid stomping active scale.
|
|
73
|
+
if (owner && uiScaleOwner !== owner)
|
|
74
|
+
return;
|
|
75
|
+
uiScaleOwner = undefined;
|
|
76
|
+
uiScaleFactor = 1;
|
|
77
|
+
}
|
|
48
78
|
/**
|
|
49
79
|
* @internal
|
|
50
80
|
*/
|
package/dist/system.d.ts
CHANGED
|
@@ -4,12 +4,25 @@ import type { ReactEcs } from './react-ecs';
|
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
6
6
|
export type UiComponent = () => ReactEcs.JSX.ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export type UiRendererOptions = {
|
|
11
|
+
virtualWidth: number;
|
|
12
|
+
virtualHeight: number;
|
|
13
|
+
};
|
|
7
14
|
/**
|
|
8
15
|
* @public
|
|
9
16
|
*/
|
|
10
17
|
export interface ReactBasedUiSystem {
|
|
18
|
+
/**
|
|
19
|
+
* Destroy all UI entities and unregister related systems.
|
|
20
|
+
*/
|
|
11
21
|
destroy(): void;
|
|
12
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Set the main UI renderer. Optional virtual size defines the global UI scale factor.
|
|
24
|
+
*/
|
|
25
|
+
setUiRenderer(ui: UiComponent, options?: UiRendererOptions): void;
|
|
13
26
|
/**
|
|
14
27
|
* Add a UI renderer associated with an entity. The UI will be automatically cleaned up
|
|
15
28
|
* when the entity is removed from the engine.
|
|
@@ -22,10 +35,12 @@ export interface ReactBasedUiSystem {
|
|
|
22
35
|
* @param entity - The entity to associate with this UI renderer. When the entity is removed,
|
|
23
36
|
* the UI renderer is automatically cleaned up.
|
|
24
37
|
* @param ui - The UI component to render
|
|
38
|
+
* @param options - Optional virtual size used for UI scale factor when main UI has none
|
|
25
39
|
*/
|
|
26
|
-
addUiRenderer(entity: Entity, ui: UiComponent): void;
|
|
40
|
+
addUiRenderer(entity: Entity, ui: UiComponent, options?: UiRendererOptions): void;
|
|
27
41
|
/**
|
|
28
42
|
* Remove a previously added UI renderer by its associated entity.
|
|
43
|
+
* It does not affect the main UI renderer.
|
|
29
44
|
* @param entity - The entity whose UI renderer should be removed
|
|
30
45
|
*/
|
|
31
46
|
removeUiRenderer(entity: Entity): void;
|
package/dist/system.js
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
import { EntityState } from '@dcl/ecs';
|
|
2
|
+
import * as ecsComponents from '@dcl/ecs/dist/components';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import { createReconciler } from './reconciler';
|
|
5
|
+
import { getUiScaleFactor, resetUiScaleFactor, setUiScaleFactor } from './components/utils';
|
|
4
6
|
/**
|
|
5
7
|
* @public
|
|
6
8
|
*/
|
|
7
9
|
export function createReactBasedUiSystem(engine, pointerSystem) {
|
|
8
10
|
const renderer = createReconciler(engine, pointerSystem);
|
|
9
11
|
let uiComponent = undefined;
|
|
12
|
+
let virtualSize = undefined;
|
|
10
13
|
const additionalRenderers = new Map();
|
|
14
|
+
const UiCanvasInformation = ecsComponents.UiCanvasInformation(engine);
|
|
15
|
+
// Unique owner to prevent other UI systems resetting this scale factor.
|
|
16
|
+
const uiScaleFactorOwner = Symbol('react-ecs-ui-scale');
|
|
17
|
+
function getActiveVirtualSize() {
|
|
18
|
+
// Main renderer options win; otherwise use the first additional renderer option.
|
|
19
|
+
if (virtualSize)
|
|
20
|
+
return virtualSize;
|
|
21
|
+
for (const entry of additionalRenderers.values()) {
|
|
22
|
+
if (entry.options)
|
|
23
|
+
return entry.options;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
11
27
|
function ReactBasedUiSystem() {
|
|
12
28
|
const components = [];
|
|
13
29
|
// Add main UI component
|
|
@@ -15,13 +31,13 @@ export function createReactBasedUiSystem(engine, pointerSystem) {
|
|
|
15
31
|
components.push(React.createElement(uiComponent, { key: '__main__' }));
|
|
16
32
|
}
|
|
17
33
|
const entitiesToRemove = [];
|
|
18
|
-
for (const [entity,
|
|
34
|
+
for (const [entity, entry] of additionalRenderers) {
|
|
19
35
|
// Check for entity-based cleanup
|
|
20
36
|
if (engine.getEntityState(entity) === EntityState.Removed) {
|
|
21
37
|
entitiesToRemove.push(entity);
|
|
22
38
|
}
|
|
23
39
|
else {
|
|
24
|
-
components.push(React.createElement(
|
|
40
|
+
components.push(React.createElement(entry.ui, { key: `__entity_${entity}__` }));
|
|
25
41
|
}
|
|
26
42
|
}
|
|
27
43
|
// Entity-based cleanup
|
|
@@ -36,19 +52,43 @@ export function createReactBasedUiSystem(engine, pointerSystem) {
|
|
|
36
52
|
renderer.update(null);
|
|
37
53
|
}
|
|
38
54
|
}
|
|
55
|
+
function UiScaleSystem() {
|
|
56
|
+
const activeVirtualSize = getActiveVirtualSize();
|
|
57
|
+
if (!activeVirtualSize) {
|
|
58
|
+
// Reset only if this system owns the scale factor.
|
|
59
|
+
resetUiScaleFactor(uiScaleFactorOwner);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const canvasInfo = UiCanvasInformation.getOrNull(engine.RootEntity);
|
|
63
|
+
if (!canvasInfo)
|
|
64
|
+
return;
|
|
65
|
+
const { width, height } = canvasInfo;
|
|
66
|
+
const { virtualWidth, virtualHeight } = activeVirtualSize;
|
|
67
|
+
if (!virtualWidth || !virtualHeight)
|
|
68
|
+
return;
|
|
69
|
+
const nextScale = Math.min(width / virtualWidth, height / virtualHeight);
|
|
70
|
+
if (Number.isFinite(nextScale) && nextScale !== getUiScaleFactor()) {
|
|
71
|
+
// Track ownership when updating to avoid cross-system conflicts.
|
|
72
|
+
setUiScaleFactor(nextScale, uiScaleFactorOwner);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
engine.addSystem(UiScaleSystem, 100e3 + 1, '@dcl/react-ecs-ui-scale');
|
|
39
76
|
engine.addSystem(ReactBasedUiSystem, 100e3, '@dcl/react-ecs');
|
|
40
77
|
return {
|
|
41
78
|
destroy() {
|
|
79
|
+
engine.removeSystem(UiScaleSystem);
|
|
42
80
|
engine.removeSystem(ReactBasedUiSystem);
|
|
81
|
+
resetUiScaleFactor(uiScaleFactorOwner);
|
|
43
82
|
for (const entity of renderer.getEntities()) {
|
|
44
83
|
engine.removeEntity(entity);
|
|
45
84
|
}
|
|
46
85
|
},
|
|
47
|
-
setUiRenderer(ui) {
|
|
86
|
+
setUiRenderer(ui, options) {
|
|
48
87
|
uiComponent = ui;
|
|
88
|
+
virtualSize = options;
|
|
49
89
|
},
|
|
50
|
-
addUiRenderer(entity, ui) {
|
|
51
|
-
additionalRenderers.set(entity, ui);
|
|
90
|
+
addUiRenderer(entity, ui, options) {
|
|
91
|
+
additionalRenderers.set(entity, { ui, options });
|
|
52
92
|
},
|
|
53
93
|
removeUiRenderer(entity) {
|
|
54
94
|
additionalRenderers.delete(entity);
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcl/react-ecs",
|
|
3
3
|
"description": "Decentraland ECS",
|
|
4
|
-
"version": "7.17.1-
|
|
4
|
+
"version": "7.17.1-21366395728.commit-ada88b6",
|
|
5
5
|
"author": "DCL",
|
|
6
6
|
"bugs": "https://github.com/decentraland/js-sdk-toolchain/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@dcl/ecs": "7.17.1-
|
|
8
|
+
"@dcl/ecs": "7.17.1-21366395728.commit-ada88b6",
|
|
9
9
|
"react": "^18.2.0",
|
|
10
10
|
"react-reconciler": "^0.29.0"
|
|
11
11
|
},
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"tsconfig": "./tsconfig.json"
|
|
41
41
|
},
|
|
42
42
|
"types": "./dist/index.d.ts",
|
|
43
|
-
"commit": "
|
|
43
|
+
"commit": "ada88b6fe8e93150056e0cade4b94e0c1e7dc850"
|
|
44
44
|
}
|