@volter/blender-engine 0.1.19 → 0.1.20
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.
|
@@ -744,6 +744,8 @@ export class BlenderRuntimeView {
|
|
|
744
744
|
* showing". Fired after the frame is applied, so a listener that reads
|
|
745
745
|
* the graph sees the new one. */
|
|
746
746
|
private readonly frameListeners = new Set<() => void>();
|
|
747
|
+
/** The views drawing this one's frames in a second area ({@link follow}). */
|
|
748
|
+
private readonly followers = new Set<BlenderRuntimeView>();
|
|
747
749
|
|
|
748
750
|
/** Subscribe to frames. Returns the unsubscribe. */
|
|
749
751
|
subscribeFrames(listener: () => void): () => void {
|
|
@@ -1867,6 +1869,15 @@ export class BlenderRuntimeView {
|
|
|
1867
1869
|
// The model moved: whoever is READING the engine (the Properties sections
|
|
1868
1870
|
// through the RNA door) re-reads now, with the new graph already standing.
|
|
1869
1871
|
for (const listener of [...this.frameListeners]) listener();
|
|
1872
|
+
// EVERY FOLLOWER TAKES THE SAME FRAME, and one that cannot (it lacks geometry the frame only
|
|
1873
|
+
// references) is rebuilt from everything this view now holds.
|
|
1874
|
+
for (const follower of this.followers) {
|
|
1875
|
+
try {
|
|
1876
|
+
follower.applyFrame(input);
|
|
1877
|
+
} catch {
|
|
1878
|
+
follower.applyFrame(this.fullFrame());
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1870
1881
|
return { ...this.inspect(), held };
|
|
1871
1882
|
}
|
|
1872
1883
|
|
|
@@ -1898,7 +1909,10 @@ export class BlenderRuntimeView {
|
|
|
1898
1909
|
* disposable geometry cross this boundary; delta-only frames are sufficient.
|
|
1899
1910
|
* The caller owns this snapshot and must dispose it on every outcome.
|
|
1900
1911
|
*/
|
|
1901
|
-
|
|
1912
|
+
/** Everything this view holds, as ONE self-contained frame another view can be built from:
|
|
1913
|
+
* every mesh's resident geometry and every resident image, with no reference to what a
|
|
1914
|
+
* receiver already holds. */
|
|
1915
|
+
private fullFrame(): Frame {
|
|
1902
1916
|
const source = this.frame;
|
|
1903
1917
|
if (!source) throw new Error('Blender capture requires a presented frame');
|
|
1904
1918
|
// Inspection overlays are not render content. In particular weight-paint
|
|
@@ -1976,6 +1990,37 @@ export class BlenderRuntimeView {
|
|
|
1976
1990
|
};
|
|
1977
1991
|
}
|
|
1978
1992
|
}
|
|
1993
|
+
return frame;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
/**
|
|
1997
|
+
* A SECOND VIEW OF THE SAME MODEL, for a second area drawing it (Blender's split 3D viewport):
|
|
1998
|
+
* its own graph, because a three.js object has one parent and each area's stage holds its own
|
|
1999
|
+
* root, built from everything this view holds and then handed every frame this one applies, so
|
|
2000
|
+
* the two show one revision. Each view keeps its own shading (Solid in one, Rendered in the
|
|
2001
|
+
* other), its own camera view and its own overlays. Inspection overlays (bones, weights) and a
|
|
2002
|
+
* Timeline pose stay this view's: they are not in a frame another view can be built from.
|
|
2003
|
+
*/
|
|
2004
|
+
follow(): { readonly view: BlenderRuntimeView; dispose(): void } {
|
|
2005
|
+
const follower = new BlenderRuntimeView();
|
|
2006
|
+
if (this.frame) follower.applyFrame(this.fullFrame());
|
|
2007
|
+
this.followers.add(follower);
|
|
2008
|
+
let disposed = false;
|
|
2009
|
+
return {
|
|
2010
|
+
view: follower,
|
|
2011
|
+
dispose: () => {
|
|
2012
|
+
if (disposed) return;
|
|
2013
|
+
disposed = true;
|
|
2014
|
+
this.followers.delete(follower);
|
|
2015
|
+
follower.dispose();
|
|
2016
|
+
follower.root.removeFromParent();
|
|
2017
|
+
},
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
captureSnapshot() {
|
|
2022
|
+
const frame = this.fullFrame();
|
|
2023
|
+
const source = this.frame!;
|
|
1979
2024
|
const effect = this.createWorldVolumePass();
|
|
1980
2025
|
const detached = new BlenderRuntimeView();
|
|
1981
2026
|
detached.photograph = true;
|