@inweb/viewer-core
Version:
3D CAD and BIM data Viewer core
615 lines (600 loc) • 19.7 kB
JavaScript
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
// This application incorporates Open Design Alliance software pursuant to a
// license agreement with Open Design Alliance.
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
// All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ODA = global.ODA || {}, global.ODA.Viewer = global.ODA.Viewer || {})));
})(this, (function (exports) { 'use strict';
class CommandsRegistry {
constructor() {
this._commands = new Map();
}
registerCommand(id, handler, description, thisArg) {
this._commands.set(id, { id, handler, thisArg, description });
}
registerCommandAlias(id, alias) {
this.registerCommand(alias, (viewer, ...args) => this.executeCommand(id, viewer, ...args));
}
getCommand(id) {
return this._commands.get(id);
}
getCommands() {
const map = new Map();
this._commands.forEach((value, key) => map.set(key, value));
return map;
}
executeCommand(id, viewer, ...args) {
const command = this._commands.get(id);
if (!command) {
if (viewer) {
const isDraggerCommand = viewer.draggers.includes(id);
if (isDraggerCommand)
return viewer.setActiveDragger(id);
}
console.warn(`Command '${id}' not found`);
return undefined;
}
const { handler, thisArg } = command;
const result = handler.apply(thisArg, [viewer, ...args]);
viewer === null || viewer === void 0 ? void 0 : viewer.emit({ type: "command", data: id, args });
return result;
}
}
const _commandsRegistry = new Map();
function commandsRegistry(viewerType = "") {
let result = _commandsRegistry.get(viewerType);
if (!result) {
result = new CommandsRegistry();
_commandsRegistry.set(viewerType, result);
}
return result;
}
class Dragger {
constructor(viewer) {
this.name = "";
}
dispose() { }
}
class DraggersRegistry {
constructor() {
this._providers = new Map();
}
registerDragger(name, provider) {
this._providers.set(name, provider);
}
registerDraggerAlias(name, alias) {
const provider = this._providers.get(name);
if (provider)
this.registerDragger(alias, (viewer) => provider(viewer));
}
getDraggers() {
const map = new Map();
this._providers.forEach((value, key) => map.set(key, value));
return map;
}
createDragger(name, viewer) {
const provider = this._providers.get(name);
if (!provider)
return null;
const dragger = provider(viewer);
dragger.name = name;
return dragger;
}
}
const _draggersRegistry = new Map();
function draggersRegistry(viewerType = "") {
let result = _draggersRegistry.get(viewerType);
if (!result) {
result = new DraggersRegistry();
_draggersRegistry.set(viewerType, result);
}
return result;
}
class Component {
constructor(viewer) {
this.name = "";
}
dispose() { }
}
class Components {
constructor() {
this._providers = new Map();
}
registerComponent(name, provider) {
this._providers.set(name, provider);
}
registerComponentAlias(name, alias) {
const provider = this._providers.get(name);
if (provider)
this.registerComponent(alias, (viewer) => provider(viewer));
}
getComponents() {
const map = new Map();
this._providers.forEach((value, key) => map.set(key, value));
return map;
}
createComponent(name, viewer) {
const provider = this._providers.get(name);
if (!provider)
return null;
const component = provider(viewer);
component.name = name;
return component;
}
}
const _components = new Map();
function componentsRegistry(viewerType = "") {
let result = _components.get(viewerType);
if (!result) {
result = new Components();
_components.set(viewerType, result);
}
return result;
}
class Loader {
constructor() {
this.name = "";
this.abortController = new AbortController();
}
dispose() {
this.abortController.abort();
this.abortController = undefined;
}
isSupport(file, format) {
return false;
}
load(file, format, params) {
return Promise.resolve(this);
}
cancel() {
this.abortController.abort();
}
yield() {
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
extractFileName(file) {
const regex = /[^/\\?#:]+(?=\?|#|$)/;
if (typeof file === "string")
return (file.match(regex) || [])[0];
else if (file instanceof globalThis.File)
return (file.name.match(regex) || [])[0];
return undefined;
}
}
class Loaders {
constructor() {
this._providers = new Map();
}
registerLoader(name, provider) {
this._providers.set(name, provider);
}
getLoader(name) {
return this._providers.get(name);
}
getLoaders() {
const map = new Map();
this._providers.forEach((value, key) => map.set(key, value));
return map;
}
createLoader(viewer, file, format) {
let result = null;
this._providers.forEach((provider, key) => {
const loader = provider(viewer);
if (loader.isSupport(file, format)) {
result = loader;
result.name = key;
}
});
return result;
}
}
const _loaders = new Map();
function loadersRegistry(viewerType = "") {
let result = _loaders.get(viewerType);
if (!result) {
result = new Loaders();
_loaders.set(viewerType, result);
}
return result;
}
function defaultOptions() {
return {
showWCS: true,
cameraAnimation: true,
antialiasing: true,
groundShadow: false,
shadows: false,
cameraAxisXSpeed: 4,
cameraAxisYSpeed: 1,
ambientOcclusion: false,
enableStreamingMode: true,
enablePartialMode: false,
memoryLimit: 3294967296,
cuttingPlaneFillColor: { red: 0xff, green: 0x98, blue: 0x00 },
edgesColor: { r: 0xff, g: 0x98, b: 0x00 },
facesColor: { r: 0xff, g: 0x98, b: 0x00 },
edgesVisibility: true,
edgesOverlap: true,
facesOverlap: false,
facesTransparancy: 200,
enableCustomHighlight: true,
sceneGraph: false,
edgeModel: true,
reverseZoomWheel: false,
enableZoomWheel: true,
enableGestures: true,
geometryType: "vsfx",
rulerUnit: "Default",
rulerPrecision: 2,
cameraMode: "perspective",
};
}
class Options {
constructor(emitter) {
this._emitter = emitter;
this._data = defaultOptions();
this.loadFromStorage();
}
static defaults() {
return defaultOptions();
}
notifierChangeEvent() {
console.warn("Options.notifierChangeEvent() has been deprecated since 25.3 and will be removed in a future release, use Options.change() instead.");
this.change();
}
change() {
if (this._emitter !== undefined) {
this.saveToStorage();
this._emitter.emit({ type: "optionschange", data: this });
}
}
saveToStorage() {
if (typeof window !== "undefined")
try {
localStorage.setItem("od-client-settings", JSON.stringify(this.data));
}
catch (error) {
console.error("Cannot save client settings.", error);
}
}
loadFromStorage() {
if (typeof window !== "undefined")
try {
const item = localStorage.getItem("od-client-settings");
if (item) {
const data = JSON.parse(item);
this.data = { ...data };
}
}
catch (error) {
console.error("Cannot load client settings.", error);
}
}
resetToDefaults(fields) {
if (fields !== undefined) {
const defaults = Options.defaults();
const resetData = fields.reduce((acc, field) => {
acc[field] = defaults[field];
return acc;
}, {});
this.data = { ...this.data, ...resetData };
}
else {
this.data = { ...this.data, ...Options.defaults() };
}
}
get data() {
return this._data;
}
set data(value) {
const enablePartialMode = value.enableStreamingMode ? value.enablePartialMode : false;
const sceneGraph = enablePartialMode ? false : value.sceneGraph;
this._data = { ...Options.defaults(), ...this._data, ...value, enablePartialMode, sceneGraph };
this.change();
}
get showWCS() {
return this._data.showWCS;
}
set showWCS(value) {
this._data.showWCS = value;
this.change();
}
get cameraAnimation() {
return this._data.cameraAnimation;
}
set cameraAnimation(value) {
this._data.cameraAnimation = value;
this.change();
}
get antialiasing() {
return this._data.antialiasing;
}
set antialiasing(value) {
this._data.antialiasing = value;
this.change();
}
get groundShadow() {
return this._data.groundShadow;
}
set groundShadow(value) {
this._data.groundShadow = value;
this.change();
}
get shadows() {
return this._data.shadows;
}
set shadows(value) {
this._data.shadows = value;
this.change();
}
get cameraAxisXSpeed() {
return this._data.cameraAxisXSpeed;
}
set cameraAxisXSpeed(value) {
this._data.cameraAxisXSpeed = value;
this.change();
}
get cameraAxisYSpeed() {
return this._data.cameraAxisYSpeed;
}
set cameraAxisYSpeed(value) {
this.cameraAxisYSpeed = value;
this.change();
}
get ambientOcclusion() {
return this._data.ambientOcclusion;
}
set ambientOcclusion(value) {
this._data.ambientOcclusion = value;
this.change();
}
get enableStreamingMode() {
return this._data.enableStreamingMode;
}
set enableStreamingMode(value) {
this._data.enableStreamingMode = value;
if (!value)
this._data.enablePartialMode = false;
this.change();
}
get enablePartialMode() {
return this._data.enablePartialMode;
}
set enablePartialMode(value) {
this._data.enablePartialMode = value;
if (value) {
this._data.enableStreamingMode = true;
this._data.sceneGraph = false;
}
this.change();
}
get memoryLimit() {
return this._data.memoryLimit;
}
set memoryLimit(value) {
this._data.memoryLimit = value;
this.change();
}
get cuttingPlaneFillColor() {
return this._data.cuttingPlaneFillColor;
}
set cuttingPlaneFillColor(value) {
this._data.cuttingPlaneFillColor = value;
this.change();
}
get edgesColor() {
return this._data.edgesColor;
}
set edgesColor(value) {
this._data.edgesColor = value;
this.change();
}
get facesColor() {
return this._data.facesColor;
}
set facesColor(value) {
this._data.facesColor = value;
this.change();
}
get edgesVisibility() {
return this._data.edgesVisibility;
}
set edgesVisibility(value) {
this._data.edgesVisibility = value;
this.change();
}
get edgesOverlap() {
return this._data.edgesOverlap;
}
set edgesOverlap(value) {
this._data.edgesOverlap = value;
this.change();
}
get facesOverlap() {
return this._data.facesOverlap;
}
set facesOverlap(value) {
this._data.facesOverlap = value;
this.change();
}
get facesTransparancy() {
return this._data.facesTransparancy;
}
set facesTransparancy(value) {
this._data.facesTransparancy = value;
this.change();
}
get enableCustomHighlight() {
return this._data.enableCustomHighlight;
}
set enableCustomHighlight(value) {
this._data.enableCustomHighlight = value;
this.change();
}
get sceneGraph() {
return this._data.sceneGraph;
}
set sceneGraph(value) {
this._data.sceneGraph = value;
if (value)
this._data.enablePartialMode = false;
this.change();
}
get edgeModel() {
return Boolean(this._data.edgeModel);
}
set edgeModel(value) {
this._data.edgeModel = Boolean(value);
this.change();
}
get reverseZoomWheel() {
return this._data.reverseZoomWheel;
}
set reverseZoomWheel(value) {
this._data.reverseZoomWheel = !!value;
this.change();
}
get enableZoomWheel() {
return this._data.enableZoomWheel;
}
set enableZoomWheel(value) {
this._data.enableZoomWheel = !!value;
this.change();
}
get enableGestures() {
return this._data.enableGestures;
}
set enableGestures(value) {
this._data.enableGestures = !!value;
this.change();
}
get geometryType() {
return this._data.geometryType;
}
set geometryType(value) {
this._data.geometryType = value;
this.change();
}
get rulerUnit() {
return this._data.rulerUnit;
}
set rulerUnit(value) {
this._data.rulerUnit = value;
this.change();
}
get rulerPrecision() {
return this._data.rulerPrecision;
}
set rulerPrecision(value) {
this._data.rulerPrecision = value;
this.change();
}
get cameraMode() {
return this._data.cameraMode || "perspective";
}
set cameraMode(value) {
this._data.cameraMode = value;
this.change();
}
}
const CanvasEvents = [
"click",
"contextmenu",
"dblclick",
"mousedown",
"mouseleave",
"mousemove",
"mouseup",
"pointercancel",
"pointerdown",
"pointerleave",
"pointermove",
"pointerup",
"touchcancel",
"touchend",
"touchmove",
"touchstart",
"wheel",
];
const CANVAS_EVENTS = CanvasEvents;
class Info {
constructor() {
this.performance = {
fps: 0,
frameTime: 0,
timeToFirstRender: 0,
loadTime: 0,
};
this.render = {
viewport: { width: 0, height: 0 },
antialiasing: "",
drawCalls: 0,
triangles: 0,
points: 0,
lines: 0,
};
this.scene = {
objects: 0,
triangles: 0,
points: 0,
lines: 0,
edges: 0,
};
this.optimizedScene = {
objects: 0,
triangles: 0,
points: 0,
lines: 0,
edges: 0,
};
this.memory = {
geometries: 0,
geometryBytes: 0,
textures: 0,
textureBytes: 0,
materials: 0,
totalEstimatedGpuBytes: 0,
usedJSHeapSize: 0,
};
this.system = {
webglRenderer: "",
webglVendor: "",
};
}
}
exports.CANVAS_EVENTS = CANVAS_EVENTS;
exports.CanvasEvents = CanvasEvents;
exports.Component = Component;
exports.Dragger = Dragger;
exports.Info = Info;
exports.Loader = Loader;
exports.Options = Options;
exports.commandsRegistry = commandsRegistry;
exports.componentsRegistry = componentsRegistry;
exports.defaultOptions = defaultOptions;
exports.draggersRegistry = draggersRegistry;
exports.loadersRegistry = loadersRegistry;
}));
//# sourceMappingURL=viewer-core.js.map