@volter/blender-engine 0.1.35 → 0.1.37

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.
@@ -76,6 +76,9 @@ export type WorkerRequest =
76
76
  /** ONE RESTRICTION COLUMN, written (`session.py`'s `outliner_set`). A column
77
77
  * Blender draws on no row of that type is refused by name. */
78
78
  | { id: number; op: 'outliner-set'; path: string; column: string; value: boolean }
79
+ /** A person's shading pick, kept in the file's own 3D View (`session.py`'s `_view_shading`);
80
+ * UI state, so it marks nothing changed and rides the next save. */
81
+ | { id: number; op: 'view-shading'; shading: 'WIREFRAME' | 'SOLID' | 'MATERIAL' | 'RENDERED' }
79
82
  | { id: number; op: 'read-file'; path: string }
80
83
  | { id: number; op: 'write-file'; path: string; bytes: Uint8Array }
81
84
  | { id: number; op: 'list-files'; path: string }
@@ -318,6 +318,12 @@ export class BlenderRuntime {
318
318
  })) as BlenderRnaWrite;
319
319
  }
320
320
 
321
+ /** Keep a person's shading pick in the file's own 3D View, as UI state (no save of its own). */
322
+ async viewShading(shading: 'WIREFRAME' | 'SOLID' | 'MATERIAL' | 'RENDERED'): Promise<void> {
323
+ await this.#ready();
324
+ await this.#request({ op: 'view-shading', shading });
325
+ }
326
+
321
327
  /** BLENDER'S VIEW LAYER TREE for the scene — what its Outliner shows, as
322
328
  * rows (`./rna.ts`, `BlenderOutlinerTree`). `selected` is our viewport's
323
329
  * selection by object name; reading it never writes the engine's. */
@@ -760,13 +760,17 @@ def _empty_display(obj):
760
760
 
761
761
 
762
762
  def _saved_view():
763
- """The 3D View the file saved, which is where Blender opens it: the `Modeling` workspace's
764
- (this editor's Model workspace is Blender's Modeling), else the first 3D View any screen
765
- holds. `RegionView3D`'s pivot, rotation (view to world, `(w, x, y, z)`), distance and
766
- projection (`PERSP`, `ORTHO`, or `CAMERA` for a view through the scene camera), and the
767
- `View3D`'s lens."""
763
+ """The 3D View the file saved, which is where Blender opens it: the one on the screen the
764
+ file's window was showing when it was saved (Blender reopens that workspace; a stock file's is
765
+ `Layout`), else the `Modeling` workspace's (this editor's Model workspace is Blender's
766
+ Modeling), else the first 3D View any screen holds. `RegionView3D`'s pivot, rotation (view to
767
+ world, `(w, x, y, z)`), distance and projection (`PERSP`, `ORTHO`, or `CAMERA` for a view
768
+ through the scene camera), the `View3D`'s lens, and its SHADING TYPE, which Blender reopens
769
+ with the view: a file saved in Material Preview opens in Material Preview."""
770
+ screens = [window.screen for wm in bpy.data.window_managers for window in wm.windows
771
+ if window.screen is not None]
768
772
  workspace = bpy.data.workspaces.get("Modeling")
769
- screens = list(workspace.screens) if workspace is not None else []
773
+ screens.extend(workspace.screens if workspace is not None else [])
770
774
  screens.extend(bpy.data.screens)
771
775
  for screen in screens:
772
776
  for area in screen.areas:
@@ -780,10 +784,28 @@ def _saved_view():
780
784
  "rotation": [float(v) for v in region.view_rotation],
781
785
  "distance": float(region.view_distance),
782
786
  "perspective": region.view_perspective,
787
+ "shading": space.shading.type,
783
788
  }
784
789
  return None
785
790
 
786
791
 
792
+ def _view_shading(shading):
793
+ """A person's shading pick, written where Blender keeps it: the `View3DShading.type` of the 3D
794
+ View `_saved_view` reads. UI STATE, NOT THE MODEL: nothing is marked changed, so it rides the
795
+ next save the model's own edits make, as a shading change in Blender is kept only by a save."""
796
+ screens = [window.screen for wm in bpy.data.window_managers for window in wm.windows
797
+ if window.screen is not None]
798
+ workspace = bpy.data.workspaces.get("Modeling")
799
+ screens.extend(workspace.screens if workspace is not None else [])
800
+ screens.extend(bpy.data.screens)
801
+ for screen in screens:
802
+ for area in screen.areas:
803
+ if area.type == "VIEW_3D":
804
+ area.spaces[0].shading.type = shading
805
+ return {"shading": area.spaces[0].shading.type}
806
+ return {"shading": None}
807
+
808
+
787
809
  def _subject_line(scene, view_layer):
