Socket
Socket
Sign inDemoInstall

@itk-viewer/remote-viewport

Package Overview
Dependencies
Maintainers
2
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@itk-viewer/remote-viewport - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

7

CHANGELOG.md
# @itk-viewer/remote-viewport
## 0.1.3
### Patch Changes
- d1bbabd: Rename remote-machine renderer prop imageFile to image
- 5a6eb88: Add image attribute to itk-remote-viewport
## 0.1.2

@@ -4,0 +11,0 @@

3

dist/remote-machine.d.ts

@@ -7,2 +7,3 @@ /// <reference types="gl-matrix/index.js" />

cameraPose: ReadonlyMat4;
image: string | undefined;
};

@@ -13,3 +14,3 @@ type Entries<T> = {

export type RendererEntries = Entries<RendererProps>;
type Context = {
export type Context = {
address: string | undefined;

@@ -16,0 +17,0 @@ server: any | undefined;

@@ -7,3 +7,2 @@ import { mat4 } from 'gl-matrix';

id: 'remote',
initial: 'disconnected',
context: ({ input }) => ({

@@ -13,3 +12,7 @@ address: undefined,

frame: undefined,
rendererProps: { density: 30, cameraPose: mat4.create() },
rendererProps: {
density: 30,
cameraPose: mat4.create(),
image: 'data/aneurism.ome.tif',
},
queuedRendererEvents: [],

@@ -19,53 +22,7 @@ stagedRendererEvents: [],

}),
initial: 'root',
states: {
disconnected: {
entry: ({ context, self }) => {
// Update camera pose on viewport change
// FIXME: not capturing initial camera position because updateRender handler not registered before connection
context.viewport.subscribe(() => {
var _a;
const cameraPose = (_a = context.viewport
.getSnapshot()
.context.camera) === null || _a === void 0 ? void 0 : _a.getSnapshot().context.pose;
if (!cameraPose)
throw new Error('no camera pose');
self.send({
type: 'updateRenderer',
props: { cameraPose },
});
});
},
// root state captures initial rendererProps even when disconnected
root: {
on: {
setAddress: {
actions: [
assign({
address: ({ event: { address } }) => {
return address;
},
}),
],
target: 'connecting',
},
},
},
connecting: {
invoke: {
id: 'connect',
src: 'connect',
input: ({ context }) => ({
address: context.address,
}),
onDone: {
actions: assign({
server: ({ event }) => event.output,
// initially, send all props to renderer
// queuedRendererEvents: ({ context }) =>
// getEntries(context.rendererProps),
}),
target: 'online',
},
},
},
online: {
on: {
updateRenderer: {

@@ -94,36 +51,105 @@ actions: [

},
initial: 'render',
initial: 'disconnected',
states: {
render: {
disconnected: {
entry: ({ context, self }) => {
// Update camera pose on viewport change
context.viewport.subscribe(() => {
var _a;
const cameraPose = (_a = context.viewport
.getSnapshot()
.context.camera) === null || _a === void 0 ? void 0 : _a.getSnapshot().context.pose;
if (!cameraPose)
throw new Error('no camera pose');
self.send({
type: 'updateRenderer',
props: { cameraPose },
});
});
},
on: {
setAddress: {
actions: [
assign({
address: ({ event: { address }, }) => {
return address;
},
}),
],
target: 'connecting',
},
updateRenderer: {
actions: [
assign({
rendererProps: ({ event: { props }, context }) => {
return {
...context.rendererProps,
...props,
};
},
queuedRendererEvents: ({ event: { props }, context }) => [
...context.queuedRendererEvents,
...getEntries(props),
],
}),
],
},
},
},
connecting: {
invoke: {
id: 'render',
src: 'renderer',
id: 'connect',
src: 'connect',
input: ({ context }) => ({
server: context.server,
events: [...context.stagedRendererEvents],
context,
}),
onDone: {
actions: assign({
frame: ({ event }) => event.output,
server: ({ event }) => event.output,
// initially, send all props to renderer
queuedRendererEvents: ({ context }) => getEntries(context.rendererProps),
}),
target: 'idle',
target: 'online',
},
},
},
idle: {
always: {
// Renderer props changed while rendering? Then render.
guard: ({ context }) => context.queuedRendererEvents.length > 0,
target: 'render',
online: {
initial: 'render',
states: {
render: {
invoke: {
id: 'render',
src: 'renderer',
input: ({ context }) => ({
server: context.server,
events: [...context.stagedRendererEvents],
}),
onDone: {
actions: assign({
frame: ({ event }) => {
return event.output;
},
}),
target: 'idle',
},
},
},
idle: {
always: {
// Renderer props changed while rendering? Then render.
guard: ({ context }) => context.queuedRendererEvents.length > 0,
target: 'render',
},
on: {
render: { target: 'render' },
},
exit: assign({
// consumes queue in prep for renderer
stagedRendererEvents: ({ context }) => [
...context.queuedRendererEvents,
],
queuedRendererEvents: [],
}),
},
},
on: {
render: { target: 'render' },
},
exit: assign({
// consumes queue in prep for renderer
stagedRendererEvents: ({ context }) => [
...context.queuedRendererEvents,
],
queuedRendererEvents: [],
}),
},

@@ -130,0 +156,0 @@ },

@@ -6,3 +6,7 @@ import { fromPromise, interpret } from 'xstate';

import { mat4, vec3 } from 'gl-matrix';
const createHyphaRenderer = async (server_url) => {
const createHyphaRenderer = async (context) => {
const { address: server_url, rendererProps: { image }, } = context;
if (!server_url) {
throw new Error('No server url provided');
}
const config = {

@@ -13,6 +17,6 @@ client_id: 'remote-renderer-test-client',

};
const server = await hyphaWebsocketClient.connectToServer(config);
const renderer = await server.getService('test-agave-renderer');
const hypha = await hyphaWebsocketClient.connectToServer(config);
const renderer = await hypha.getService('test-agave-renderer');
await renderer.setup();
await renderer.setImage('data/aneurism.ome.tif');
await renderer.loadImage(image);
return renderer;

@@ -22,5 +26,6 @@ };

actors: {
connect: fromPromise(async ({ input }) => createHyphaRenderer(input.address)),
connect: fromPromise(async ({ input }) => createHyphaRenderer(input.context)),
renderer: fromPromise(async ({ input: { server, events }, }) => {
const translatedEvents = events.map(([key, value]) => {
const translatedEvents = events
.map(([key, value]) => {
if (key === 'cameraPose') {

@@ -34,5 +39,11 @@ const eye = vec3.create();

}
if (key === 'image') {
server.loadImage(value);
return;
}
return [key, value];
});
return server.updateRenderer(translatedEvents);
})
.filter(Boolean);
server.updateRenderer(translatedEvents);
return server.render();
}),

@@ -39,0 +50,0 @@ },

{
"name": "@itk-viewer/remote-viewport",
"version": "0.1.2",
"version": "0.1.3",
"description": "",

@@ -5,0 +5,0 @@ "type": "module",

@@ -9,2 +9,3 @@ import { ReadonlyMat4, mat4 } from 'gl-matrix';

cameraPose: ReadonlyMat4;
image: string | undefined;
};

@@ -23,3 +24,3 @@

type Context = {
export type Context = {
address: string | undefined;

@@ -54,3 +55,2 @@ server: any | undefined;

id: 'remote',
initial: 'disconnected',
context: ({ input }: { input: { viewport: Viewport } }) => ({

@@ -60,3 +60,7 @@ address: undefined,

frame: undefined,
rendererProps: { density: 30, cameraPose: mat4.create() },
rendererProps: {
density: 30,
cameraPose: mat4.create(),
image: 'data/aneurism.ome.tif',
},
queuedRendererEvents: [],

@@ -66,51 +70,8 @@ stagedRendererEvents: [],

}),
initial: 'root',
states: {
disconnected: {
entry: ({ context, self }) => {
// Update camera pose on viewport change
// FIXME: not capturing initial camera position because updateRender handler not registered before connection
context.viewport.subscribe(() => {
const cameraPose = context.viewport
.getSnapshot()
.context.camera?.getSnapshot().context.pose;
if (!cameraPose) throw new Error('no camera pose');
self.send({
type: 'updateRenderer',
props: { cameraPose },
});
});
},
// root state captures initial rendererProps even when disconnected
root: {
on: {
setAddress: {
actions: [
assign({
address: ({ event: { address } }: { event: SetAddressEvent }) => {
return address;
},
}),
],
target: 'connecting',
},
},
},
connecting: {
invoke: {
id: 'connect',
src: 'connect',
input: ({ context }: { context: Context }) => ({
address: context.address,
}),
onDone: {
actions: assign({
server: ({ event }) => event.output,
// initially, send all props to renderer
// queuedRendererEvents: ({ context }) =>
// getEntries(context.rendererProps),
}),
target: 'online',
},
},
},
online: {
on: {
updateRenderer: {

@@ -130,2 +91,3 @@ actions: [

}),
// Trigger a render (if in idle state)

@@ -140,36 +102,109 @@ ({ self }) => {

},
initial: 'render',
initial: 'disconnected',
states: {
render: {
disconnected: {
entry: ({ context, self }) => {
// Update camera pose on viewport change
context.viewport.subscribe(() => {
const cameraPose = context.viewport
.getSnapshot()
.context.camera?.getSnapshot().context.pose;
if (!cameraPose) throw new Error('no camera pose');
self.send({
type: 'updateRenderer',
props: { cameraPose },
});
});
},
on: {
setAddress: {
actions: [
assign({
address: ({
event: { address },
}: {
event: SetAddressEvent;
}) => {
return address;
},
}),
],
target: 'connecting',
},
updateRenderer: {
actions: [
assign({
rendererProps: ({ event: { props }, context }) => {
return {
...context.rendererProps,
...props,
};
},
queuedRendererEvents: ({ event: { props }, context }) => [
...context.queuedRendererEvents,
...(getEntries(props) as RendererEntries),
],
}),
],
},
},
},
connecting: {
invoke: {
id: 'render',
src: 'renderer',
id: 'connect',
src: 'connect',
input: ({ context }: { context: Context }) => ({
server: context.server,
events: [...context.stagedRendererEvents],
context,
}),
onDone: {
actions: assign({
frame: ({ event }) => event.output,
server: ({ event }) => event.output,
// initially, send all props to renderer
queuedRendererEvents: ({ context }) =>
getEntries(context.rendererProps),
}),
target: 'idle',
target: 'online',
},
},
},
idle: {
always: {
// Renderer props changed while rendering? Then render.
guard: ({ context }) => context.queuedRendererEvents.length > 0,
target: 'render',
online: {
initial: 'render',
states: {
render: {
invoke: {
id: 'render',
src: 'renderer',
input: ({ context }: { context: Context }) => ({
server: context.server,
events: [...context.stagedRendererEvents],
}),
onDone: {
actions: assign({
frame: ({ event }) => {
return event.output;
},
}),
target: 'idle',
},
},
},
idle: {
always: {
// Renderer props changed while rendering? Then render.
guard: ({ context }) => context.queuedRendererEvents.length > 0,
target: 'render',
},
on: {
render: { target: 'render' },
},
exit: assign({
// consumes queue in prep for renderer
stagedRendererEvents: ({ context }) => [
...context.queuedRendererEvents,
],
queuedRendererEvents: [],
}),
},
},
on: {
render: { target: 'render' },
},
exit: assign({
// consumes queue in prep for renderer
stagedRendererEvents: ({ context }) => [
...context.queuedRendererEvents,
],
queuedRendererEvents: [],
}),
},

@@ -176,0 +211,0 @@ },

import { fromPromise, interpret } from 'xstate';
import { hyphaWebsocketClient } from 'imjoy-rpc';
import { Viewport, createViewport } from '@itk-viewer/viewer/viewport.js';
import { RendererEntries, remoteMachine } from './remote-machine.js';
import { RendererEntries, remoteMachine, Context } from './remote-machine.js';
import { mat4, vec3 } from 'gl-matrix';

@@ -10,7 +10,15 @@

connect: ReturnType<typeof fromPromise<unknown>>;
renderer: ReturnType<typeof fromPromise<string>>;
renderer: ReturnType<typeof fromPromise<ArrayBuffer>>;
};
};
const createHyphaRenderer = async (server_url: string) => {
const createHyphaRenderer = async (context: Context) => {
const {
address: server_url,
rendererProps: { image },
} = context;
if (!server_url) {
throw new Error('No server url provided');
}
const config = {

@@ -21,6 +29,7 @@ client_id: 'remote-renderer-test-client',

};
const server = await hyphaWebsocketClient.connectToServer(config);
const renderer = await server.getService('test-agave-renderer');
const hypha = await hyphaWebsocketClient.connectToServer(config);
const renderer = await hypha.getService('test-agave-renderer');
await renderer.setup();
await renderer.setImage('data/aneurism.ome.tif');
await renderer.loadImage(image);
return renderer;

@@ -32,3 +41,3 @@ };

connect: fromPromise(async ({ input }) =>
createHyphaRenderer(input.address)
createHyphaRenderer(input.context)
),

@@ -40,21 +49,35 @@ renderer: fromPromise(

input: {
server: { updateRenderer: (events: unknown) => Promise<string> };
server: {
updateRenderer: (events: unknown) => Promise<ArrayBuffer>;
loadImage: (image: string | undefined) => void;
render: () => Promise<ArrayBuffer>;
};
events: RendererEntries;
};
}) => {
const translatedEvents = events.map(([key, value]) => {
if (key === 'cameraPose') {
const eye = vec3.create();
mat4.getTranslation(eye, value);
const translatedEvents = events
.map(([key, value]) => {
if (key === 'cameraPose') {
const eye = vec3.create();
mat4.getTranslation(eye, value);
const target = vec3.fromValues(value[8], value[9], value[10]);
vec3.subtract(target, eye, target);
const target = vec3.fromValues(value[8], value[9], value[10]);
vec3.subtract(target, eye, target);
const up = vec3.fromValues(value[4], value[5], value[6]);
const up = vec3.fromValues(value[4], value[5], value[6]);
return ['cameraPose', { eye, up, target }];
}
return [key, value];
});
return server.updateRenderer(translatedEvents);
return ['cameraPose', { eye, up, target }];
}
if (key === 'image') {
server.loadImage(value);
return;
}
return [key, value];
})
.filter(Boolean);
server.updateRenderer(translatedEvents);
return server.render();
}

@@ -61,0 +84,0 @@ ),

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc