@gjsify/example-dom-three-loader-ldraw 0.55.0 → 0.56.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.
- package/dist/browser.js +151 -48
- package/dist/index.html +0 -1
- package/dist/webgl.css +3 -3
- package/package.json +6 -6
- package/src/browser/browser.ts +46 -81
- package/src/browser/index.html +0 -1
- package/src/browser/webgl.css +3 -3
package/dist/index.html
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>LDraw Loader — gjsify</title>
|
|
6
6
|
<link rel="stylesheet" href="./webgl.css" type="text/css" />
|
|
7
|
-
<link rel="stylesheet" href="./browser.css" type="text/css" />
|
|
8
7
|
<script src="./browser.js" type="module" defer></script>
|
|
9
8
|
</head>
|
|
10
9
|
<body></body>
|
package/dist/webgl.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Page chrome for the STANDALONE `index.html` only — how the window is centred
|
|
2
|
-
on an otherwise empty page. The window's own layout (
|
|
3
|
-
deliberately NOT here: `browser.ts`
|
|
2
|
+
on an otherwise empty page. The window's own layout (controls vs. GL area) is
|
|
3
|
+
deliberately NOT here: `browser.ts` mounts the `.blp` tree and
|
|
4
4
|
inline-styles the GL container, because the website embeds `mount()` without
|
|
5
5
|
ever loading this file, and a layout that lives here is a layout the embed
|
|
6
6
|
does not get. */
|
|
@@ -21,7 +21,7 @@ html, body {
|
|
|
21
21
|
justify-content: center;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
adw-window {
|
|
24
|
+
adw-application-window {
|
|
25
25
|
max-width: 100%;
|
|
26
26
|
max-height: 100%;
|
|
27
27
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/example-dom-three-loader-ldraw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.0",
|
|
4
4
|
"description": "Three.js LDraw loader showcase ported from refs/three/examples/webgl_loader_ldraw.html with Adwaita controls",
|
|
5
5
|
"main": "dist/gjs.js",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"build:assets": "gjsify copy src/browser/index.html src/browser/webgl.css src/assets dist/"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@gjsify/webgl": "^0.
|
|
31
|
+
"@gjsify/webgl": "^0.56.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@girs/adw-1": "5.4.0",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"@girs/gjs": "5.4.0",
|
|
37
37
|
"@girs/gobject-2.0": "5.4.0",
|
|
38
38
|
"@girs/gtk-4.0": "5.4.0",
|
|
39
|
-
"@gjsify/adwaita-web": "^0.
|
|
40
|
-
"@gjsify/cli": "^0.
|
|
41
|
-
"@gjsify/devtools": "^0.
|
|
39
|
+
"@gjsify/adwaita-web": "^0.56.0",
|
|
40
|
+
"@gjsify/cli": "^0.56.0",
|
|
41
|
+
"@gjsify/devtools": "^0.56.0",
|
|
42
42
|
"@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
|
|
43
|
-
"@gjsify/vite-plugin-blueprint": "^0.
|
|
43
|
+
"@gjsify/vite-plugin-blueprint": "^0.56.0",
|
|
44
44
|
"@types/node": "^25.9.2",
|
|
45
45
|
"@types/three": "^0.185.0",
|
|
46
46
|
"http-server": "^14.1.1",
|
package/src/browser/browser.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Browser UI for three-loader-ldraw example.
|
|
2
|
-
//
|
|
2
|
+
// The widget tree is the GJS window's own `ldraw-window.blp`, projected and mounted by
|
|
3
|
+
// @gjsify/adwaita-web — one authored file, so the control groups and the GL area cannot drift
|
|
4
|
+
// from the GTK build.
|
|
3
5
|
// Ported from refs/three/examples/webgl_loader_ldraw.html
|
|
4
6
|
// Original: MIT license, three.js authors (https://threejs.org)
|
|
5
7
|
// This software uses the LDraw Parts Library (http://www.ldraw.org), CC BY 2.0.
|
|
@@ -9,14 +11,14 @@
|
|
|
9
11
|
// dead twice over: under this build css-as-string turns it into a string a
|
|
10
12
|
// side-effect import discards, and under a real CSS pipeline it injects the same
|
|
11
13
|
// rules a SECOND time (`style.css.d.ts` says so).
|
|
12
|
-
import '@gjsify/adwaita-web';
|
|
14
|
+
import { mountSharedTree } from '@gjsify/adwaita-web';
|
|
13
15
|
// A showcase is served to whatever browser opens it, so it cannot assume the host has
|
|
14
16
|
// Adwaita Sans the way a GNOME desktop does. `import '@gjsify/adwaita-web'` names the
|
|
15
17
|
// family and ships no `@font-face`, so without this call the chrome renders in the host's
|
|
16
18
|
// default sans on macOS, on Windows and on any Linux that is not GNOME — and looks right
|
|
17
19
|
// only on the machine it was written on.
|
|
18
20
|
import { applyAdwaitaFonts } from '@gjsify/adwaita-web/fonts';
|
|
19
|
-
import
|
|
21
|
+
import tree from '../gjs/ldraw-window.blp?shared-tree';
|
|
20
22
|
import { start, MODEL_LIST, DEFAULT_MODEL_INDEX, type LDrawDemo } from '../three-demo.js';
|
|
21
23
|
|
|
22
24
|
// Idempotent, and a no-op where there is no `document` — so a build-time import of this
|
|
@@ -38,84 +40,50 @@ export interface ShowcaseHandle {
|
|
|
38
40
|
readonly isPaused: boolean;
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
/** The one element of the mounted tree with this authored id. */
|
|
44
|
+
function byId(root: HTMLElement, id: string): HTMLElement {
|
|
45
|
+
const el = root.querySelector<HTMLElement>(`#${id}`);
|
|
46
|
+
if (el === null) throw new Error(`ldraw-window.blp declares no object with the id "${id}"`);
|
|
47
|
+
return el;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The values `ldraw-window.ts` sets in TypeScript because Blueprint has no spelling for them
|
|
52
|
+
* here, so they are not in the tree and this is the browser's copy. Keep the two in step.
|
|
53
|
+
*
|
|
54
|
+
* | id | attribute | value | GTK counterpart |
|
|
55
|
+
* | ------------------ | ------------ | --------------------------------------- | --------------------------------------------- |
|
|
56
|
+
* | `modelRow` | `model` | `MODEL_LIST` names | `set_model(Gtk.StringList.new(…))` |
|
|
57
|
+
* | `modelRow` | `selected` | `DEFAULT_MODEL_INDEX` | `set_selected(DEFAULT_MODEL_INDEX)` |
|
|
58
|
+
* | `buildingStepRow` | `adjustment` | `lower 0, upper 0, stepIncrement 1, value 0` | `set_adjustment(new Gtk.Adjustment(…))` |
|
|
59
|
+
*
|
|
60
|
+
* `upper` and `value` of the building step follow the loaded model (see the `start` callback).
|
|
61
|
+
*/
|
|
62
|
+
const TS_ONLY = {
|
|
63
|
+
modelRow: { model: MODEL_LIST.map((m) => m.name), selected: DEFAULT_MODEL_INDEX },
|
|
64
|
+
buildingStepRow: { lower: 0, upper: 0, stepIncrement: 1, value: 0 },
|
|
65
|
+
};
|
|
66
|
+
|
|
41
67
|
export function mount(container: HTMLElement, options?: MountOptions): ShowcaseHandle {
|
|
42
68
|
const { assetBase } = options ?? {};
|
|
43
69
|
|
|
44
|
-
const win =
|
|
45
|
-
|
|
46
|
-
win
|
|
70
|
+
const { root: win } = mountSharedTree(tree, { into: container });
|
|
71
|
+
|
|
72
|
+
const modelRow = byId(win, 'modelRow');
|
|
73
|
+
const flatColorsRow = byId(win, 'flatColorsRow');
|
|
74
|
+
const mergeModelRow = byId(win, 'mergeModelRow');
|
|
75
|
+
const smoothNormalsRow = byId(win, 'smoothNormalsRow');
|
|
76
|
+
const buildingStepRow = byId(win, 'buildingStepRow');
|
|
77
|
+
const displayLinesRow = byId(win, 'displayLinesRow');
|
|
78
|
+
const conditionalLinesRow = byId(win, 'conditionalLinesRow');
|
|
47
79
|
|
|
48
|
-
|
|
49
|
-
|
|
80
|
+
modelRow.setAttribute('model', JSON.stringify(TS_ONLY.modelRow.model));
|
|
81
|
+
modelRow.setAttribute('selected', String(TS_ONLY.modelRow.selected));
|
|
82
|
+
buildingStepRow.setAttribute('adjustment', JSON.stringify(TS_ONLY.buildingStepRow));
|
|
50
83
|
|
|
51
84
|
// A showcase has two hosts — the standalone page and the website embed — and only the former
|
|
52
85
|
// loads `browser/webgl.css`, so the layout has to live here rather than in that stylesheet.
|
|
53
|
-
const
|
|
54
|
-
splitView.setAttribute('min-sidebar-width', '280');
|
|
55
|
-
splitView.setAttribute('max-sidebar-width', '400');
|
|
56
|
-
splitView.setAttribute('sidebar-width-fraction', '0.30');
|
|
57
|
-
splitView.setAttribute('show-sidebar', '');
|
|
58
|
-
|
|
59
|
-
// Inline styles for the same reason as the GL container below.
|
|
60
|
-
const sidebarContent = document.createElement('div');
|
|
61
|
-
sidebarContent.setAttribute('slot', 'sidebar');
|
|
62
|
-
sidebarContent.className = 'adw-sidebar-content';
|
|
63
|
-
sidebarContent.style.cssText = 'padding:12px;display:flex;flex-direction:column;gap:12px';
|
|
64
|
-
|
|
65
|
-
const modelGroup = document.createElement('adw-preferences-group');
|
|
66
|
-
modelGroup.setAttribute('title', 'Model');
|
|
67
|
-
|
|
68
|
-
const modelRow = document.createElement('adw-combo-row');
|
|
69
|
-
modelRow.setAttribute('title', 'Model');
|
|
70
|
-
modelRow.setAttribute('items', JSON.stringify(MODEL_LIST.map((m) => m.name)));
|
|
71
|
-
modelRow.setAttribute('selected', String(DEFAULT_MODEL_INDEX));
|
|
72
|
-
|
|
73
|
-
modelGroup.append(modelRow);
|
|
74
|
-
|
|
75
|
-
// Rendering group
|
|
76
|
-
const renderGroup = document.createElement('adw-preferences-group');
|
|
77
|
-
renderGroup.setAttribute('title', 'Rendering');
|
|
78
|
-
|
|
79
|
-
const flatColorsRow = document.createElement('adw-switch-row');
|
|
80
|
-
flatColorsRow.setAttribute('title', 'Flat Colors');
|
|
81
|
-
|
|
82
|
-
const mergeModelRow = document.createElement('adw-switch-row');
|
|
83
|
-
mergeModelRow.setAttribute('title', 'Merge Model');
|
|
84
|
-
|
|
85
|
-
const smoothNormalsRow = document.createElement('adw-switch-row');
|
|
86
|
-
smoothNormalsRow.setAttribute('title', 'Smooth Normals');
|
|
87
|
-
smoothNormalsRow.setAttribute('active', '');
|
|
88
|
-
|
|
89
|
-
renderGroup.append(flatColorsRow, mergeModelRow, smoothNormalsRow);
|
|
90
|
-
|
|
91
|
-
// Display group
|
|
92
|
-
const displayGroup = document.createElement('adw-preferences-group');
|
|
93
|
-
displayGroup.setAttribute('title', 'Display');
|
|
94
|
-
|
|
95
|
-
const buildingStepRow = document.createElement('adw-spin-row');
|
|
96
|
-
buildingStepRow.setAttribute('title', 'Building Step');
|
|
97
|
-
buildingStepRow.setAttribute('min', '0');
|
|
98
|
-
buildingStepRow.setAttribute('max', '0');
|
|
99
|
-
buildingStepRow.setAttribute('step', '1');
|
|
100
|
-
buildingStepRow.setAttribute('value', '0');
|
|
101
|
-
|
|
102
|
-
const displayLinesRow = document.createElement('adw-switch-row');
|
|
103
|
-
displayLinesRow.setAttribute('title', 'Display Lines');
|
|
104
|
-
displayLinesRow.setAttribute('active', '');
|
|
105
|
-
|
|
106
|
-
const conditionalLinesRow = document.createElement('adw-switch-row');
|
|
107
|
-
conditionalLinesRow.setAttribute('title', 'Conditional Lines');
|
|
108
|
-
conditionalLinesRow.setAttribute('active', '');
|
|
109
|
-
|
|
110
|
-
displayGroup.append(buildingStepRow, displayLinesRow, conditionalLinesRow);
|
|
111
|
-
|
|
112
|
-
sidebarContent.append(modelGroup, renderGroup, displayGroup);
|
|
113
|
-
|
|
114
|
-
// GL container (content slot) — inline styles so the showcase
|
|
115
|
-
// is self-contained and works regardless of host CSS.
|
|
116
|
-
const glContainer = document.createElement('div');
|
|
117
|
-
glContainer.setAttribute('slot', 'content');
|
|
118
|
-
glContainer.id = 'gl-area-container';
|
|
86
|
+
const glContainer = byId(win, 'glAreaContainer');
|
|
119
87
|
glContainer.style.cssText = 'flex:1;position:relative;min-width:0;min-height:0';
|
|
120
88
|
|
|
121
89
|
const canvas = document.createElement('canvas');
|
|
@@ -123,10 +91,6 @@ export function mount(container: HTMLElement, options?: MountOptions): ShowcaseH
|
|
|
123
91
|
canvas.style.cssText = 'display:block;width:100%;height:100%;position:absolute;inset:0';
|
|
124
92
|
glContainer.append(canvas);
|
|
125
93
|
|
|
126
|
-
splitView.append(sidebarContent, glContainer);
|
|
127
|
-
win.append(headerBar, splitView);
|
|
128
|
-
container.append(win);
|
|
129
|
-
|
|
130
94
|
// Sync canvas size
|
|
131
95
|
new ResizeObserver(() => {
|
|
132
96
|
canvas.width = glContainer.clientWidth;
|
|
@@ -138,9 +102,10 @@ export function mount(container: HTMLElement, options?: MountOptions): ShowcaseH
|
|
|
138
102
|
// Start three.js
|
|
139
103
|
const demo = start(canvas, { assetBase }, (numSteps) => {
|
|
140
104
|
// Update building step range when model loads
|
|
141
|
-
buildingStepRow.setAttribute(
|
|
142
|
-
|
|
143
|
-
|
|
105
|
+
buildingStepRow.setAttribute(
|
|
106
|
+
'adjustment',
|
|
107
|
+
JSON.stringify({ ...TS_ONLY.buildingStepRow, upper: numSteps - 1, value: numSteps - 1 }),
|
|
108
|
+
);
|
|
144
109
|
});
|
|
145
110
|
|
|
146
111
|
connectControls(
|
package/src/browser/index.html
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>LDraw Loader — gjsify</title>
|
|
6
6
|
<link rel="stylesheet" href="./webgl.css" type="text/css" />
|
|
7
|
-
<link rel="stylesheet" href="./browser.css" type="text/css" />
|
|
8
7
|
<script src="./browser.js" type="module" defer></script>
|
|
9
8
|
</head>
|
|
10
9
|
<body></body>
|
package/src/browser/webgl.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Page chrome for the STANDALONE `index.html` only — how the window is centred
|
|
2
|
-
on an otherwise empty page. The window's own layout (
|
|
3
|
-
deliberately NOT here: `browser.ts`
|
|
2
|
+
on an otherwise empty page. The window's own layout (controls vs. GL area) is
|
|
3
|
+
deliberately NOT here: `browser.ts` mounts the `.blp` tree and
|
|
4
4
|
inline-styles the GL container, because the website embeds `mount()` without
|
|
5
5
|
ever loading this file, and a layout that lives here is a layout the embed
|
|
6
6
|
does not get. */
|
|
@@ -21,7 +21,7 @@ html, body {
|
|
|
21
21
|
justify-content: center;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
adw-window {
|
|
24
|
+
adw-application-window {
|
|
25
25
|
max-width: 100%;
|
|
26
26
|
max-height: 100%;
|
|
27
27
|
}
|