@antha/graphics-2d 0.15.1 → 0.16.0

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,3 +1,4 @@
1
+ import { type PartialWithUndefined, type RequireAtLeastOne } from '@augment-vir/common';
1
2
  import { type AnthaGraphics2dModState } from './antha-graphics-2d.mod.js';
2
3
  /**
3
4
  * The logical dimensions and scale of a virtual viewport.
@@ -15,6 +16,15 @@ export type VirtualViewport = {
15
16
  * @category Internal
16
17
  */
17
18
  export type VirtualViewportSize = Pick<VirtualViewport, 'height' | 'width'>;
19
+ /**
20
+ * Options for {@link createAnthaVirtualViewportMod}.
21
+ *
22
+ * @category Pre-Built Mods
23
+ */
24
+ export type AnthaVirtualViewportOptions = RequireAtLeastOne<{
25
+ virtualHeight: number;
26
+ virtualWidth: number;
27
+ }>;
18
28
  /**
19
29
  * State added by {@link createAnthaVirtualViewportMod}.
20
30
  *
@@ -28,9 +38,8 @@ export type AnthaVirtualViewportModState = AnthaGraphics2dModState & {
28
38
  *
29
39
  * @category Util
30
40
  */
31
- export declare function calculateVirtualViewport({ screenSize, virtualWidth, }: Readonly<{
41
+ export declare function calculateVirtualViewport({ screenSize, virtualHeight, virtualWidth, }: Readonly<PartialWithUndefined<AnthaVirtualViewportOptions> & {
32
42
  screenSize: Readonly<VirtualViewportSize>;
33
- virtualWidth: number;
34
43
  }>): {
35
44
  height: number;
36
45
  scale: number;
@@ -67,14 +76,8 @@ export declare function createVirtualViewportPixiOptions(): {
67
76
  resolution: number;
68
77
  };
69
78
  /**
70
- * A pre-built mod that scales an Antha UI and Pixi canvas to a logical viewport width.
79
+ * A pre-built mod that scales an Antha UI and Pixi canvas to a logical viewport.
71
80
  *
72
81
  * @category Pre-Built Mods
73
82
  */
74
- export declare function createAnthaVirtualViewportMod({ virtualWidth, }: Readonly<{
75
- /**
76
- * The reference width for your game screen. Any browser window wider or skinnier than this will
77
- * be scaled.
78
- */
79
- virtualWidth: number;
80
- }>): import("@antha/engine").AnthaMod<NoInfer<AnthaVirtualViewportModState>>;
83
+ export declare function createAnthaVirtualViewportMod({ virtualHeight, virtualWidth, }: Readonly<AnthaVirtualViewportOptions>): import("@antha/engine").AnthaMod<NoInfer<AnthaVirtualViewportModState>>;
@@ -1,19 +1,43 @@
1
1
  import { defineAnthaMod } from '@antha/engine';
2
+ import { assertWrap } from '@augment-vir/assert';
2
3
  /**
3
4
  * Calculates the logical viewport for a physical screen size.
4
5
  *
5
6
  * @category Util
6
7
  */
7
- export function calculateVirtualViewport({ screenSize, virtualWidth, }) {
8
- if (!screenSize.width || !virtualWidth) {
8
+ export function calculateVirtualViewport({ screenSize, virtualHeight, virtualWidth, }) {
9
+ if (!screenSize.height ||
10
+ !screenSize.width ||
11
+ virtualHeight === 0 ||
12
+ virtualWidth === 0 ||
13
+ (virtualHeight == undefined && virtualWidth == undefined)) {
9
14
  return undefined;
10
15
  }
11
- const scale = screenSize.width / virtualWidth;
12
- return {
13
- height: screenSize.height / scale,
14
- scale,
15
- width: virtualWidth,
16
- };
16
+ else if (virtualHeight == undefined) {
17
+ const definedVirtualWidth = assertWrap.isDefined(virtualWidth);
18
+ const scale = screenSize.width / definedVirtualWidth;
19
+ return {
20
+ height: screenSize.height / scale,
21
+ scale,
22
+ width: definedVirtualWidth,
23
+ };
24
+ }
25
+ else if (virtualWidth == undefined) {
26
+ const scale = screenSize.height / virtualHeight;
27
+ return {
28
+ height: virtualHeight,
29
+ scale,
30
+ width: screenSize.width / scale,
31
+ };
32
+ }
33
+ else {
34
+ const scale = Math.min(screenSize.height / virtualHeight, screenSize.width / virtualWidth);
35
+ return {
36
+ height: virtualHeight,
37
+ scale,
38
+ width: virtualWidth,
39
+ };
40
+ }
17
41
  }
18
42
  /**
19
43
  * Maps a pointer position from canvas coordinates into a virtual viewport.
@@ -46,11 +70,38 @@ function hasSameVirtualViewport({ previousVirtualViewport, virtualViewport, }) {
46
70
  Math.abs(previousVirtualViewport.scale - virtualViewport.scale) < 0.0001 &&
47
71
  previousVirtualViewport.width === virtualViewport.width);
48
72
  }
49
- function updateVirtualViewportHostElement({ hostElement, virtualViewport, }) {
50
- hostElement.style.height = `${100 / virtualViewport.scale}%`;
51
- hostElement.style.transform = `scale(${virtualViewport.scale})`;
73
+ function updateVirtualViewportHostElement({ hostElement, isFixedViewport, screenSize, virtualViewport, }) {
74
+ hostElement.style.height = isFixedViewport
75
+ ? `${virtualViewport.height}px`
76
+ : `${100 / virtualViewport.scale}%`;
77
+ hostElement.style.transform = getVirtualViewportHostTransform({
78
+ isFixedViewport,
79
+ screenSize,
80
+ virtualViewport,
81
+ });
52
82
  hostElement.style.transformOrigin = 'top left';
53
- hostElement.style.width = `${100 / virtualViewport.scale}%`;
83
+ hostElement.style.width = isFixedViewport
84
+ ? `${virtualViewport.width}px`
85
+ : `${100 / virtualViewport.scale}%`;
86
+ }
87
+ function getVirtualViewportHostTransform({ isFixedViewport, screenSize, virtualViewport, }) {
88
+ const horizontalOffset = isFixedViewport
89
+ ? (screenSize.width - virtualViewport.width * virtualViewport.scale) / 2
90
+ : 0;
91
+ const verticalOffset = isFixedViewport
92
+ ? (screenSize.height - virtualViewport.height * virtualViewport.scale) / 2
93
+ : 0;
94
+ return isFixedViewport
95
+ ? `translate(${horizontalOffset}px, ${verticalOffset}px) scale(${virtualViewport.scale})`
96
+ : `scale(${virtualViewport.scale})`;
97
+ }
98
+ function getVirtualViewportScreenSize({ hostElement, isFixedViewport, }) {
99
+ if (!isFixedViewport) {
100
+ return hostElement.getBoundingClientRect();
101
+ }
102
+ const rootNode = hostElement.getRootNode();
103
+ const viewportContainer = rootNode instanceof ShadowRoot ? rootNode.host : hostElement.parentElement || hostElement;
104
+ return viewportContainer.getBoundingClientRect();
54
105
  }
55
106
  function resetVirtualViewportHostElement({ hostElement, }) {
56
107
  hostElement.style.removeProperty('height');
@@ -59,11 +110,12 @@ function resetVirtualViewportHostElement({ hostElement, }) {
59
110
  hostElement.style.removeProperty('width');
60
111
  }
61
112
  /**
62
- * A pre-built mod that scales an Antha UI and Pixi canvas to a logical viewport width.
113
+ * A pre-built mod that scales an Antha UI and Pixi canvas to a logical viewport.
63
114
  *
64
115
  * @category Pre-Built Mods
65
116
  */
66
- export function createAnthaVirtualViewportMod({ virtualWidth, }) {
117
+ export function createAnthaVirtualViewportMod({ virtualHeight, virtualWidth, }) {
118
+ const isFixedViewport = !!virtualHeight && !!virtualWidth;
67
119
  return defineAnthaMod({
68
120
  modName: 'antha-virtual-viewport',
69
121
  cleanup({ hostElement, state }) {
@@ -73,8 +125,13 @@ export function createAnthaVirtualViewportMod({ virtualWidth, }) {
73
125
  state.virtualViewport = undefined;
74
126
  },
75
127
  execute({ hostElement, state }) {
128
+ const screenSize = getVirtualViewportScreenSize({
129
+ hostElement,
130
+ isFixedViewport,
131
+ });
76
132
  const virtualViewport = calculateVirtualViewport({
77
- screenSize: hostElement.getBoundingClientRect(),
133
+ screenSize,
134
+ virtualHeight,
78
135
  virtualWidth,
79
136
  });
80
137
  if (!virtualViewport) {
@@ -83,10 +140,18 @@ export function createAnthaVirtualViewportMod({ virtualWidth, }) {
83
140
  const hasViewportChanged = !hasSameVirtualViewport({
84
141
  previousVirtualViewport: state.virtualViewport,
85
142
  virtualViewport,
86
- }) || hostElement.style.transform !== `scale(${virtualViewport.scale})`;
143
+ }) ||
144
+ hostElement.style.transform !==
145
+ getVirtualViewportHostTransform({
146
+ isFixedViewport,
147
+ screenSize,
148
+ virtualViewport,
149
+ });
87
150
  if (hasViewportChanged) {
88
151
  updateVirtualViewportHostElement({
89
152
  hostElement,
153
+ isFixedViewport,
154
+ screenSize,
90
155
  virtualViewport,
91
156
  });
92
157
  state.virtualViewport = virtualViewport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antha/graphics-2d",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "An Antha mod for rendering 2D graphics to a canvas.",
5
5
  "keywords": [
6
6
  "vir",
@@ -31,8 +31,8 @@
31
31
  "scripts": {
32
32
  "compile": "virmator compile",
33
33
  "docs": "virmator docs",
34
- "test": "virmator test web",
35
- "test:coverage": "NODE_OPTIONS=--import=tsx npm test coverage",
34
+ "test": "NODE_OPTIONS=--import=tsx virmator test web",
35
+ "test:coverage": "npm test coverage",
36
36
  "test:docs": "virmator docs check"
37
37
  },
38
38
  "dependencies": {
@@ -40,8 +40,8 @@
40
40
  "@augment-vir/common": "^32.3.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@antha/engine": "^0.15.1",
44
- "@antha/web-test-runner-plugin-pixi": "^0.15.1",
43
+ "@antha/engine": "^0.16.0",
44
+ "@antha/web-test-runner-plugin-pixi": "^0.16.0",
45
45
  "@augment-vir/test": "^32.3.0",
46
46
  "@electrovir/color": "^2.0.0",
47
47
  "@web/dev-server-esbuild": "^2.0.0",
@@ -52,7 +52,7 @@
52
52
  "vira": "32.0.0"
53
53
  },
54
54
  "peerDependencies": {
55
- "@antha/engine": "^0.15.1",
55
+ "@antha/engine": "^0.16.0",
56
56
  "@electrovir/color": "^2",
57
57
  "element-vir": "^27",
58
58
  "pixi.js": "^8",