Enumeration InfiniteEngineInterfaceSignal

The InfiniteEngineInterfaceSignal lists all the signals that may be sent by the InfiniteEngineInterface.

These signals are emitted by the InfiniteEngineInterface when the following occurs :

/** 
* Sample to illustrate the handling of a mouse pick in an InfiniteEngineInterface.
*/
import {
InfiniteEngineInterface, InfiniteFactory, PickingAttachment, PickingAttachmentItem,
Vector3, VisualStates, InfiniteEngineInterfaceSignal, Rectangle, InfiniteEvent,
PrimitiveManagerInterface
} from 'generated_files/documentation/appinfiniteapi';

// the div to render to
let lView3D: HTMLElement;

// create an 3D engine
const lInfiniteEngine: InfiniteEngineInterface = InfiniteFactory.CreateInfiniteEngine();

// What to do on pick ?
let onButtonClicked : (pEvent) => void = undefined;

// What to do on pick ?
let onPicking : (pEvent : InfiniteEvent, _pCallbackData) => void = undefined;

// We pick a rectangle if big enough, else only a point
let pickAtImpl : () => void = undefined;

// bind the 3D rendering to the div
lInfiniteEngine.setView(lView3D);

// ####################################################################################################################################
// ############################################ PICKING ###############################################################################
// ####################################################################################################################################
// Used to copy the relevant portion of a MouseEvent
// position, previous buttons, current button and type
// store also if we started showing the rubber band
interface EventPos
{
x : number;
y : number;
buttons : number;
button : number;
type : string;
// is the rubber band initialized, i.e. have we begun to draw a rectangle ?
rubberInit : boolean;
}
// store the last click to know the extent of the rectangle to pick, and after pick request
// to know the properties of the pick request
// we store a copy of the MouseEvent
const lLastClickEvent: EventPos = {
x: 0,
y: 0,
buttons: 0,
button: 0,
type: '',
rubberInit: false,
};

// What to do on pick ?
onPicking = (pEvent : InfiniteEvent, _pCallbackData) : void =>
{
const lAttachment: PickingAttachment = <PickingAttachment>pEvent.attachments;
// care only about 3d geometries (no line, point, box)
const l3dAttachment: PickingAttachmentItem[] | undefined = lAttachment.geometric;

let lFirstGeometricId: number = 0;
let l3dPosition: Vector3 | undefined = undefined;
if (l3dAttachment !== undefined && l3dAttachment.length > 0)
{
lFirstGeometricId = l3dAttachment[0].instanceId;
l3dPosition = l3dAttachment[0].position;
}

// Mid button click => set Center Of Interest (COI)
if (lLastClickEvent.button === 1) {
if (!l3dPosition) return;
// set the center coi
lInfiniteEngine.getCameraManager().lookAt(l3dPosition);
return;
}

// no left button click => do nothing
if (lLastClickEvent.button !== 0)
{
return;
}
// if double click
if (lLastClickEvent.type === 'dblclick')
{
// fit to geometry
lInfiniteEngine.getCameraManager().fitGeometry(lFirstGeometricId);
return;
}
// clear selected state on pick
let lWasSelected: boolean = false;
if (lFirstGeometricId !== 0)
{
const lGeomState = lInfiniteEngine.getGeometricState(lFirstGeometricId);
lWasSelected = ((lGeomState & VisualStates.S_Selected) !== 0);
}
// if multiple selections => do not change the selected state of a single geometry
// but select all the relevant 3D data instead
if (l3dAttachment && l3dAttachment.length > 1)
{
lWasSelected = false;
}
// unselect everyone
lInfiniteEngine.updateGeometricStateForAll(VisualStates.S_Selected, ~VisualStates.S_Selected);
// and begin
if (lFirstGeometricId !== 0 && !lWasSelected && l3dAttachment)
{
// update visual state of selected items
const lIds = new Uint32Array(l3dAttachment.length);
for (let i = 0; i < l3dAttachment.length; i += 1) {
lIds[i] = l3dAttachment[i].instanceId;
}
lInfiniteEngine.updateGeometricState(lIds, VisualStates.S_Selected, VisualStates.S_Selected);
}
};

// and bind the callback on pick result
lInfiniteEngine.addEventListener(InfiniteEngineInterfaceSignal.Picked, onPicking);

// the rectangle to pick (if relevant)
const lRubberBand: Rectangle = new Rectangle();

// We pick a rectangle if big enough, else only a point
pickAtImpl = (): void =>
{
// single pick if small rectangle
if (((lRubberBand.width <= 3) && (lRubberBand.height <= 3)) || (lRubberBand.width === 0) || (lRubberBand.height === 0))
{
// pick the last point
lInfiniteEngine.pickAt(lLastClickEvent.x, lLastClickEvent.y, false);
}
else
{
// pick an area
lInfiniteEngine.pickRect(lRubberBand, false);
}
// and clear the rectangle in all the cases
lRubberBand.clear();
};

onButtonClicked = (event) : void =>
{
lLastClickEvent.x = event.offsetX;
lLastClickEvent.y = event.offsetY;
lLastClickEvent.button = event.button;
lLastClickEvent.buttons = event.buttons;
lLastClickEvent.type = event.type;
lLastClickEvent.rubberInit = false;

if (lLastClickEvent.buttons === 0)
{
// make a pick
pickAtImpl();
}
};
// on left click => pick
lView3D.addEventListener('click', onButtonClicked);

const onMouseDown = (event) : void =>
{
// store the pick start
lLastClickEvent.x = event.offsetX;
lLastClickEvent.y = event.offsetY;
lLastClickEvent.button = event.button;
lLastClickEvent.buttons = event.buttons;
lLastClickEvent.type = event.type;
// no rubber
lLastClickEvent.rubberInit = false;
};
// store the position to the first pick pos
lView3D.addEventListener('mousedown', onMouseDown);

// when we release the mouse button, make a pick only on middle mouse if close to start pos
// and hide the rubber band
const onMouseUp = (event) : void =>
{
// middle click
if (lLastClickEvent.button === 1 && event.button === 1)
{
if (!lLastClickEvent.rubberInit) {
// if no rectangle => set COI
lLastClickEvent.x = event.offsetX;
lLastClickEvent.y = event.offsetY;
lLastClickEvent.button = event.button;
lLastClickEvent.buttons = event.buttons;
lLastClickEvent.type = event.type;
lLastClickEvent.rubberInit = false;
pickAtImpl();
}
}
const lPrimitiveManager : PrimitiveManagerInterface = lInfiniteEngine.getPrimitiveManager();
lPrimitiveManager.getRubberBandManager().setRubberBandVisible(false);
lLastClickEvent.x = event.offsetX;
lLastClickEvent.y = event.offsetY;
lLastClickEvent.button = event.button;
lLastClickEvent.buttons = event.buttons;
lLastClickEvent.type = event.type;
lLastClickEvent.rubberInit = false;
};

lView3D.addEventListener('mouseup', onMouseUp);

// we we move the mouse, display the rubber band
const onMouseMove = (event) : void =>
{
if (lLastClickEvent.rubberInit || (Math.abs(lLastClickEvent.x - event.offsetX) > 3 || Math.abs(lLastClickEvent.y - event.offsetY) > 3))
{
lRubberBand.x = Math.min(lLastClickEvent.x, event.offsetX);
lRubberBand.y = Math.min(lLastClickEvent.y, event.offsetY);
lRubberBand.width = Math.abs(lLastClickEvent.x - event.offsetX);
lRubberBand.height = Math.abs(lLastClickEvent.y - event.offsetY);
lLastClickEvent.rubberInit = true;
}
if ((lLastClickEvent.buttons === 1) && (event.buttons === 1) && lLastClickEvent.rubberInit)
{
// show/update the rubber band
const lPrimitiveManager: PrimitiveManagerInterface = lInfiniteEngine.getPrimitiveManager();
lPrimitiveManager.getRubberBandManager().setRubberBandRectangle(lRubberBand);
lPrimitiveManager.getRubberBandManager().setRubberBandVisible(true);
}
};
lView3D.addEventListener('mousemove', onMouseMove);

Screenshot sample :
/** 
* Sample to illustrate the screenshot procedure of the InfiniteEngineInterface.
*/
import {
InfiniteEngineInterface, LoadingStates, Vector3, InfiniteEngineLoadingStateAttachment,
InfiniteEngineInterfaceSignal, InfiniteEvent, InfiniteImageInterface, ScreenshotType
} from 'generated_files/documentation/appinfiniteapi';

// We try to make a screenshot when all data is loaded

// the div to render the 3D display
let lView3D: HTMLElement;

// created previously, should receive the image data to be displayed to the user (or ask for a download maybe ?)
let lImageData : HTMLImageElement;

// created previously the position of the camera for the screenshot
let lCameraLocation : Vector3;

// created previously the camera center of interest
let lCenterOfInterest : Vector3;

// created previously the 3D engine
let lInfiniteEngine: InfiniteEngineInterface;

let lScreenshotId : string = '';
// What to do when screenshot is ready ?
let onScreenshotReady : (pEvent : InfiniteEvent, _pCallbackData) => void = undefined;

// What to do when all data is loaded ?
let onDataStateChanged : (pEvent : InfiniteEvent, _pCallbackData) => void = undefined;

// bind the 3D rendering to the div (should have been done earlier :) )
lInfiniteEngine.setView(lView3D);

// we will make screenshot of 1024x1024
lInfiniteEngine.setFixedResolution(1024, 1024, 1);

lInfiniteEngine.addEventListener(InfiniteEngineInterfaceSignal.LoadingStateChanged, onDataStateChanged);
lInfiniteEngine.addEventListener(InfiniteEngineInterfaceSignal.ScreenshotReady, onScreenshotReady);

// go to the expected position / location
lInfiniteEngine.getCameraManager().setCameraLocation(lCameraLocation);
lInfiniteEngine.getCameraManager().lookAt(lCenterOfInterest, 0);

// ####################################################################################################################################
// ############################################ Screenshot ############################################################################
// ####################################################################################################################################

// What to do when state changes ? We wait till everything is loaded and then make a screenshot
onDataStateChanged = (pEvent : InfiniteEvent, _pCallbackData) : void =>
{
// check the attachment
const lStateAttachment : InfiniteEngineLoadingStateAttachment = pEvent.attachments;

// some check, but useless, only for illustration purpose
console.assert(lStateAttachment.newLoadingState === lInfiniteEngine.getResourceLoadingState());

switch (lStateAttachment.newLoadingState)
{
case LoadingStates.S_Loading:
// do nothing if we are still loading
return;
case LoadingStates.S_OutOfBudget:
// some fancy message
console.log('Taking a screenshot without everything loaded');
// but we still make a screenshot :)
break;
default:
break;
}
// make a screenshot request in jpeg with 95% quality, data will be base64 encoded
lScreenshotId = lInfiniteEngine.screenshot(ScreenshotType.ST_Color, true, 'image/jpeg', 0.95);
if (lScreenshotId.length === 0)
{
// for some reason, this failed
console.log('Screenshot request failed');
}
};

// what to do when we get the screenshot result ?
onScreenshotReady = (pEvent : InfiniteEvent, _pCallbackData) : void =>
{
// the image result
const lInfiniteImage : InfiniteImageInterface = pEvent.attachments;

// if the id does not match, bail out
if (lInfiniteImage.screenshotid !== lScreenshotId)
{
console.log('This is not the expected screenshot id, aborting');
return;
}

// is the image valid ? and base64 encoded ?
if ((lInfiniteImage.width === 0) || (!lInfiniteImage.data) || (!lInfiniteImage.base64))
{
console.log('Unexpected screenshot error, aborting');
return;
}

// create the data url in base64
// even if we did not get the expected format, we still get the result
const lDataUrl : string = 'data:' + lInfiniteImage.format + ';base64,' + lInfiniteImage.data;

// resize the image markup
lImageData.width = lInfiniteImage.width;
lImageData.height = lInfiniteImage.height;
// and set data
lImageData.src = lDataUrl;

// we get back to the size of the 3d view but this is up to the application needs
lInfiniteEngine.unsetFixedResolution();
};

Please refer to InfiniteEngineInterface for more information.
Events

Enumeration Members

DataSessionLoaded: "dataSessionLoaded"

Signal sent when a data session has finished loading for the given InfiniteEngineInterface.

Depending on the code, this signal may be called just after DataSessionInterfaceSignal.DMULoadingSuccess if the InfiniteEngineInterface is already bound to the data session when the data session has finished loading, or shortly after InfiniteEngineInterface.bindDataSession or DataSessionInterface.bindInfiniteEngine if the data session was already loaded.

No attachment for events of this type.

DisplayDone: "displayDone"

Called each time the rendering is over (after all is rendered with the callback to window.requestAnimationFrame).

No attachment for events of this type.

LoadingStateChanged: "loadingStateChanged"

Signal sent by the InfiniteEngineInterface when the loading state of the resource manager has changed.

The event tells the old and new loading state.

The attachment for events of this type is a InfiniteEngineLoadingStateAttachment.

Picked: "picked"

Signal sent by the InfiniteEngineInterface when a pick request is completed.

A pick request aks to know the content (i.e. geometries, lines, boxes, points) at specific positions in the 3D display. The picking request may concern a specific position (InfiniteEngineInterface.pickAt), a rectangular area (InfiniteEngineInterface.pickRect) or the element that intersects a ray (InfiniteEngineInterface.pickFromRay) inside the 3d view.

The actual picked point follows the following convention :

picking convention
The attachment for events of this type is a PickingAttachment.
ScreenshotReady: "screenshotReady"

Signal sent by the InfiniteEngineInterface when a screenshot request has finished processing.

The attachment for events of this type is an InfiniteImageInterface.

ViewChanged: "viewChanged"

Signal sent by the InfiniteEngineInterface when the engine has changed its view, i.e. the bound html element is changed (another element or undefined) with a call to InfiniteEngineInterface.setView.

No attachment for events of this type.

ViewResized: "viewResized"

Signal sent by the InfiniteEngineInterface when the rendering size of the display has changed.

This may be due to a change in the canvas size or a call to InfiniteEngineInterface.setMaximumEngineResolution with values inferior to the current rendering size.

No attachment for events of this type.

XRSessionReady: "XRSessionReady"

(WebXR) Signal sent by the InfiniteEngineInterface when a XR Session is ready to be used.

The attachment for events of this type is an InfiniteXRSession which is a XRSession. XR types are mapped to avoid installing WebXR types.

/** 
* Sample to illustrate using a webxr session.
*/
import {
InfiniteEngineInterface, InfiniteEngineInterfaceSignal, InfiniteEvent, InfiniteXRSession,
CameraManagerInterfaceSignal, InfiniteXRReferenceSpace
} from 'generated_files/documentation/appinfiniteapi';

// We try to make a screenshot when all data is loaded

// created previously the 3D engine
let lInfiniteEngine: InfiniteEngineInterface;
// the webXR session
let lCurSession : InfiniteXRSession;

// store the XRSession when ready
lInfiniteEngine.addEventListener(
InfiniteEngineInterfaceSignal.XRSessionReady,
(pEvent: InfiniteEvent) : void =>
{
lCurSession = pEvent.attachments;
}
);

// make some fancy things on camera changes
// we may have used InfiniteEngineInterfaceSignal.DisplayDone
// to be called each frame
lInfiniteEngine.getCameraManager().addEventListener(
CameraManagerInterfaceSignal.CameraLocationChanged,
(_pEvent: InfiniteEvent) : void =>
{
if (!lCurSession)
{
return;
}
const lXRRefSpace : InfiniteXRReferenceSpace | undefined = lInfiniteEngine.getCameraManager().getXRReferenceFrame();
if (!lXRRefSpace)
{
return;
}
// make some computations with XRSession inputs
console.log(lCurSession.inputSources.length);
}
);

// bind the 3D rendering to the div (should have been done earlier :) )
lInfiniteEngine.setView(undefined, { type: 'webxr', options: {} });

The WebXR api should be used with specific hardware.