788
810
  """The 3D Viewport's second overlay line, as `draw_selected_name` (`view3d_draw.cc`) writes it,
789
811
  less the two parts that follow the playhead: the tab draws `(frame)` and the marker on it
@@ -4997,6 +5019,8 @@ def _dispatch(request):
4997
5019
  _say("@@VOLTER-ERROR the present after this call failed, so the Model document is "
4998
5020
  "showing the state before it: " + repr(thrown))
4999
5021
  return answer
5022
+ if op == "view-shading":
5023
+ return _view_shading(request["shading"])
5000
5024
  if op == "rna-set":
5001
5025
  SESSION.mark_changed()
5002
5026
  answer = rna_set(request["path"], request["property"], request["value"],
@@ -43,6 +43,13 @@ import {
43
43
  } from './blender-runtime-camera-view';
44
44
  import { DEFAULT_VIEWPORT_DISPLAY, workbenchMaterial } from './blender-workbench-material';
45
45
 
46
+ /** A saved `View3DShading.type` as the stage's draw mode: Material Preview is `preview`. */
47
+ const SAVED_SHADING = {
48
+ WIREFRAME: 'wireframe',
49
+ SOLID: 'solid',
50
+ MATERIAL: 'preview',
51
+ RENDERED: 'rendered',
52
+ } as const;
46
53
  const scalar = z.number().finite();
47
54
  const point = z.tuple([scalar, scalar, scalar]);
48
55
  const edge = z.tuple([z.number().int().nonnegative(), z.number().int().nonnegative()]);
@@ -547,6 +554,7 @@ export const frameSchema = z
547
554
  distance: z.number().finite(),
548
555
  perspective: z.enum(['PERSP', 'ORTHO', 'CAMERA']),
549
556
  lens: z.number().finite().positive().default(50),
557
+ shading: z.enum(['WIREFRAME', 'SOLID', 'MATERIAL', 'RENDERED']).optional(),
550
558
  })
551
559
  .nullable()
552
560
  .optional(),
@@ -831,9 +839,14 @@ export class BlenderRuntimeView {
831
839
  * direction from the pivot to the eye (the view's +Z, `view_rotation` turning view space into
832
840
  * the world: RNA's inverse of `viewquat`), the screen's up (the view's +Y), the distance and
833
841
  * the projection. A view saved through the scene camera opens in perspective along the same
834
- * axis: looking through a camera is not a view this stage has. Null before a frame or when
835
- * the file saved no 3D View.
842
+ * axis: looking through a camera is not a view this stage has. With it the view's SHADING, the
843
+ * draw mode Blender reopens it in (null from a file whose view carried none). Null before a
844
+ * frame or when the file saved no 3D View.
836
845
  */
846
+ noteSavedShading(shading: keyof typeof SAVED_SHADING): void {
847
+ if (this.frame?.view) this.frame.view.shading = shading;
848
+ }
849
+
837
850
  savedView(): {
838
851
  readonly target: readonly [number, number, number];
839
852
  readonly direction: readonly [number, number, number];
@@ -841,6 +854,7 @@ export class BlenderRuntimeView {
841
854
  readonly distance: number;
842
855
  readonly projection: 'perspective' | 'orthographic';
843
856
  readonly lens: number;
857
+ readonly drawMode: 'wireframe' | 'solid' | 'preview' | 'rendered' | null;
844
858
  } | null {
845
859
  const saved = this.frame?.view;
846
860
  if (!saved) return null;
@@ -855,6 +869,7 @@ export class BlenderRuntimeView {
855
869
  distance: saved.distance,
856
870
  projection: saved.perspective === 'ORTHO' ? 'orthographic' : 'perspective',
857
871
  lens: saved.lens,
872
+ drawMode: saved.shading ? SAVED_SHADING[saved.shading] : null,
858
873
  };
859
874
  }
860
875
 
package/browser/worker.ts CHANGED
@@ -508,6 +508,8 @@ async function handle(request: WorkerRequest): Promise<unknown> {
508
508
  ...(request.object === undefined ? {} : { object: request.object }),
509
509
  ...(request.collection === undefined ? {} : { collection: request.collection }),
510
510
  });
511
+ case 'view-shading':
512
+ return ask({ op: 'view-shading', shading: request.shading });
511
513
  case 'rna-set':
512
514
  return ask({
513
515
  op: 'rna-set',
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/blender-engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "GPL-3.0-or-later",
5
- "version": "0.1.35",
5
+ "version": "0.1.37",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },