Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7d68aa4
fix: correct global bind key
seankmartin Jun 8, 2026
9fa5c4a
fix: correct tool binding and correct pattern
seankmartin Jun 22, 2026
aae0de6
feat: bind to non-key tool
seankmartin Jun 22, 2026
a565247
fix: show user bind
seankmartin Jun 22, 2026
dcd85dc
feat: update hovered node update logic so node ID + seg ID is there
seankmartin Jun 25, 2026
d79b0bf
feat: thread highlighted node ID through FE
seankmartin Jun 25, 2026
fc83399
feat: add two palettes, one hovered, one selected
seankmartin Jun 25, 2026
8c0fb7b
Merge pull request #197 from MetaCell/feat/NA-874
seankmartin Jun 25, 2026
0198cfa
feat: Add optional layer-owned runtime cleanup
afonsobspinto Jun 26, 2026
9e9eb14
fix: add back unconditional node draw
seankmartin Jun 26, 2026
1e60c5b
feat: tweak radius for a bit of leeway to reduce gaps
seankmartin Jun 26, 2026
f470be8
feat: v1 of new tool system
seankmartin Jun 26, 2026
8f96954
Merge pull request #199 from MetaCell/feat/always-draw-nodes
seankmartin Jun 26, 2026
d84bd74
temp: force transparent rendering
seankmartin Jun 26, 2026
eb38ab3
Merge pull request #200 from MetaCell/temp/force-transparent-skeleton
seankmartin Jun 26, 2026
404c165
refactor: move dumped logic in activate into class methods and class …
seankmartin Jun 26, 2026
791922b
fix: block modes at the same time
seankmartin Jun 26, 2026
28b61a0
feat: update UI with less tools
seankmartin Jun 26, 2026
862d484
Merge pull request #201 from MetaCell/feat/merge-skeleton-tools
seankmartin Jun 26, 2026
1d573ad
feat: add dual mode for split and merge
seankmartin Jun 26, 2026
8c02cf2
Merge pull request #202 from MetaCell/feat/dual-mode-merge-skeleton-t…
seankmartin Jun 26, 2026
48733fc
feat: bump radius a little
seankmartin Jun 26, 2026
7cd39be
refactor: update command naming
seankmartin Jun 26, 2026
60e59a0
Merge branch 'feat/skeleton-ux-improvement' into feat/skeleton-new-ac…
seankmartin Jun 26, 2026
bc84758
chore: update func to async
seankmartin Jun 26, 2026
71332b6
feat: update edit tool behaviour
seankmartin Jun 28, 2026
3a52889
feat: v1 of picking indicator
seankmartin Jun 28, 2026
c1ac150
Merge pull request #203 from MetaCell/feat/skeleton-new-actions
seankmartin Jun 29, 2026
7d0df5b
refactor: use correct actions pattern following recolor
seankmartin Jun 29, 2026
2be3ff6
Merge pull request #205 from MetaCell/feat/skeleton-action-updates
seankmartin Jun 29, 2026
197252e
Merge branch 'feat/skeleton-ux-improvement' into feat/picking-indicator
seankmartin Jun 29, 2026
cd01bdf
Merge pull request #204 from MetaCell/feature/NA-881
afonsobspinto Jun 29, 2026
9f593ba
fix: block undo/redo having many at the same time
seankmartin Jun 29, 2026
44ade78
Merge pull request #207 from MetaCell/fix/block-undo-redo
seankmartin Jun 29, 2026
1d0ecca
Merge branch 'feat/command-palette' into feat/skeleton-ux-improvement
seankmartin Jun 29, 2026
d26170d
Merge branch 'feat/skeleton-ux-improvement' of https://github.com/Met…
seankmartin Jun 29, 2026
8a02a19
fix: set skeleton state watchable
seankmartin Jun 29, 2026
184ead3
Merge pull request #208 from MetaCell/fix/watchables-actions-skeleton
seankmartin Jun 29, 2026
7f9c77e
feat: add second outline to node border
seankmartin Jun 29, 2026
7af0d27
feat: link outline to skeleton fe
seankmartin Jun 29, 2026
656a784
Merge pull request #209 from MetaCell/feat/skeleton-node-border
seankmartin Jun 29, 2026
400783b
feat: hide skeletons action
seankmartin Jun 29, 2026
0507df5
Merge branch 'feature/edit-mode' into feat/skeleton-ux-improvement
seankmartin Jun 30, 2026
3bec268
Merge branch 'feat/skeleton-ux-improvement' of https://github.com/Met…
seankmartin Jun 30, 2026
c3ec658
feat: remove radius factor experiment
seankmartin Jun 30, 2026
89cc916
Merge pull request #210 from MetaCell/feat/new-action-hide-skel
seankmartin Jun 30, 2026
adf5d98
Merge pull request #206 from MetaCell/feat/picking-indicator
seankmartin Jun 30, 2026
667a871
refactor: update color handling
seankmartin Jun 30, 2026
6f4b2a8
feat: prepend new status messages
seankmartin Jun 30, 2026
f841fa3
feat: pick color based on current color for highlight
seankmartin Jun 30, 2026
9f797ef
feat: message in skeleton tab if node from non vis
seankmartin Jul 1, 2026
1584eca
Merge pull request #212 from MetaCell/feat/skeleton-non-visible-tab
seankmartin Jul 1, 2026
872e94c
feat: allow desaturate on highly saturated
seankmartin Jul 1, 2026
d96fa6a
fix: more flexible platform detection mac
seankmartin Jul 3, 2026
0305e21
fix: correct more mac bind labels
seankmartin Jul 3, 2026
28de1be
Merge branch 'feature/edit-mode' into feat/skeleton-ux-improvement
seankmartin Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/chunk_manager/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,11 @@ export class ChunkQueueManager extends SharedObject {
}

