@volter/editor-blender 0.1.8 → 0.1.10
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/contributions/blender-header-menus.tsx +4 -9
- package/contributions/blender-icons.source.mjs +74 -6
- package/contributions/blender-outliner-authoring.ts +10 -21
- package/contributions/blender-palette.source.mjs +16 -5
- package/contributions/blender-properties-view.tsx +28 -9
- package/contributions/blender-runtime-skin.ts +6 -0
- package/contributions/blender-runtime.document.tsx +219 -23
- package/contributions/blender.command.ts +5 -1
- package/contributions/blender.environment.ts +32 -0
- package/contributions/blender.icons.json +22 -2
- package/contributions/blender.icons.traced.json +28 -0
- package/contributions/blender.keymap.ts +33 -0
- package/contributions/blender.palette.json +6 -0
- package/contributions/blender.status.tsx +2 -6
- package/contributions/blender.style.ts +30 -89
- package/contributions/model.layout.ts +7 -7
- package/contributions/models.finder.ts +16 -0
- package/contributions/sculpt.layout.ts +3 -0
- package/contributions/shading.layout.ts +3 -0
- package/contributions/studiolights/world/city.exr +0 -0
- package/contributions/studiolights/world/courtyard.exr +0 -0
- package/contributions/studiolights/world/forest.exr +0 -0
- package/contributions/studiolights/world/interior.exr +0 -0
- package/contributions/studiolights/world/license.txt +15 -0
- package/contributions/studiolights/world/night.exr +0 -0
- package/contributions/studiolights/world/studio.exr +0 -0
- package/contributions/studiolights/world/sunrise.exr +0 -0
- package/contributions/studiolights/world/sunset.exr +0 -0
- package/contributions/uv-editing.layout.ts +3 -0
- package/dist-node/serving.mjs +624 -0
- package/host/blender-runtime-host.ts +11 -1
- package/node/blender-mcp.ts +2 -2
- package/package.json +20 -10
- package/serving/blender-routes.ts +427 -0
- package/serving/blender-wasm-artifact.ts +449 -0
- package/serving/index.ts +10 -0
- package/src/layouts.tsx +4 -5
- package/src/presentation.ts +111 -0
- package/src/regions.ts +59 -0
|
@@ -175,97 +175,38 @@ export const style: StyleContribution = {
|
|
|
175
175
|
// applied TWICE; see `theme.ts`'s `areaEmbossValue`.
|
|
176
176
|
areaEmboss: 8.2,
|
|
177
177
|
},
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
upAxis: 'z',
|
|
209
|
-
// BLENDER'S SELECT BOX IS A TOUCH TEST — its object-mode box select
|
|
210
|
-
// reads the object-id buffer under the rectangle, so any drawn part of
|
|
211
|
-
// an object inside it selects that object. The editor's own answer is
|
|
212
|
-
// containment, for its own measured reason; see the field.
|
|
213
|
-
boxSelect: 'touch',
|
|
214
|
-
},
|
|
178
|
+
},
|
|
179
|
+
stage: {
|
|
180
|
+
// BLENDER'S GIZMO IS A CONSTANT SCREEN SIZE (owner, 2026-09-21: "is
|
|
181
|
+
// gizmo perhaps the wrong size?"). `U.gizmo_size` is 75
|
|
182
|
+
// (`DNA_userdef_types.h:1095`; Preferences > Viewport > Gizmos > Size,
|
|
183
|
+
// `rna_userdef.cc:5415-5419`, range 10..200), and it is px PER GIZMO
|
|
184
|
+
// UNIT: `wm_gizmo.cc:450-474` sets `scale_final = scale_basis *
|
|
185
|
+
// UI_SCALE_FAC * U.gizmo_size * ED_view3d_pixel_size_no_ui_scale(...)`,
|
|
186
|
+
// whose last term is world units per DEVICE px against a
|
|
187
|
+
// `UI_SCALE_FAC` of device px per UI px — so one gizmo unit is 75 CSS
|
|
188
|
+
// px whatever the display scale (read back from the engine's own pin
|
|
189
|
+
// on this box: `ui_scale=2.0 pixel_size=2.0 gizmo_size=75`).
|
|
190
|
+
gizmoSize: 75,
|
|
191
|
+
// A resting handle at 0.6 opacity, a highlighted one opaque in its own colour
|
|
192
|
+
// (`transform_gizmo_3d.cc`, `gizmo_get_axis_color`).
|
|
193
|
+
gizmoOpacity: 0.6,
|
|
194
|
+
// BLENDER'S OUTLINE IS A HARD LINE, and hidden parts are not drawn: four device pixels
|
|
195
|
+
// of orange around the cube in `modeling-object-selected.png` (at 2x), no halo.
|
|
196
|
+
outlineStyle: 'crisp',
|
|
197
|
+
outlineWidth: 4,
|
|
198
|
+
outlineHidden: false,
|
|
199
|
+
// BLENDER'S FLOOR LINES, in device pixels, measured across one scanline of
|
|
200
|
+
// `modeling-object-none.png` at device resolution: the 1 m line is 4 px at half rise and
|
|
201
|
+
// plateaus at 83, the 10 m line is 6 px and plateaus at 101 — so the major line is wider
|
|
202
|
+
// (2.25 against 1.5) and carried (102 − 63) / (84 − 63) past the minor's colour from the
|
|
203
|
+
// background they share. Stated here, the look's, since the editor's own floor is a
|
|
204
|
+
// single hairline level.
|
|
205
|
+
gridLineWidth: 1.5,
|
|
206
|
+
gridMajorWidth: 2.25,
|
|
207
|
+
gridMajorContrast: 39 / 21,
|
|
215
208
|
},
|
|
216
209
|
},
|
|
217
210
|
icons,
|
|
218
|
-
regions: {
|
|
219
|
-
workspaceTabs: 'shown',
|
|
220
|
-
// Blender has no document tab strip over its areas (the host's own note
|
|
221
|
-
// in `workspace-presets.ts` says so; the bundle contradicted it).
|
|
222
|
-
header: 'shown',
|
|
223
|
-
shelf: 'shown',
|
|
224
|
-
inspector: 'properties',
|
|
225
|
-
// Measured on `modeling.png`: Blender's top-right corner carries two quiet
|
|
226
|
-
// wells (Scene, ViewLayer) and nothing brighter than the 216 its labels
|
|
227
|
-
// ink at. Ours drew a yellow FPS/ms readout, an orange sparkline and a lit
|
|
228
|
-
// audio meter there — the brightest, highest-chroma thing in the frame and
|
|
229
|
-
// the first place the eye lands. The numbers keep their door (the Profiler
|
|
230
|
-
// utility, which the readout's own tooltip names).
|
|
231
|
-
telemetry: 'hidden',
|
|
232
|
-
// Measured on `outliner.png`: Scene Collection, Collection, Camera, Cube
|
|
233
|
-
// and Light each carry their NAME and nothing after it — no type text
|
|
234
|
-
// anywhere in the frame. The type is the GLYPH, which is why the glyph is
|
|
235
|
-
// coloured by category in the first place; a row that also spelled the
|
|
236
|
-
// type would say it twice. Ours printed `Hero Box ·HeroBox` at
|
|
237
|
-
// `content.dim` in a 10px face, one `space-2` past the name.
|
|
238
|
-
hierarchyTypeSuffix: 'hidden',
|
|
239
|
-
// Measured across all three Outliner frames — `outliner.png` (edit mode),
|
|
240
|
-
// `modeling-object-none.png` (object mode, nothing selected) and
|
|
241
|
-
// `modeling-object-selected.png` (object mode, everything selected):
|
|
242
|
-
// Blender draws NO rule, dotted or solid, under any name in that panel, in
|
|
243
|
-
// any selection state. Ours drew an orange dotted rule under every
|
|
244
|
-
// component-instance name — six of this scaffold's eleven rows — which is a
|
|
245
|
-
// mark with no counterpart in the frame at all. The instance fact keeps its
|
|
246
|
-
// doors (the label's tooltip, Go to Callsite / Open Component Source, the
|
|
247
|
-
// inspector's component sections); only the paint yields.
|
|
248
|
-
hierarchyInstanceRule: 'hidden',
|
|
249
|
-
// Measured on `outliner.png`: every object row carries an EYE (CSS ink
|
|
250
|
-
// 257.5-270.5, 32 px in from the area's right edge) and a render CAMERA
|
|
251
|
-
// (277.5-290.5, 12 px in) on a 20 px column pitch, and no lock glyph
|
|
252
|
-
// anywhere — Blender's Disable Selection column is off by default. Ours
|
|
253
|
-
// drew a lock 29-41 px in and the eye 6-18 px in, so the LOCK was sitting
|
|
254
|
-
// in Blender's eye column and the eye outboard of its camera column. The
|
|
255
|
-
// lock goes, and the render column is reserved blank so the eye lands on
|
|
256
|
-
// Blender's own; `workspace-regions.ts` carries why it stays blank.
|
|
257
|
-
hierarchyRestrictions: 'viewport+render',
|
|
258
|
-
// Measured at native 2x on `outliner.png` AND on the Properties area of
|
|
259
|
-
// `modeling-edit-none.png` — device x relative to each area's own left
|
|
260
|
-
// edge, and the two agree to half a pixel: every Blender area begins with
|
|
261
|
-
// an EDITOR-TYPE WELL at x 17..80, i.e. 8.5 CSS in and 32 CSS wide, 20
|
|
262
|
-
// tall, its glyph and a chevron inside a 1 px `#3c3c3c` outline over a
|
|
263
|
-
// `#272727` inner. It is there whether the area holds one editor or a
|
|
264
|
-
// dozen, and its dropdown is how an area changes editor. Ours began with
|
|
265
|
-
// a 203 px strip of WORDS, which is what squeezed the Outliner's search
|
|
266
|
-
// to 64 px against Blender's 115, truncated the third tab to `Libr`, and
|
|
267
|
-
// left the Properties area — a lone panel declaring no header controls —
|
|
268
|
-
// with no header band at all.
|
|
269
|
-
},
|
|
270
211
|
palette,
|
|
271
212
|
};
|
|
@@ -7,20 +7,20 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { WorkspaceLayoutContribution } from '@volter/editor-sdk/looks';
|
|
10
|
+
import { BLENDER_REGIONS } from '../src/regions';
|
|
10
11
|
|
|
11
12
|
export const point = 'workspace.layout';
|
|
12
13
|
export const layout: WorkspaceLayoutContribution = {
|
|
13
14
|
id: 'model',
|
|
14
15
|
title: 'Model',
|
|
15
16
|
description: 'Blender-shaped modeling: a dominant document, outliner above properties.',
|
|
16
|
-
// No `tabs` here
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// has none). Leave a region unstated unless this workspace genuinely needs
|
|
22
|
-
// it different from the host default.
|
|
17
|
+
// No `tabs` here: the workspace layer sits above the person's own choice
|
|
18
|
+
// (`workspace-regions.ts`), so a stated region shadows it. Leave a region
|
|
19
|
+
// unstated unless this workspace genuinely needs it different from the host
|
|
20
|
+
// default.
|
|
21
|
+
// Blender's areas beneath this workspace's own (`../src/regions.ts`).
|
|
23
22
|
regions: {
|
|
23
|
+
...BLENDER_REGIONS,
|
|
24
24
|
header: 'shown',
|
|
25
25
|
shelf: 'shown',
|
|
26
26
|
inspector: 'properties',
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
*
|
|
17
17
|
* documents: { find: [{ finder: 'modelsFromBlendFiles', include: ['src/models/**\/*.blend'] }] }
|
|
18
18
|
*
|
|
19
|
+
* THE SESSION'S OWN MODEL. A project that holds no `.blend` of its own still
|
|
20
|
+
* needs ONE model — it is what `blender-start` presents into and what a first
|
|
21
|
+
* bpy call models in, saved to the session's default `models/model.blend` — so
|
|
22
|
+
* when the selection finds no file, the finder lists the standing
|
|
23
|
+
* `blender:runtime` entry instead. Never beside a real model.
|
|
24
|
+
*
|
|
19
25
|
* This module is a plain object the HOST registers; it mounts no UI. It reads
|
|
20
26
|
* the project only through `input.files` — the PATHS matching those globs.
|
|
21
27
|
* Deliberately not `input.sources`: a `.blend` is binary, there is nothing in
|
|
@@ -54,6 +60,16 @@ export const finder = {
|
|
|
54
60
|
source: { path },
|
|
55
61
|
});
|
|
56
62
|
}
|
|
63
|
+
if (entries.length === 0) {
|
|
64
|
+
entries.push({
|
|
65
|
+
id: 'blender:runtime',
|
|
66
|
+
label: 'Model',
|
|
67
|
+
kind: 'model',
|
|
68
|
+
region: null,
|
|
69
|
+
authorable: true,
|
|
70
|
+
reach: { kind: 'root-mount' as const },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
57
73
|
return { entries, notes };
|
|
58
74
|
},
|
|
59
75
|
} as const;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { WorkspaceLayoutContribution } from '@volter/editor-sdk/looks';
|
|
9
|
+
import { BLENDER_REGIONS } from '../src/regions';
|
|
9
10
|
|
|
10
11
|
export const point = 'workspace.layout';
|
|
11
12
|
export const layout: WorkspaceLayoutContribution = {
|
|
@@ -16,7 +17,9 @@ export const layout: WorkspaceLayoutContribution = {
|
|
|
16
17
|
requires: { documentKind: 'model' },
|
|
17
18
|
// `tabs` unstated — see `model.layout.ts`: the workspace layer wins over the
|
|
18
19
|
// style bundle, so restating the host default shadows it.
|
|
20
|
+
// Blender's areas beneath this workspace's own (`../src/regions.ts`).
|
|
19
21
|
regions: {
|
|
22
|
+
...BLENDER_REGIONS,
|
|
20
23
|
header: 'shown',
|
|
21
24
|
shelf: 'shown',
|
|
22
25
|
inspector: 'properties',
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
*/
|
|
54
54
|
|
|
55
55
|
import type { WorkspaceLayoutContribution } from '@volter/editor-sdk/looks';
|
|
56
|
+
import { BLENDER_REGIONS } from '../src/regions';
|
|
56
57
|
|
|
57
58
|
export const point = 'workspace.layout';
|
|
58
59
|
export const layout: WorkspaceLayoutContribution = {
|
|
@@ -64,7 +65,9 @@ export const layout: WorkspaceLayoutContribution = {
|
|
|
64
65
|
// layer wins over the style bundle, so restating the host default would
|
|
65
66
|
// silently shadow `blender.style.ts`'s `tabs: 'hidden'` and paint a tab row
|
|
66
67
|
// Blender does not have.
|
|
68
|
+
// Blender's areas beneath this workspace's own (`../src/regions.ts`).
|
|
67
69
|
regions: {
|
|
70
|
+
...BLENDER_REGIONS,
|
|
68
71
|
header: 'shown',
|
|
69
72
|
shelf: 'shown',
|
|
70
73
|
inspector: 'properties',
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
All HDRIs are licensed as CC0.
|
|
2
|
+
|
|
3
|
+
These were created by Greg Zaal (Poly Haven https://polyhaven.com).
|
|
4
|
+
Originals used for each HDRI:
|
|
5
|
+
- City: https://polyhaven.com/a/portland_landing_pad
|
|
6
|
+
- Courtyard: https://polyhaven.com/a/courtyard
|
|
7
|
+
- Forest: https://polyhaven.com/a/ninomaru_teien
|
|
8
|
+
- Interior: https://polyhaven.com/a/hotel_room
|
|
9
|
+
- Night: Probably https://polyhaven.com/a/moonless_golf
|
|
10
|
+
- Studio: Probably https://polyhaven.com/a/studio_small_01
|
|
11
|
+
- Sunrise: https://polyhaven.com/a/spruit_sunrise
|
|
12
|
+
- Sunset: https://polyhaven.com/a/venice_sunset
|
|
13
|
+
|
|
14
|
+
1K resolution of each was taken, and compressed with oiiotool:
|
|
15
|
+
oiiotool input.exr --ch R,G,B -d float --compression dwab:300 --clamp:min=0.0:max=32000.0 -o output.exr
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
48
|
import type { WorkspaceLayoutContribution } from '@volter/editor-sdk/looks';
|
|
49
|
+
import { BLENDER_REGIONS } from '../src/regions';
|
|
49
50
|
|
|
50
51
|
export const point = 'workspace.layout';
|
|
51
52
|
export const layout: WorkspaceLayoutContribution = {
|
|
@@ -57,7 +58,9 @@ export const layout: WorkspaceLayoutContribution = {
|
|
|
57
58
|
// layer wins over the style bundle, so restating the host default would
|
|
58
59
|
// silently shadow `blender.style.ts`'s `tabs: 'hidden'` and paint a tab row
|
|
59
60
|
// Blender does not have.
|
|
61
|
+
// Blender's areas beneath this workspace's own (`../src/regions.ts`).
|
|
60
62
|
regions: {
|
|
63
|
+
...BLENDER_REGIONS,
|
|
61
64
|
header: 'shown',
|
|
62
65
|
shelf: 'shown',
|
|
63
66
|
inspector: 'properties',
|