Skip to content

Commit

Permalink
aggressively clean up objects
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonDanisch committed Dec 12, 2024
1 parent d8c4dbd commit 98e6c10
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 72 deletions.
63 changes: 35 additions & 28 deletions WGLMakie/src/Serialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class Plot {
plot_data = {};

constructor(scene, data) {

this.plot_data = data;

connect_plot(scene, this);
Expand All @@ -51,7 +50,7 @@ class Plot {
} else if (data.plot_type === "linesegments") {
this.mesh = create_linesegments(scene, this.plot_data);
} else if ("instance_attributes" in data) {
this.is_instanced = true
this.is_instanced = true;
this.mesh = create_instanced_mesh(scene, this.plot_data);
} else {
this.mesh = create_mesh(scene, this.plot_data);
Expand All @@ -65,7 +64,6 @@ class Plot {
this.mesh.matrixAutoUpdate = false;
this.mesh.renderOrder = data.zvalue;


data.uniform_updater.on(([name, data]) => {
this.update_uniform(name, data);
});
Expand All @@ -79,52 +77,67 @@ class Plot {
// Give mesh a reference to the plot object.
this.mesh.plot_object = this;
this.mesh.visible = data.visible.value;
data.visible.on(v=> {
data.visible.on((v) => {
this.mesh.visible = v;
});

}

dispose() {
delete plot_cache[this.uuid];
this.parent.remove(this.mesh);
this.mesh.geometry.dispose();
this.mesh.material.dispose();
this.mesh = undefined;
this.parent = undefined;
this.uuid = "";
this.name = "";
this.is_instanced = false;
this.geometry_needs_recreation = false;
this.plot_data = {};
}
move_to(scene) {
if (scene === this.parent) {
return
return;
}
this.parent.remove(this.mesh)
connect_plot(scene, this)
scene.add(this.mesh)
this.parent = scene
return
this.parent.remove(this.mesh);
connect_plot(scene, this);
scene.add(this.mesh);
this.parent = scene;
return;
}

update(attributes) {
attributes.keys().forEach(key=> {
const value = attributes[key]
attributes.keys().forEach((key) => {
const value = attributes[key];
if (value.type == "uniform") {
this.update_uniform(key, value.data);
} else if (value.type === "geometry") {
this.update_geometries(value.data)
this.update_geometries(value.data);
} else if (value.type === "faces") {
this.update_faces(value.data)
this.update_faces(value.data);
}
})
});
// For e.g. when we need to re-create the geometry
this.apply_updates()
this.apply_updates();
}

update_uniform(name, new_data) {
const uniform = this.mesh.material.uniforms[name];
if (!uniform) {
throw new Error(`Uniform ${name} doesn't exist in Plot: ${this.name}`)
throw new Error(
`Uniform ${name} doesn't exist in Plot: ${this.name}`
);
}
update_uniform(uniform, new_data);
}

update_geometry(name, new_data) {
buffer = this.mesh.geometry.attributes[name];
if (!buffer) {
throw new Error(`Buffer ${name} doesn't exist in Plot: ${this.name}`)
throw new Error(
`Buffer ${name} doesn't exist in Plot: ${this.name}`
);
}
const old_length = buffer.count
const old_length = buffer.count;
if (new_data.length <= old_length) {
buffer.set(new_data.data);
buffer.needsUpdate = true;
Expand Down Expand Up @@ -716,13 +729,7 @@ export function deserialize_scene(data, screen) {
}

export function delete_plot(plot) {
delete plot_cache[plot.plot_uuid];
const { parent } = plot;
if (parent) {
parent.remove(plot);
}
plot.geometry.dispose();
plot.material.dispose();
plot.plot_object.dispose()
}

export function delete_three_scene(scene) {
Expand Down
109 changes: 86 additions & 23 deletions WGLMakie/src/wglmakie.bundled.js
Original file line number Diff line number Diff line change
Expand Up @@ -22341,6 +22341,19 @@ class Plot {
this.mesh.visible = v;
});
}
dispose() {
delete plot_cache[this.uuid];
this.parent.remove(this.mesh);
this.mesh.geometry.dispose();
this.mesh.material.dispose();
this.mesh = undefined;
this.parent = undefined;
this.uuid = "";
this.name = "";
this.is_instanced = false;
this.geometry_needs_recreation = false;
this.plot_data = {};
}
move_to(scene) {
if (scene === this.parent) {
return;
Expand Down Expand Up @@ -22862,13 +22875,7 @@ function deserialize_scene(data, screen) {
return scene;
}
function delete_plot(plot) {
delete plot_cache[plot.plot_uuid];
const { parent } = plot;
if (parent) {
parent.remove(plot);
}
plot.geometry.dispose();
plot.material.dispose();
plot.plot_object.dispose();
}
function delete_three_scene(scene) {
delete scene_cache[scene.scene_uuid];
Expand All @@ -22878,20 +22885,45 @@ function delete_three_scene(scene) {
}
}
window.THREE = mod;
function dispose_screen(screen) {
const { renderer , picking_target , root_scene } = screen;
if (renderer) {
const canvas = renderer.domElement;
if (canvas.parentNode) {
canvas.parentNode.removeChild(canvas);
}
renderer.state.reset();
renderer.forceContextLoss();
renderer.dispose();
}
if (screen.texture_atlas) {
const data = TEXTURE_ATLAS[0].value;
TEXTURE_ATLAS[0].notify(screen.texture_atlas, true);
TEXTURE_ATLAS[0].value = data;
screen.texture_atlas = undefined;
}
if (root_scene) {
delete_three_scene(root_scene);
}
if (picking_target) {
picking_target.dispose();
}
Object.keys(screen).forEach((key)=>delete screen[key]);
return;
}
function render_scene(scene, picking = false) {
if (scene.screen == {}) {
return false;
}
const { camera , renderer , px_per_unit } = scene.screen;
if (!renderer) {
dispose_screen(scene.screen);
return false;
}
const canvas = renderer.domElement;
if (!document.body.contains(canvas)) {
console.log("removing WGL context, canvas is not in the DOM anymore!");
if (scene.screen.texture_atlas) {
const data = TEXTURE_ATLAS[0].value;
TEXTURE_ATLAS[0].notify(scene.screen.texture_atlas, true);
TEXTURE_ATLAS[0].value = data;
scene.screen.texture_atlas = undefined;
}
delete_three_scene(scene);
renderer.state.reset();
renderer.dispose();
dispose_screen(scene.screen);
return false;
}
if (!scene.visible.value) {
Expand Down Expand Up @@ -23002,6 +23034,9 @@ function on_shader_error(gl, program, glVertexShader, glFragmentShader) {
}
function add_canvas_events(screen, comm, resize_to) {
const { canvas , winscale } = screen;
canvas.addEventListener("webglcontextlost", (event)=>{
dispose_screen(screen);
});
function mouse_callback(event) {
const [x1, y1] = events2unitless(screen, event);
comm.notify({
Expand Down Expand Up @@ -23199,6 +23234,7 @@ function create_scene(wrapper, canvas, canvas_width, scenes, comm, width, height
add_canvas_events(screen, comm, resize_to);
set_render_size(screen, width, height);
const three_scene = deserialize_scene(scenes, screen);
screen.root_scene = three_scene;
start_renderloop(three_scene);
canvas_width.on((w_h)=>{
set_render_size(screen, ...w_h);
Expand Down Expand Up @@ -23276,7 +23312,10 @@ function pick_native(scene, _x, _y, _w, _h, apply_ppu = true) {
];
renderer.setRenderTarget(picking_target);
set_picking_uniforms(scene, 1, true);
render_scene(scene, true);
const rendered = render_scene(scene, true);
if (!rendered) {
return;
}
renderer.setRenderTarget(null);
const picked_plots_array = read_pixels(renderer, picking_target, x1, y1, w, h);
const picked_plots = {};
Expand Down Expand Up @@ -23318,7 +23357,10 @@ function get_picking_buffer(scene) {
];
renderer.setRenderTarget(picking_target);
set_picking_uniforms(scene, 1, true);
render_scene(scene, true);
const rendered = render_scene(scene, true);
if (!rendered) {
return;
}
renderer.setRenderTarget(null);
const picked_plots_array = read_pixels(renderer, picking_target, x, y, w, h);
return {
Expand Down Expand Up @@ -23386,7 +23428,11 @@ function pick_sorted(scene, xy, range) {
const y1 = Math.min(canvas.height, Math.ceil(px_per_unit * (xy[1] + range)));
const dx = x1 - x0;
const dy = y1 - y0;
const [plot_data1, selected] = pick_native(scene, x0, y0, dx, dy, false);
const picked = pick_native(scene, x0, y0, dx, dy, false);
if (!picked) {
return null;
}
const [plot_data1, selected] = picked;
if (selected.length == 0) {
return null;
}
Expand Down Expand Up @@ -23416,15 +23462,28 @@ function pick_sorted(scene, xy, range) {
});
}
function pick_native_uuid(scene, x1, y1, w, h) {
const [_, picked_plots] = pick_native(scene, x1, y1, w, h);
const picked = pick_native(scene, x1, y1, w, h);
if (!picked) {
return [];
}
const [_, picked_plots] = picked;
return picked_plots.map(([p, index])=>[
p.plot_uuid,
index
]);
}
function pick_native_matrix(scene, x1, y1, w, h) {
const [matrix, _] = pick_native(scene, x1, y1, w, h);
return matrix;
const picked = pick_native(scene, x1, y1, w, h);
if (!picked) {
return {
data: [],
size: [
0,
0
]
};
}
return picked[0];
}
function register_popup(popup, scene, plots_to_pick, callback) {
if (!scene || !scene.screen) {
Expand All @@ -23433,7 +23492,11 @@ function register_popup(popup, scene, plots_to_pick, callback) {
const { canvas } = scene.screen;
canvas.addEventListener("mousedown", (event)=>{
const [x1, y1] = events2unitless(scene.screen, event);
const [_, picks] = pick_native(scene, x1, y1, 1, 1);
const picked = pick_native(scene, x1, y1, 1, 1);
if (!picked) {
return;
}
const [_, picks] = picked;
if (picks.length == 1) {
const [plot, index] = picks[0];
if (plots_to_pick.has(plot.plot_uuid)) {
Expand Down
Loading

0 comments on commit 98e6c10

Please sign in to comment.