function updateChunk(rpc: RPC, x: any) {
const source: ChunkSource = rpc.get(x.source);
const source = rpc.get(x.source) as ChunkSource | undefined;
if (source === undefined) {
// Source was removed while chunk update was in flight.
return;
}
if (DEBUG_CHUNK_UPDATES) {
console.log(
`${Date.now()} Chunk.update received: ` +
Expand Down
2 changes: 2 additions & 0 deletions src/data_panel_layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export interface ViewerUIState
crossSectionBackgroundColor: TrackableRGB;
perspectiveViewBackgroundColor: TrackableRGB;
hideCrossSectionBackground3D: TrackableBoolean;
showPickingIndicator: TrackableBoolean;
pickRadius: TrackableValue<number>;
}

Expand Down Expand Up @@ -184,6 +185,7 @@ export function getCommonViewerState(viewer: ViewerUIState) {
visibility: viewer.visibility,
scaleBarOptions: viewer.scaleBarOptions,
hideCrossSectionBackground3D: viewer.hideCrossSectionBackground3D,
showPickingIndicator: viewer.showPickingIndicator,
pickRadius: viewer.pickRadius,
};
}
Expand Down
3 changes: 3 additions & 0 deletions src/datasource/catmaid/frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ export class CatmaidDataSourceProvider implements DataSourceProvider {
id: "skeletons-chunked",
default: true,
subsource: { mesh: multiscaleSource },
layerRuntimeStateDisposal: {
kind: "spatiallyIndexedSkeleton",
},
},
{
id: "skeletons",
Expand Down
14 changes: 6 additions & 8 deletions src/datasource/catmaid/spatial_skeleton_commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,18 @@ import {
addSegmentToVisibleSets,
removeSegmentFromVisibleSets,
} from "#src/segmentation_display_state/base.js";
import {
SpatialSkeletonActions,
type SpatialSkeletonAction,
} from "#src/skeleton/actions.js";
import type {
SpatiallyIndexedSkeletonNode,
SpatialSkeletonSourceState,
SpatialSkeletonVector,
} from "#src/skeleton/api.js";
import type { SpatialSkeletonEditCommandFactory } from "#src/skeleton/command_factories.js";
import type {
SpatialSkeletonCommand,
SpatialSkeletonCommandContext,
} from "#src/skeleton/command_history.js";
import {
SpatialSkeletonActions,
type SpatialSkeletonAction,
type SpatialSkeletonCommand,
type SpatialSkeletonCommandContext,
} from "#src/skeleton/command_protocol.js";
import type { SpatiallyIndexedSkeletonLayer } from "#src/skeleton/frontend.js";
import {
findSpatiallyIndexedSkeletonNode,
Expand Down
10 changes: 10 additions & 0 deletions src/datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ export interface CompleteUrlOptions extends CompleteUrlOptionsBase {
signal: AbortSignal;
}

export interface LayerRuntimeStateDisposalRequest {
kind: string;
}

export interface DataSubsourceEntry {
/**
* Unique identifier (within the group) for this subsource. Stored in the JSON state
Expand Down Expand Up @@ -182,6 +186,12 @@ export interface DataSubsourceEntry {
* Specifies whether this associated data source is enabled by default.
*/
default: boolean;

/**
* Optional layer-owned runtime cleanup requested when this active subsource's
* datasource is replaced or cleared.
*/
layerRuntimeStateDisposal?: LayerRuntimeStateDisposalRequest;
}

export interface ChannelMetadata {
Expand Down
13 changes: 11 additions & 2 deletions src/help/input_event_bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
type EventActionMap,
} from "#src/util/event_action_map.js";
import { emptyToUndefined } from "#src/util/json.js";
import { isMacPlatform } from "#src/util/platform.js";

declare let NEUROGLANCER_BUILD_INFO:
| { tag: string; url?: string; timestamp?: string }
Expand All @@ -51,8 +52,16 @@ export function formatKeyName(name: string) {
}

export function formatKeyStroke(stroke: string) {
const parts = stroke.split("+");
return parts.map(formatKeyName).join("+");
const mac = isMacPlatform();
return stroke
.split("+")
.map((part) => {
if (mac && part === "control") return "⌘";
if (mac && part === "alt") return "⌥";
if (mac && part === "shift") return "⇧";
return formatKeyName(part);
})
.join("+");
}

const DEFAULT_HELP_PANEL_LOCATION: SidePanelLocation = {
Expand Down
13 changes: 12 additions & 1 deletion src/layer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ import type {
} from "#src/datasource/index.js";
import { makeEmptyDataSourceSpecification } from "#src/datasource/index.js";
import type { DisplayContext, RenderedPanel } from "#src/display_context.js";
import type { LoadedDataSubsource } from "#src/layer/layer_data_source.js";
import type {
LayerDataSourceChangeRuntimeDisposalContext,
LoadedDataSubsource,
} from "#src/layer/layer_data_source.js";
import {
LayerDataSource,
layerDataSourceSpecificationFromJson,
Expand Down Expand Up @@ -429,6 +432,14 @@ export class UserLayer extends RefCounted {
subsources;
}

// Derived classes may override to clear layer-owned runtime state for active
// datasources that explicitly request cleanup on source change.
disposeLayerRuntimeStateForDataSourceChange(
_context: LayerDataSourceChangeRuntimeDisposalContext,
) {
return false;
}

updateDataSubsourceActivations() {
function* getDataSubsources(
this: UserLayer,
Expand Down
49 changes: 46 additions & 3 deletions src/layer/layer_data_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type {
DataSourceWithRedirectInfo,
DataSubsourceEntry,
DataSubsourceSpecification,
LayerRuntimeStateDisposalRequest,
} from "#src/datasource/index.js";
import { makeEmptyDataSourceSpecification } from "#src/datasource/index.js";
import type { UserLayer } from "#src/layer/index.js";
Expand Down Expand Up @@ -148,6 +149,7 @@ export class LoadedDataSubsource {
enabled: boolean;
activated: RefCounted | undefined = undefined;
guardValues: any[] = [];
renderLayers = new Set<RenderLayer>();
messages = new MessageList();
isActiveChanged = new NullarySignal();
constructor(
Expand Down Expand Up @@ -212,9 +214,13 @@ export class LoadedDataSubsource {

addRenderLayer(renderLayer: Owned<RenderLayer>) {
const activated = this.activated!;
activated.registerDisposer(
this.loadedDataSource.layer.addRenderLayer(renderLayer),
);
const removeRenderLayer =
this.loadedDataSource.layer.addRenderLayer(renderLayer);
this.renderLayers.add(renderLayer);
activated.registerDisposer(() => {
this.renderLayers.delete(renderLayer);
removeRenderLayer();
});
activated.registerDisposer(this.messages.addChild(renderLayer.messages));
}

Expand Down Expand Up @@ -301,6 +307,16 @@ export class LoadedLayerDataSource extends RefCounted {
}
}

export type LayerDataSourceChangeReason = "replace" | "clear";

export interface LayerDataSourceChangeRuntimeDisposalContext {
request: LayerRuntimeStateDisposalRequest;
reason: LayerDataSourceChangeReason;
layerDataSource: LayerDataSource;
loadedDataSource: LoadedLayerDataSource;
loadedSubsource: LoadedDataSubsource;
}

export type LayerDataSourceLoadState =
| {
error: Error;
Expand Down Expand Up @@ -368,10 +384,36 @@ export class LayerDataSource extends RefCounted {
return this.loadState_;
}

private disposeRuntimeStateForDataSourceChange(
reason: LayerDataSourceChangeReason,
) {
const { loadState } = this;
if (loadState === undefined || loadState.error !== undefined) return false;
const handledRequestKinds = new Set<string>();
let changed = false;
for (const loadedSubsource of loadState.subsources) {
if (loadedSubsource.activated === undefined) continue;
const request = loadedSubsource.subsourceEntry.layerRuntimeStateDisposal;
if (request === undefined) continue;
if (handledRequestKinds.has(request.kind)) continue;
handledRequestKinds.add(request.kind);
changed =
this.layer.disposeLayerRuntimeStateForDataSourceChange({
request,
reason,
layerDataSource: this,
loadedDataSource: loadState,
loadedSubsource,
}) || changed;
}
return changed;
}

set spec(spec: DataSourceSpecification) {
const { layer } = this;
this.messages.clearMessages();
if (spec.url.length === 0) {
this.disposeRuntimeStateForDataSourceChange("clear");
if (layer.dataSources.length !== 1) {
const index = layer.dataSources.indexOf(this);
if (index !== -1) {
Expand All @@ -395,6 +437,7 @@ export class LayerDataSource extends RefCounted {
disposableOnce(layer.markLoading()),
);
if (this.refCounted_ !== undefined) {
this.disposeRuntimeStateForDataSourceChange("replace");
this.refCounted_.dispose();
this.loadState_ = undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion src/layer/segmentation/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { describe, expect, it, vi } from "vitest";

import type { RenderLayerTransform } from "#src/render_coordinate_transform.js";
import { SpatialSkeletonActions } from "#src/skeleton/actions.js";
import { SpatialSkeletonActions } from "#src/skeleton/command_protocol.js";
import { WatchableValue } from "#src/trackable_value.js";

if (!("WebGL2RenderingContext" in globalThis)) {
Expand Down
Loading