diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6c699e36c67a..f027cb2f0f83 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -105,8 +105,9 @@ rush.json @iTwin/itwinjs-core-admins /core/ecschema-* @calebmshafer @ColinKerr @wgoehrig /core/electron @wgoehrig @ramanujam-raman /core/express-server @calebmshafer @wgoehrig @ramanujam-raman +/core/extension @calebmshafer @wgoehrig @aruniverse @kckst8 /core/frontend @kabentley @bbastings @iTwin/itwinjs-core-display -/core/frontend/src/extension @calebmshafer @wgoehrig +/core/frontend/src/extension @calebmshafer @wgoehrig @aruniverse @kckst8 /core/frontend-devtools @iTwin/itwinjs-core-display @Ellord207 /core/geometry @bbastings @mgooding @dassaf4 /core/hypermodeling @bbastings @iTwin/itwinjs-core-display @@ -134,6 +135,7 @@ rush.json @iTwin/itwinjs-core-admins /example-code @iTwin/itwinjs-core-admins /extensions @bsteinbk @calebmshafer +/extensions/test-extension @calebmshafer @wgoehrig @aruniverse @kckst8 /extensions/map-layers @bsteinbk @mdastous-bentley /full-stack-tests/core @iTwin/itwinjs-core-admins @@ -163,7 +165,7 @@ rush.json @iTwin/itwinjs-core-admins /tools/backend-webpack @calebmshafer @wgoehrig /tools/build @calebmshafer @wgoehrig /tools/certa @calebmshafer @wgoehrig -/tools/webpack-core @calebmshafer @wgoehrig +/tools/webpack-core @calebmshafer @wgoehrig @aruniverse /tools/ecschema2ts @calebmshafer @ColinKerr @wgoehrig /tools/eslint-plugin @calebmshafer @paulius-valiunas /tools/internal @calebmshafer @wgoehrig diff --git a/clients/imodelhub/CHANGELOG.json b/clients/imodelhub/CHANGELOG.json index 69838f4bcfeb..7ec8e71592d6 100644 --- a/clients/imodelhub/CHANGELOG.json +++ b/clients/imodelhub/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@bentley/imodelbank-client", "entries": [ + { + "version": "3.0.2", + "tag": "@bentley/imodelbank-client_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:12 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@bentley/imodelbank-client_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@bentley/imodelbank-client_v3.0.0", diff --git a/clients/imodelhub/CHANGELOG.md b/clients/imodelhub/CHANGELOG.md index 0bc9d413c492..18635dc6760c 100644 --- a/clients/imodelhub/CHANGELOG.md +++ b/clients/imodelhub/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @bentley/imodelbank-client -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:12 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:12 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/clients/imodelhub/package.json b/clients/imodelhub/package.json index 6b1b20355efe..a4cc94226796 100644 --- a/clients/imodelhub/package.json +++ b/clients/imodelhub/package.json @@ -1,7 +1,7 @@ { "name": "@bentley/imodelbank-client", "private": true, - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iModel.js iModelHub Client", "main": "lib/cjs/imodelhub-client.js", "modules": "lib/esm/imodelhub-client.js", @@ -48,7 +48,7 @@ "superagent": "^7.0.1" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21" }, "devDependencies": { "@itwin/core-backend": "workspace:*", diff --git a/common/api/appui-abstract.api.md b/common/api/appui-abstract.api.md index aa894beea9b9..e95387609b8f 100644 --- a/common/api/appui-abstract.api.md +++ b/common/api/appui-abstract.api.md @@ -253,11 +253,11 @@ export abstract class BaseQuantityDescription implements PropertyDescription { // @public export class BaseUiItemsProvider implements UiItemsProvider { - constructor(_providerId: string, isSupportedStage?: ((stageId: string, stageUsage: string, stageAppData?: any) => boolean) | undefined); + constructor(_providerId: string, isSupportedStage?: ((stageId: string, stageUsage: string, stageAppData?: any, provider?: UiItemsProvider | undefined) => boolean) | undefined); // (undocumented) get id(): string; // (undocumented) - isSupportedStage?: ((stageId: string, stageUsage: string, stageAppData?: any) => boolean) | undefined; + isSupportedStage?: ((stageId: string, stageUsage: string, stageAppData?: any, provider?: UiItemsProvider | undefined) => boolean) | undefined; // (undocumented) onUnregister(): void; provideBackstageItems(): BackstageItem[]; @@ -1200,9 +1200,15 @@ export interface IconListEditorParams extends BasePropertyEditorParams { // @public export class IconSpecUtilities { + // @deprecated static createSvgIconSpec(svgSrc: string): string; + static createWebComponentIconSpec(srcString: string): string; + // @deprecated static getSvgSource(iconSpec: string): string | undefined; + static getWebComponentSource(iconSpec: string): string | undefined; static readonly SVG_PREFIX = "svg:"; + // (undocumented) + static readonly WEB_COMPONENT_PREFIX = "webSvg:"; } // @internal @@ -2099,6 +2105,8 @@ export enum UiItemsApplicationAction { // @public export class UiItemsManager { + // @internal + static clearAllProviders(): void; static getBackstageItems(): BackstageItem[]; static getStatusBarItems(stageId: string, stageUsage: string, stageAppData?: any): CommonStatusBarItem[]; static getToolbarButtonItems(stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation, stageAppData?: any): CommonToolbarItem[]; diff --git a/common/api/appui-react.api.md b/common/api/appui-react.api.md index 5a60bb855538..ff59b9a8a629 100644 --- a/common/api/appui-react.api.md +++ b/common/api/appui-react.api.md @@ -6779,10 +6779,10 @@ export class UiFramework { static getWidgetOpacity(): number; // @alpha (undocumented) static get hideIsolateEmphasizeActionHandler(): HideIsolateEmphasizeActionHandler; - static initialize(store: Store | undefined, frameworkStateKey?: string): Promise; + static initialize(store: Store | undefined, frameworkStateKey?: string, startInUi1Mode?: boolean): Promise; static get initialized(): boolean; // @internal - static initializeEx(store: Store | undefined, frameworkStateKey?: string): Promise; + static initializeEx(store: Store | undefined, frameworkStateKey?: string, startInUi1Mode?: boolean): Promise; static initializeStateFromUserSettingsProviders(immediateSync?: boolean): Promise; // @alpha static get isContextMenuOpen(): boolean; diff --git a/common/api/components-react.api.md b/common/api/components-react.api.md index 976ebc0a3ebc..6af63e102704 100644 --- a/common/api/components-react.api.md +++ b/common/api/components-react.api.md @@ -1246,9 +1246,9 @@ export function getVisibleDescendants(model: TreeModel, parentNode: TreeModelNod export interface GridCategoryItem extends FlatGridItemBase { // (undocumented) readonly derivedCategory: PropertyCategory; - // (undocumented) + // @deprecated (undocumented) getChildCategories(): GridCategoryItem[]; - // (undocumented) + // @deprecated (undocumented) getDescendantCategoriesAndSelf(): GridCategoryItem[]; // (undocumented) readonly name: string; @@ -1493,9 +1493,9 @@ export interface IMutableFlatPropertyGridItem { export interface IMutableGridCategoryItem extends IMutableFlatPropertyGridItem { // (undocumented) derivedCategory: PropertyCategory; - // (undocumented) + // @deprecated (undocumented) getChildCategories(): IMutableGridCategoryItem[]; - // (undocumented) + // @deprecated (undocumented) getDescendantCategoriesAndSelf(): IMutableGridCategoryItem[]; // (undocumented) isRootCategory: boolean; @@ -2912,7 +2912,7 @@ export class ShortDateTypeConverter extends DateTimeTypeConverterBase { protected getTimeFormat(): TimeFormat; } -// @public +// @public @deprecated export class ShowHideDialog extends React.PureComponent, ShowHideDialogState> { constructor(props: ShowHideDialogProps); // @internal (undocumented) @@ -2923,17 +2923,17 @@ export class ShowHideDialog extends React.PureComponent; } -// @public +// @public @deprecated export interface ShowHideDialogProps extends GlobalDialogProps { initialHidden?: T[]; items: Array>; onShowHideChange?: (cols: T[]) => boolean | undefined; } -// @public +// @public @deprecated export type ShowHideID = string | number | symbol; -// @public +// @public @deprecated export interface ShowHideItem { // (undocumented) id: T; @@ -2941,7 +2941,7 @@ export interface ShowHideItem { label: string; } -// @public +// @public @deprecated export class ShowHideMenu extends React.PureComponent, ShowHideMenuState> { // @internal constructor(props: ShowHideMenuProps); @@ -2953,7 +2953,7 @@ export class ShowHideMenu extends React.PureComponent; } -// @public +// @public @deprecated export interface ShowHideMenuProps extends GlobalContextMenuProps { initialHidden?: T[]; items: Array>; diff --git a/common/api/core-bentley.api.md b/common/api/core-bentley.api.md index ca46ab3a09b9..061bad2bd09b 100644 --- a/common/api/core-bentley.api.md +++ b/common/api/core-bentley.api.md @@ -1527,6 +1527,23 @@ export function utf8ToString(utf8: Uint8Array): string | undefined; // @internal export function utf8ToStringPolyfill(utf8: Uint8Array): string | undefined; +// @internal +export class YieldManager { + constructor(options?: YieldManagerOptions); + // (undocumented) + protected actualYield(): Promise; + // (undocumented) + allowYield(): Promise; + // (undocumented) + options: Readonly>; +} + +// @internal +export interface YieldManagerOptions { + // (undocumented) + iterationsBeforeYield?: number; +} + // (No @packageDocumentation comment for this package) diff --git a/common/api/core-common.api.md b/common/api/core-common.api.md index 53850dafcafa..b0be0d1668ce 100644 --- a/common/api/core-common.api.md +++ b/common/api/core-common.api.md @@ -405,6 +405,7 @@ export interface BackgroundMapProps { // @beta export class BackgroundMapProvider { + clone(changedProps: BackgroundMapProviderProps): BackgroundMapProvider; equals(other: BackgroundMapProvider): boolean; // @internal (undocumented) static fromBackgroundMapProps(props: DeprecatedBackgroundMapProps): BackgroundMapProvider; @@ -1255,308 +1256,158 @@ export class CodeSpec { } // @public -export enum ColorByName { - // (undocumented) - aliceBlue = 16775408, - // (undocumented) - amber = 49151, - // (undocumented) - antiqueWhite = 14150650, - // (undocumented) - aqua = 16776960, - // (undocumented) - aquamarine = 13959039, - // (undocumented) - azure = 16777200, - // (undocumented) - beige = 14480885, - // (undocumented) - bisque = 12903679, - // (undocumented) - black = 0, - // (undocumented) - blanchedAlmond = 13495295, - // (undocumented) - blue = 16711680, - // (undocumented) - blueViolet = 14822282, - // (undocumented) - brown = 2763429, - // (undocumented) - burlyWood = 8894686, - // (undocumented) - cadetBlue = 10526303, - // (undocumented) - chartreuse = 65407, - // (undocumented) - chocolate = 1993170, - // (undocumented) - coral = 5275647, - // (undocumented) - cornflowerBlue = 15570276, - // (undocumented) - cornSilk = 14481663, - // (undocumented) - crimson = 3937500, - // (undocumented) - cyan = 16776960, - // (undocumented) - darkBlue = 9109504, - // (undocumented) - darkBrown = 2179941, - // (undocumented) - darkCyan = 9145088, - // (undocumented) - darkGoldenrod = 755384, - // (undocumented) - darkGray = 11119017, - // (undocumented) - darkGreen = 25600, - // (undocumented) - darkGrey = 11119017, - // (undocumented) - darkKhaki = 7059389, - // (undocumented) - darkMagenta = 9109643, - // (undocumented) - darkOliveGreen = 3107669, - // (undocumented) - darkOrange = 36095, - // (undocumented) - darkOrchid = 13382297, - // (undocumented) - darkRed = 139, - // (undocumented) - darkSalmon = 8034025, - // (undocumented) - darkSeagreen = 9419919, - // (undocumented) - darkSlateBlue = 9125192, - // (undocumented) - darkSlateGray = 5197615, - // (undocumented) - darkSlateGrey = 5197615, - // (undocumented) - darkTurquoise = 13749760, - // (undocumented) - darkViolet = 13828244, - // (undocumented) - deepPink = 9639167, - // (undocumented) - deepSkyBlue = 16760576, - // (undocumented) - dimGray = 6908265, - // (undocumented) - dimGrey = 6908265, - // (undocumented) - dodgerBlue = 16748574, - // (undocumented) - fireBrick = 2237106, - // (undocumented) - floralWhite = 15792895, - // (undocumented) - forestGreen = 2263842, - // (undocumented) - fuchsia = 16711935, - // (undocumented) - gainsboro = 14474460, - // (undocumented) - ghostWhite = 16775416, - // (undocumented) - gold = 55295, - // (undocumented) - goldenrod = 2139610, - // (undocumented) - gray = 8421504, - // (undocumented) - green = 32768, - // (undocumented) - greenYellow = 3145645, - // (undocumented) - grey = 8421504, - // (undocumented) - honeydew = 15794160, - // (undocumented) - hotPink = 11823615, - // (undocumented) - indianRed = 6053069, - // (undocumented) - indigo = 8519755, - // (undocumented) - ivory = 15794175, - // (undocumented) - khaki = 9234160, - // (undocumented) - lavender = 16443110, - // (undocumented) - lavenderBlush = 16118015, - // (undocumented) - lawnGreen = 64636, - // (undocumented) - lemonChiffon = 13499135, - // (undocumented) - lightBlue = 15128749, - // (undocumented) - lightCoral = 8421616, - // (undocumented) - lightCyan = 16777184, - // (undocumented) - lightGoldenrodYellow = 13826810, - // (undocumented) - lightGray = 13882323, - // (undocumented) - lightGreen = 9498256, - // (undocumented) - lightGrey = 13882323, - // (undocumented) - lightPink = 12695295, - // (undocumented) - lightSalmon = 8036607, - // (undocumented) - lightSeagreen = 11186720, - // (undocumented) - lightSkyBlue = 16436871, - // (undocumented) - lightSlateGray = 10061943, - // (undocumented) - lightSlateGrey = 10061943, - // (undocumented) - lightSteelBlue = 14599344, - // (undocumented) - lightyellow = 14745599, - // (undocumented) - lime = 65280, - // (undocumented) - limeGreen = 3329330, - // (undocumented) - linen = 15134970, - // (undocumented) - magenta = 16711935, - // (undocumented) - maroon = 128, - // (undocumented) - mediumAquamarine = 11193702, - // (undocumented) - mediumBlue = 13434880, - // (undocumented) - mediumOrchid = 13850042, - // (undocumented) - mediumPurple = 14381203, - // (undocumented) - mediumSeaGreen = 7451452, - // (undocumented) - mediumSlateBlue = 15624315, - // (undocumented) - mediumSpringGreen = 10156544, - // (undocumented) - mediumTurquoise = 13422920, - // (undocumented) - mediumVioletRed = 8721863, - // (undocumented) - midnightBlue = 7346457, - // (undocumented) - mintCream = 16449525, - // (undocumented) - mistyRose = 14804223, - // (undocumented) - moccasin = 11920639, - // (undocumented) - navajoWhite = 11394815, - // (undocumented) - navy = 8388608, - // (undocumented) - oldLace = 15136253, - // (undocumented) - olive = 32896, - // (undocumented) - oliveDrab = 2330219, - // (undocumented) - orange = 42495, - // (undocumented) - orangeRed = 17919, - // (undocumented) - orchid = 14053594, - // (undocumented) - paleGoldenrod = 11200750, - // (undocumented) - paleGreen = 10025880, - // (undocumented) - paleTurquoise = 15658671, - // (undocumented) - paleVioletRed = 9662683, - // (undocumented) - papayaWhip = 14020607, - // (undocumented) - peachPuff = 12180223, - // (undocumented) - peru = 4163021, - // (undocumented) - pink = 13353215, - // (undocumented) - plum = 14524637, - // (undocumented) - powderBlue = 15130800, - // (undocumented) - purple = 8388736, - // (undocumented) - rebeccaPurple = 10040166, - // (undocumented) - red = 255, - // (undocumented) - rosyBrown = 9408444, - // (undocumented) - royalBlue = 14772545, - // (undocumented) - saddleBrown = 1262987, - // (undocumented) - salmon = 7504122, - // (undocumented) - sandyBrown = 6333684, - // (undocumented) - seaGreen = 5737262, - // (undocumented) - seaShell = 15660543, - // (undocumented) - sienna = 2970272, - // (undocumented) - silver = 12632256, - // (undocumented) - skyBlue = 15453831, - // (undocumented) - slateBlue = 13458026, - // (undocumented) - slateGray = 9470064, - // (undocumented) - slateGrey = 9470064, - // (undocumented) - snow = 16448255, - // (undocumented) - springGreen = 8388352, - // (undocumented) - steelBlue = 11829830, - // (undocumented) - tan = 9221330, - // (undocumented) - teal = 8421376, - // (undocumented) - thistle = 14204888, - // (undocumented) - tomato = 4678655, - // (undocumented) - turquoise = 13688896, - // (undocumented) - violet = 15631086, - // (undocumented) - wheat = 11788021, - // (undocumented) - white = 16777215, - // (undocumented) - whiteSmoke = 16119285, - // (undocumented) - yellow = 65535, - // (undocumented) - yellowGreen = 3329434 -} +export const ColorByName: { + aliceBlue: number; + amber: number; + antiqueWhite: number; + aqua: number; + aquamarine: number; + azure: number; + beige: number; + bisque: number; + black: number; + blanchedAlmond: number; + blue: number; + blueViolet: number; + brown: number; + burlyWood: number; + cadetBlue: number; + chartreuse: number; + chocolate: number; + coral: number; + cornflowerBlue: number; + cornSilk: number; + crimson: number; + cyan: number; + darkBlue: number; + darkBrown: number; + darkCyan: number; + darkGoldenrod: number; + darkGray: number; + darkGreen: number; + darkGrey: number; + darkKhaki: number; + darkMagenta: number; + darkOliveGreen: number; + darkOrange: number; + darkOrchid: number; + darkRed: number; + darkSalmon: number; + darkSeagreen: number; + darkSlateBlue: number; + darkSlateGray: number; + darkSlateGrey: number; + darkTurquoise: number; + darkViolet: number; + deepPink: number; + deepSkyBlue: number; + dimGray: number; + dimGrey: number; + dodgerBlue: number; + fireBrick: number; + floralWhite: number; + forestGreen: number; + fuchsia: number; + gainsboro: number; + ghostWhite: number; + gold: number; + goldenrod: number; + gray: number; + green: number; + greenYellow: number; + grey: number; + honeydew: number; + hotPink: number; + indianRed: number; + indigo: number; + ivory: number; + khaki: number; + lavender: number; + lavenderBlush: number; + lawnGreen: number; + lemonChiffon: number; + lightBlue: number; + lightCoral: number; + lightCyan: number; + lightGoldenrodYellow: number; + lightGray: number; + lightGreen: number; + lightGrey: number; + lightPink: number; + lightSalmon: number; + lightSeagreen: number; + lightSkyBlue: number; + lightSlateGray: number; + lightSlateGrey: number; + lightSteelBlue: number; + lightyellow: number; + lime: number; + limeGreen: number; + linen: number; + magenta: number; + maroon: number; + mediumAquamarine: number; + mediumBlue: number; + mediumOrchid: number; + mediumPurple: number; + mediumSeaGreen: number; + mediumSlateBlue: number; + mediumSpringGreen: number; + mediumTurquoise: number; + mediumVioletRed: number; + midnightBlue: number; + mintCream: number; + mistyRose: number; + moccasin: number; + navajoWhite: number; + navy: number; + oldLace: number; + olive: number; + oliveDrab: number; + orange: number; + orangeRed: number; + orchid: number; + paleGoldenrod: number; + paleGreen: number; + paleTurquoise: number; + paleVioletRed: number; + papayaWhip: number; + peachPuff: number; + peru: number; + pink: number; + plum: number; + powderBlue: number; + purple: number; + rebeccaPurple: number; + red: number; + rosyBrown: number; + royalBlue: number; + saddleBrown: number; + salmon: number; + sandyBrown: number; + seaGreen: number; + seaShell: number; + sienna: number; + silver: number; + skyBlue: number; + slateBlue: number; + slateGray: number; + slateGrey: number; + snow: number; + springGreen: number; + steelBlue: number; + tan: number; + teal: number; + thistle: number; + tomato: number; + turquoise: number; + violet: number; + wheat: number; + white: number; + whiteSmoke: number; + yellow: number; + yellowGreen: number; +}; // @public export class ColorDef { @@ -1570,10 +1421,10 @@ export class ColorDef { t: number; }; // @internal (undocumented) - static computeTbgr(val?: string | ColorDefProps): number; - static computeTbgrFromComponents(red: number, green: number, blue: number, transparency?: number): number; - static computeTbgrFromHSL(h: number, s: number, l: number, transparency?: number): number; - static computeTbgrFromString(val: string): number; + static computeTbgr(val?: string | ColorDefProps): ColorDefProps; + static computeTbgrFromComponents(red: number, green: number, blue: number, transparency?: number): ColorDefProps; + static computeTbgrFromHSL(h: number, s: number, l: number, transparency?: number): ColorDefProps; + static computeTbgrFromString(val: string): ColorDefProps; static create(val?: string | ColorDefProps): ColorDef; equals(other: ColorDef): boolean; static from(red: number, green: number, blue: number, transparency?: number): ColorDef; @@ -1581,46 +1432,48 @@ export class ColorDef { static fromHSV(hsv: HSVColor, transparency?: number): ColorDef; static fromJSON(json?: ColorDefProps): ColorDef; static fromString(val: string): ColorDef; - static fromTbgr(tbgr: number): ColorDef; + static fromTbgr(tbgr: ColorDefProps): ColorDef; getAbgr(): number; - static getAbgr(tbgr: number): number; + static getAbgr(tbgr: ColorDefProps): number; getAlpha(): number; - static getAlpha(tbgr: number): number; - static getColors(tbgr: number): { + static getAlpha(tbgr: ColorDefProps): number; + static getColors(tbgr: ColorDefProps): { b: number; g: number; r: number; t: number; }; - static getName(tbgr: number): string | undefined; + static getName(tbgr: ColorDefProps): string | undefined; getRgb(): number; - static getRgb(tbgr: number): number; + static getRgb(tbgr: ColorDefProps): number; getTransparency(): number; - static getTransparency(tbgr: number): number; + static getTransparency(tbgr: ColorDefProps): number; static readonly green: ColorDef; inverse(): ColorDef; - static inverse(tbgr: number): number; + static inverse(tbgr: ColorDefProps): ColorDefProps; get isOpaque(): boolean; - static isOpaque(tbgr: number): boolean; + static isOpaque(tbgr: ColorDefProps): boolean; + static isValidColor(val: string | number): boolean; lerp(color2: ColorDef, weight: number): ColorDef; - static lerp(tbgr1: number, tbgr2: number, weight: number): number; + static lerp(tbgr1: ColorDefProps, tbgr2: ColorDefProps, weight: number): ColorDefProps; get name(): string | undefined; static readonly red: ColorDef; - get tbgr(): number; + get tbgr(): ColorDefProps; toHexString(): string; - static toHexString(tbgr: number): string; + static toHexString(tbgr: ColorDefProps): string; toHSL(): HSLColor; toHSV(): HSVColor; toJSON(): ColorDefProps; toRgbaString(): string; - static toRgbaString(tbgr: number): string; + static toRgbaString(tbgr: ColorDefProps): string; toRgbString(): string; - static toRgbString(tbgr: number): string; + static toRgbString(tbgr: ColorDefProps): string; + static tryComputeTbgrFromString(val: string): ColorDefProps | undefined; static readonly white: ColorDef; withAlpha(alpha: number): ColorDef; - static withAlpha(tbgr: number, alpha: number): number; + static withAlpha(tbgr: ColorDefProps, alpha: number): number; withTransparency(transparency: number): ColorDef; - static withTransparency(tbgr: number, transparency: number): number; + static withTransparency(tbgr: ColorDefProps, transparency: number): ColorDefProps; } // @public diff --git a/common/api/core-frontend.api.md b/common/api/core-frontend.api.md index 9f3ef8fd7e98..f58b66e75929 100644 --- a/common/api/core-frontend.api.md +++ b/common/api/core-frontend.api.md @@ -54,6 +54,7 @@ import { CodeSpec } from '@itwin/core-common'; import { ColorDef } from '@itwin/core-common'; import { ColorDefProps } from '@itwin/core-common'; import { ColorIndex } from '@itwin/core-common'; +import { CommonToolbarItem } from '@itwin/appui-abstract'; import { CompressedId64Set } from '@itwin/core-bentley'; import { Constructor } from '@itwin/core-bentley'; import { ContentIdProvider } from '@itwin/core-common'; @@ -218,6 +219,8 @@ import { PolylineTypeFlags } from '@itwin/core-common'; import { PrimaryTileTreeId } from '@itwin/core-common'; import { PromiseReturnType } from '@itwin/core-bentley'; import { PropertyDescription } from '@itwin/appui-abstract'; +import { PropertyRecord } from '@itwin/appui-abstract'; +import { PropertyValue } from '@itwin/appui-abstract'; import { QParams2d } from '@itwin/core-common'; import { QParams3d } from '@itwin/core-common'; import { QPoint2d } from '@itwin/core-common'; @@ -290,12 +293,15 @@ import { TileHeader } from '@itwin/core-common'; import { TileProps } from '@itwin/core-common'; import { TileReadStatus } from '@itwin/core-common'; import { TileVersionInfo } from '@itwin/core-common'; +import { ToolbarOrientation } from '@itwin/appui-abstract'; +import { ToolbarUsage } from '@itwin/appui-abstract'; import { Transform } from '@itwin/core-geometry'; import { TransformProps } from '@itwin/core-geometry'; import { TransientIdSequence } from '@itwin/core-bentley'; import { Tweens } from '@itwin/core-common'; import { TxnNotifications } from '@itwin/core-common'; import { UiAdmin } from '@itwin/appui-abstract'; +import { UiItemsProvider } from '@itwin/appui-abstract'; import { UnitConversion } from '@itwin/core-quantity'; import { UnitProps } from '@itwin/core-quantity'; import { UnitsProvider } from '@itwin/core-quantity'; @@ -1020,6 +1026,12 @@ export enum ACSType { Spherical = 3 } +// @alpha (undocumented) +export enum ActivationEvent { + // (undocumented) + onStartup = "onStartup" +} + // @public export class ActivityMessageDetails { constructor(showProgressBar: boolean, showPercentInMessage: boolean, supportsCancellation: boolean, showDialogInitially?: boolean); @@ -1139,6 +1151,8 @@ export class ArcGISMapLayerImageryProvider extends MapLayerImageryProvider { // (undocumented) protected _generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void): void; // (undocumented) + getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree): Promise; + // (undocumented) protected getLayerString(prefix?: string): string; // (undocumented) getLogo(): HTMLTableRowElement; @@ -1603,8 +1617,6 @@ export class BingElevationProvider { constructor(); // @internal (undocumented) getGeodeticToSeaLevelOffset(point: Point3d, iModel: IModelConnection): Promise; - // @internal (undocumented) - getGraphic(latLongRange: Range2d, corners: Point3d[], groundBias: number, texture: RenderTexture, system: RenderSystem): Promise; getHeight(carto: Cartographic, geodetic?: boolean): Promise; getHeightAverage(iModel: IModelConnection): Promise; getHeightRange(iModel: IModelConnection): Promise; @@ -1660,6 +1672,8 @@ export class BriefcaseConnection extends IModelConnection { protected constructor(props: IModelConnectionProps, openMode: OpenMode); close(): Promise; get editingScope(): GraphicalEditingScope | undefined; + // @alpha + readonly editorToolSettings: BriefcaseEditorToolSettings; enterEditingScope(): Promise; hasPendingTxns(): Promise; get iModelId(): GuidString; @@ -1680,6 +1694,16 @@ export class BriefcaseConnection extends IModelConnection { readonly txns: BriefcaseTxns; } +// @alpha +export class BriefcaseEditorToolSettings { + get category(): Id64String | undefined; + set category(category: Id64String | undefined); + get model(): Id64String | undefined; + set model(model: Id64String | undefined); + readonly onCategoryChanged: BeEvent<(previousCategory: Id64String | undefined) => void>; + readonly onModelChanged: BeEvent<(previousModel: Id64String | undefined) => void>; +} + // @public export abstract class BriefcaseNotificationHandler extends NotificationHandler { constructor(_key: string); @@ -1751,6 +1775,19 @@ export class BriefcaseTxns extends BriefcaseNotificationHandler implements TxnNo reverseTxns(numOperations: number): Promise; } +// @alpha (undocumented) +export interface BuildExtensionManifest extends ExtensionManifest { + readonly module: string; +} + +// @alpha (undocumented) +export interface BuiltInExtensionLoaderProps { + // (undocumented) + loader: ResolveFunc; + // (undocumented) + manifest: Promise; +} + // @internal (undocumented) export type CachedDecoration = { type: "graphic"; @@ -3061,6 +3098,64 @@ export enum EventHandled { Yes = 1 } +// @alpha +export class ExtensionAdmin { + constructor(); + addBuildExtension(manifestPromise: Promise, mainFunc?: ResolveFunc): Promise; + addExtensionLoader(extensionLoader: ExtensionLoader): void; + addExtensionLoaderFront(extensionLoader: ExtensionLoader): void; + // @internal + onStartup: () => Promise; +} + +// @alpha +export class ExtensionHost { + protected constructor(); + // (undocumented) + static get accuSnap(): AccuSnap; + // (undocumented) + static get locateManager(): ElementLocateManager; + // (undocumented) + static get notifications(): NotificationManager; + // (undocumented) + static get renderSystem(): RenderSystem; + // (undocumented) + static get toolAdmin(): ToolAdmin; + // (undocumented) + static get viewManager(): ViewManager; +} + +// @alpha (undocumented) +export class ExtensionImpl { + constructor(_id: string); + // (undocumented) + registerTool(tool: ToolType, onRegistered?: () => any): Promise; +} + +// @alpha +export interface ExtensionLoader { + downloadExtension(arg: ExtensionLoaderProps): Promise; + getManifest(arg: ExtensionLoaderProps): Promise; +} + +// @alpha +export interface ExtensionLoaderProps { + // (undocumented) + name: string; + // (undocumented) + version: string; +} + +// @alpha +export interface ExtensionManifest { + readonly activationEvents: ActivationEvent[]; + readonly description?: string; + readonly displayName?: string; + readonly main: string; + readonly name: string; + readonly version: string; +} + // @public export interface ExtentLimits { max: number; @@ -4465,7 +4560,7 @@ export function imageBufferToPngDataUrl(buffer: ImageBuffer, preserveAlpha?: boo export function imageElementFromImageSource(source: ImageSource): Promise; // @public -export function imageElementFromUrl(url: string): Promise; +export function imageElementFromUrl(url: string, skipCrossOriginCheck?: boolean): Promise; // @internal export class ImageryMapLayerFormat extends MapLayerFormat { @@ -4636,6 +4731,8 @@ export class IModelApp { static authorizationClient?: AuthorizationClient; // @internal (undocumented) static createRenderSys(opts?: RenderSystem.Options): RenderSystem; + // @alpha (undocumented) + static readonly extensionAdmin: ExtensionAdmin; // @alpha static formatElementToolTip(msg: string[]): HTMLElement; static getAccessToken(): Promise; @@ -4646,7 +4743,7 @@ export class IModelApp { // @internal (undocumented) static get initialized(): boolean; static get localization(): Localization; - // @internal (undocumented) + // (undocumented) static get locateManager(): ElementLocateManager; // @internal (undocumented) static lookupEntityClass(classFullName: string): typeof EntityState | undefined; @@ -4672,6 +4769,8 @@ export class IModelApp { // @internal static get mapLayerFormatRegistry(): MapLayerFormatRegistry; static get notifications(): NotificationManager; + // @internal + static readonly onAfterStartup: BeEvent<() => void>; static readonly onBeforeShutdown: BeEvent<() => void>; // @beta static get publicPath(): string; @@ -4865,7 +4964,7 @@ export namespace IModelConnection { export class Views { // @internal constructor(_iModel: IModelConnection); - // @deprecated (undocumented) + // @deprecated getThumbnail(_viewId: Id64String): Promise; getViewList(queryParams: ViewQueryParams): Promise; load(viewDefinitionId: Id64String): Promise; @@ -5246,6 +5345,9 @@ export interface ITwinIdArg { readonly iTwinId?: GuidString; } +// @public (undocumented) +export const ITWINJS_CORE_VERSION: string; + // @public export enum KeyinParseError { MismatchedQuotes = 4, @@ -5276,6 +5378,14 @@ export class LengthDescription extends FormattedQuantityDescription { // @internal (undocumented) export function linePlaneIntersect(outP: Point3d, linePt: Point3d, lineNormal: Vector3d | undefined, planePt: Point3d, planeNormal: Vector3d, perpendicular: boolean): void; +// @alpha +export interface LocalExtensionProps { + // (undocumented) + readonly mainFunc?: ResolveFunc; + // (undocumented) + readonly manifest: ExtensionManifest; +} + // @internal export class LocalhostIpcApp { // (undocumented) @@ -5552,6 +5662,19 @@ export class MapCartoRectangle extends Range2d { set west(x: number); } +// @alpha (undocumented) +export interface MapFeatureInfo { + // (undocumented) + hitPoint?: Cartographic; + // (undocumented) + layerInfo?: MapLayerFeatureInfo[]; +} + +// @alpha (undocumented) +export class MapFeatureInfoRecord extends PropertyRecord { + constructor(value: PropertyValue, property: PropertyDescription); +} + // @internal (undocumented) export interface MapLayerAuthenticationInfo { // (undocumented) @@ -5573,6 +5696,14 @@ export enum MapLayerAuthType { // @internal (undocumented) export type MapLayerClassifiers = Map; +// @alpha (undocumented) +export interface MapLayerFeatureInfo { + // (undocumented) + info?: MapSubLayerFeatureInfo[] | HTMLElement; + // (undocumented) + layerName: string; +} + // @internal (undocumented) export class MapLayerFormat { // (undocumented) @@ -5643,6 +5774,8 @@ export abstract class MapLayerImageryProvider { // (undocumented) getEPSG4326ExtentString(row: number, column: number, zoomLevel: number, latLongAxisOrdering: boolean): string; // (undocumented) + getFeatureInfo(featureInfos: MapLayerFeatureInfo[], _quadId: QuadId, _carto: Cartographic, _tree: ImageryMapTileTree): Promise; + // (undocumented) protected getImageFromTileResponse(tileResponse: Response, zoomLevel: number): ImageSource | undefined; // (undocumented) getLogo(_viewport: ScreenViewport): HTMLTableRowElement | undefined; @@ -5833,6 +5966,16 @@ export interface MapLayerTokenEndpoint { getUrl(): string; } +// @alpha (undocumented) +export interface MapSubLayerFeatureInfo { + // (undocumented) + displayFieldName?: string; + // (undocumented) + records?: MapFeatureInfoRecord[]; + // (undocumented) + subLayerName: string; +} + // @internal (undocumented) export class MapTile extends RealityTile { constructor(params: RealityTileParams, mapTree: MapTileTree, quadId: QuadId, _patch: TilePatch, rectangle: MapCartoRectangle, heightRange: Range1d | undefined, _cornerRays: Ray3d[] | undefined); @@ -6129,6 +6272,8 @@ export class MapTileTreeReference extends TileTreeReference { // (undocumented) getLayerImageryTreeRef(index: number): MapLayerTileTreeReference | undefined; // (undocumented) + getMapFeatureInfo(hit: HitDetail): Promise; + // (undocumented) protected getSymbologyOverrides(_tree: TileTree): FeatureSymbology.Overrides | undefined; // (undocumented) getToolTip(hit: HitDetail): Promise; @@ -7626,6 +7771,7 @@ export interface PreferenceKeyArg { // @public export abstract class PrimitiveTool extends InteractiveTool { autoLockTarget(): void; + get briefcase(): BriefcaseConnection | undefined; // (undocumented) exitTool(): Promise; getPrompt(): string; @@ -8974,6 +9120,9 @@ export abstract class RenderTextureDrape implements IDisposable { // @internal (undocumented) export type RequestTileTreePropsFunc = (iModel: IModelConnection, treeId: string) => Promise; +// @alpha (undocumented) +export type ResolveFunc = () => Promise; + // @internal export type RootIModelTile = Tile & { tileScreenSize: number; @@ -11237,6 +11386,8 @@ export abstract class TileTreeReference { protected getClipVolume(tree: TileTree): RenderClipVolume | undefined; protected getHiddenLineSettings(_tree: TileTree): HiddenLine.Settings | undefined; getLocation(): Transform | undefined; + // @alpha + getMapFeatureInfo(_hit: HitDetail): Promise; protected getSymbologyOverrides(_tree: TileTree): FeatureSymbology.Overrides | undefined; // @internal (undocumented) getTerrainHeight(_terrainHeights: Range1d): void; @@ -11366,8 +11517,6 @@ export class Tool { export class ToolAdmin { acsContextLock: boolean; acsPlaneSnapLock: boolean; - // @alpha - readonly activeSettings: ToolAdmin.ActiveSettings; get activeTool(): InteractiveTool | undefined; readonly activeToolChanged: BeEvent<(tool: Tool, start: StartOrResume) => void>; // @internal @@ -11432,8 +11581,8 @@ export class ToolAdmin { getDecorationGeometry(hit: HitDetail): GeometryStreamProps | undefined; getToolTip(hit: HitDetail): Promise; gridLock: boolean; - get idleTool(): IdleTool; - set idleTool(idleTool: IdleTool); + get idleTool(): InteractiveTool; + set idleTool(idleTool: InteractiveTool); // (undocumented) get isLocateCircleOn(): boolean; readonly manipulatorToolEvent: BeEvent<(tool: Tool, event: ManipulatorToolEvent) => void>; @@ -11513,15 +11662,6 @@ export class ToolAdmin { get viewTool(): ViewTool | undefined; } -// @public (undocumented) -export namespace ToolAdmin { - // @alpha - export class ActiveSettings { - category?: Id64String; - model?: Id64String; - } -} - // @public export class ToolAssistance { static get altKey(): string; @@ -11610,6 +11750,15 @@ export interface ToolAssistanceSection { // @public (undocumented) export type ToolList = ToolType[]; +// @alpha (undocumented) +export class ToolProvider implements UiItemsProvider { + constructor(tool: ToolType); + // (undocumented) + readonly id: string; + // (undocumented) + provideToolbarButtonItems(_stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation): CommonToolbarItem[]; + } + // @public export class ToolRegistry { create(toolId: string, ...args: any[]): Tool | undefined; @@ -11795,7 +11944,7 @@ export class TraversalSelectionContext { } // @public -export function tryImageElementFromUrl(url: string): Promise; +export function tryImageElementFromUrl(url: string, skipCrossOriginCheck?: boolean): Promise; // @public export class TwoWayViewportFrustumSync extends TwoWayViewportSync { @@ -12960,6 +13109,8 @@ export abstract class Viewport implements IDisposable, TileUser { getAuxCoordRotation(result?: Matrix3d): Matrix3d; getContrastToBackgroundColor(): ColorDef; getFrustum(sys?: CoordSystem, adjustedBox?: boolean, box?: Frustum): Frustum; + // @alpha (undocumented) + getMapFeatureInfo(hit: HitDetail): Promise; // @internal (undocumented) getMapLayerImageryProvider(index: number, isOverlay: boolean): MapLayerImageryProvider | undefined; getPixelDataNpcPoint(pixels: Pixel.Buffer, x: number, y: number, out?: Point3d): Point3d | undefined; diff --git a/common/api/core-geometry.api.md b/common/api/core-geometry.api.md index 15e55941ce80..bb8004e9ba82 100644 --- a/common/api/core-geometry.api.md +++ b/common/api/core-geometry.api.md @@ -21,9 +21,8 @@ export abstract class AbstractNewtonIterator { // @public export class AkimaCurve3d extends ProxyCurve { - clone(): GeometryQuery | undefined; + clone(): AkimaCurve3d; cloneProps(): AkimaCurve3dProps; - cloneTransformed(transform: Transform): GeometryQuery | undefined; copyFitPointsFloat64Array(): Float64Array; static create(options: AkimaCurve3dOptions | AkimaCurve3dProps): AkimaCurve3d | undefined; // (undocumented) @@ -247,8 +246,8 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { clone(): Arc3d; cloneAtZ(z?: number): Arc3d; cloneInRotatedBasis(theta: Angle): Arc3d; - clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined; - cloneTransformed(transform: Transform): CurvePrimitive; + clonePartialCurve(fractionA: number, fractionB: number): Arc3d; + cloneTransformed(transform: Transform): Arc3d; closestPoint(spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail): CurveLocationDetail; computeStrokeCountForOptions(options?: StrokeOptions): number; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; @@ -510,8 +509,6 @@ export abstract class BezierCoffs { // @public export class BezierCurve3d extends BezierCurveBase { clone(): BezierCurve3d; - clonePartialCurve(f0: number, f1: number): BezierCurve3d | undefined; - cloneTransformed(transform: Transform): BezierCurve3d; copyPointsAsLineString(): LineString3d; static create(data: Point3d[] | Point2d[]): BezierCurve3d | undefined; static createOrder(order: number): BezierCurve3d; @@ -531,7 +528,6 @@ export class BezierCurve3d extends BezierCurveBase { // @public export class BezierCurve3dH extends BezierCurveBase { clone(): BezierCurve3dH; - cloneTransformed(transform: Transform): BezierCurve3dH; static create(data: Point3d[] | Point4d[] | Point2d[]): BezierCurve3dH | undefined; static createOrder(order: number): BezierCurve3dH; dispatchToGeometryHandler(handler: GeometryHandler): any; @@ -557,6 +553,9 @@ export class BezierCurve3dH extends BezierCurveBase { export abstract class BezierCurveBase extends CurvePrimitive { protected constructor(blockSize: number, data: Float64Array); protected allocateAndZeroBezierWorkData(primaryBezierOrder: number, orderA: number, orderB: number): void; + abstract clone(): BezierCurveBase; + clonePartialCurve(fractionA: number, fractionB: number): BezierCurveBase; + cloneTransformed(transform: Transform): BezierCurveBase; computeStrokeCountForOptions(options?: StrokeOptions): number; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; copyPolesAsJsonArray(): any[]; @@ -694,6 +693,7 @@ export class BoxTopology { // @public export class BSpline1dNd { protected constructor(numPoles: number, poleLength: number, order: number, knots: KnotVector); + addKnot(knot: number, totalMultiplicity: number): boolean; basisBuffer: Float64Array; basisBuffer1: Float64Array; basisBuffer2: Float64Array; @@ -759,7 +759,6 @@ export abstract class BSpline2dNd extends GeometryQuery { // @public export class BSplineCurve3d extends BSplineCurve3dBase { clone(): BSplineCurve3d; - cloneTransformed(transform: Transform): BSplineCurve3d; // @alpha computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentStrokeMap?: StrokeCountMap): void; computeStrokeCountForOptions(options?: StrokeOptions): number; @@ -778,9 +777,6 @@ export class BSplineCurve3d extends BSplineCurve3dBase { evaluatePointAndDerivativeInSpan(spanIndex: number, spanFraction: number): Ray3d; evaluatePointInSpan(spanIndex: number, spanFraction: number): Point3d; extendRange(rangeToExtend: Range3d, transform?: Transform): void; - fractionToPoint(fraction: number, result?: Point3d): Point3d; - fractionToPointAnd2Derivatives(fraction: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors; - fractionToPointAndDerivative(fraction: number, result?: Ray3d): Ray3d; getPolePoint3d(poleIndex: number, result?: Point3d): Point3d | undefined; getPolePoint4d(poleIndex: number, result?: Point4d): Point4d | undefined; getSaturatedBezierSpan3d(spanIndex: number, result?: BezierCurveBase): BezierCurveBase | undefined; @@ -804,6 +800,9 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { protected constructor(poleDimension: number, numPoles: number, order: number, knots: KnotVector); appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail[]): number; protected _bcurve: BSpline1dNd; + abstract clone(): BSplineCurve3dBase; + clonePartialCurve(fractionA: number, fractionB: number): BSplineCurve3dBase; + cloneTransformed(transform: Transform): BSplineCurve3dBase; closestPoint(spacePoint: Point3d, _extend: boolean): CurveLocationDetail | undefined; collectBezierSpans(prefer3dH: boolean): BezierCurveBase[]; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; @@ -841,7 +840,6 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { weights: Float64Array; } | Point3d[]): Float64Array | undefined; clone(): BSplineCurve3dH; - cloneTransformed(transform: Transform): BSplineCurve3dH; computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentStrokeMap?: StrokeCountMap): void; computeStrokeCountForOptions(options?: StrokeOptions): number; copyPoints(): any[]; @@ -1464,14 +1462,14 @@ export class CurveChainWireOffsetContext { export class CurveChainWithDistanceIndex extends CurvePrimitive { chainDistanceToChainFraction(distance: number): number; protected chainDistanceToFragment(distance: number, allowExtrapolation?: boolean): PathFragment | undefined; - clone(): CurvePrimitive | undefined; - cloneTransformed(transform: Transform): CurvePrimitive | undefined; + clone(): CurveChainWithDistanceIndex; + cloneTransformed(transform: Transform): CurveChainWithDistanceIndex | undefined; closestPoint(spacePoint: Point3d, extend: VariantCurveExtendParameter): CurveLocationDetail | undefined; collectCurvePrimitivesGo(collectorArray: CurvePrimitive[], smallestPossiblePrimitives?: boolean, explodeLineStrings?: boolean): void; computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentStrokeMap?: StrokeCountMap): void; computeStrokeCountForOptions(options?: StrokeOptions): number; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; - static createCapture(path: CurveChain, options?: StrokeOptions): CurveChainWithDistanceIndex | undefined; + static createCapture(path: CurveChain, options?: StrokeOptions): CurveChainWithDistanceIndex; protected curveAndChildFractionToFragment(curve: CurvePrimitive, fraction: number): PathFragment | undefined; curveLength(): number; curveLengthBetweenFractions(fraction0: number, fraction1: number): number; @@ -1500,11 +1498,11 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { export abstract class CurveCollection extends GeometryQuery { abstract announceToCurveProcessor(processor: RecursiveCurveProcessor): void; checkForNonLinearPrimitives(): boolean; - clone(): CurveCollection | undefined; + clone(): CurveCollection; abstract cloneEmptyPeer(): CurveCollection; abstract cloneStroked(options?: StrokeOptions): AnyCurve; cloneTransformed(transform: Transform): CurveCollection | undefined; - cloneWithExpandedLineStrings(): CurveCollection | undefined; + cloneWithExpandedLineStrings(): CurveCollection; closestPoint(spacePoint: Point3d): CurveLocationDetail | undefined; collectCurvePrimitives(collectorArray?: CurvePrimitive[], smallestPossiblePrimitives?: boolean, explodeLineStrings?: boolean): CurvePrimitive[]; static createCurveLocationDetailOnAnyCurvePrimitive(source: GeometryQuery | undefined, fraction?: number): CurveLocationDetail | undefined; @@ -1681,7 +1679,9 @@ export abstract class CurvePrimitive extends GeometryQuery { addMappedStrokesToLineString3D(map: StrokeCountMap, linestring: LineString3d): number; announceClipIntervals(_clipper: Clipper, _announce?: AnnounceNumberNumberCurvePrimitive): boolean; appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail[]): number; + abstract clone(): CurvePrimitive; clonePartialCurve(_fractionA: number, _fractionB: number): CurvePrimitive | undefined; + abstract cloneTransformed(transform: Transform): CurvePrimitive | undefined; closestPoint(spacePoint: Point3d, extend: VariantCurveExtendParameter): CurveLocationDetail | undefined; collectCurvePrimitives(collectorArray?: CurvePrimitive[], smallestPossiblePrimitives?: boolean, explodeLinestrings?: boolean): CurvePrimitive[]; collectCurvePrimitivesGo(collectorArray: CurvePrimitive[], _smallestPossiblePrimitives: boolean, _explodeLinestrings?: boolean): void; @@ -1833,8 +1833,6 @@ export class DirectSpiral3d extends TransitionSpiral3d { constructor(localToWorld: Transform, spiralType: string | undefined, originalProperties: TransitionConditionalProperties | undefined, nominalL1: number, nominalR1: number, activeFractionInterval: Segment1d | undefined, evaluator: XYCurveEvaluator); get activeStrokes(): LineString3d; clone(): DirectSpiral3d; - clonePartialCurve(fractionA: number, fractionB: number): DirectSpiral3d | undefined; - cloneTransformed(transform: Transform): DirectSpiral3d; computeStrokeCountForOptions(options?: StrokeOptions): number; static createArema(localToWorld: Transform, nominalL1: number, nominalR1: number, activeInterval?: Segment1d): DirectSpiral3d | undefined; static createAustralianRail(localToWorld: Transform, nominalL1: number, nominalR1: number, activeInterval?: Segment1d): DirectSpiral3d | undefined; @@ -2545,6 +2543,8 @@ export namespace IModelJson { topY?: number; } export interface BSplineSurfaceProps { + closedU?: boolean; + closedV?: boolean; orderU: number; orderV: number; points: [[[number]]]; @@ -2910,8 +2910,6 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { get activeStrokes(): LineString3d; bearing01: AngleSweep; clone(): IntegratedSpiral3d; - clonePartialCurve(fractionA: number, fractionB: number): IntegratedSpiral3d | undefined; - cloneTransformed(transform: Transform): TransitionSpiral3d; computeStrokeCountForOptions(options?: StrokeOptions): number; static createFrom4OutOf5(spiralType: string | undefined, radius0: number | undefined, radius1: number | undefined, bearing0: Angle | undefined, bearing1: Angle | undefined, arcLength: number | undefined, fractionInterval: undefined | Segment1d, localToWorld: Transform): IntegratedSpiral3d | undefined; static createRadiusRadiusBearingBearing(radius01: Segment1d, bearing01: AngleSweep, activeFractionInterval: Segment1d, localToWorld: Transform, typeName?: string): IntegratedSpiral3d | undefined; @@ -2953,9 +2951,8 @@ export function interpolateColor(color0: number, fraction: number, color1: numbe // @public export class InterpolationCurve3d extends ProxyCurve { - clone(): GeometryQuery | undefined; + clone(): InterpolationCurve3d; cloneProps(): InterpolationCurve3dProps; - cloneTransformed(transform: Transform): GeometryQuery | undefined; copyFitPointsFloat64Array(): Float64Array; static create(options: InterpolationCurve3dOptions | InterpolationCurve3dProps): InterpolationCurve3d | undefined; static createCapture(options: InterpolationCurve3dOptions): InterpolationCurve3d | undefined; @@ -3066,7 +3063,9 @@ export class KnotVector { evaluateBasisFunctions(knotIndex0: number, u: number, f: Float64Array): void; evaluateBasisFunctions1(knotIndex0: number, u: number, f: Float64Array, df: Float64Array, ddf?: Float64Array): void; fractionToKnot(fraction: number): number; - grevilleKnot(spanIndex: number): number; + getKnotMultiplicity(knot: number): number; + getKnotMultiplicityAtIndex(knotIndex: number): number; + grevilleKnot(knotIndex: number): number; isAlmostEqual(other: KnotVector): boolean; isIndexOfRealSpan(spanIndex: number): boolean; get knotLength01(): number; @@ -3075,11 +3074,13 @@ export class KnotVector { static readonly knotTolerance = 1e-9; get leftKnot(): number; get leftKnotIndex(): number; + normalize(): boolean; get numSpans(): number; reflectKnots(): void; get rightKnot(): number; get rightKnotIndex(): number; setKnots(knots: number[] | Float64Array, skipFirstAndLast?: boolean): void; + setKnotsCapture(knots: Float64Array): void; spanFractionToFraction(spanIndex: number, localFraction: number): number; spanFractionToKnot(spanIndex: number, localFraction: number): number; spanIndexToLeftKnotIndex(spanIndex: number): number; @@ -3115,8 +3116,8 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { announceClipIntervals(clipper: Clipper, announce?: AnnounceNumberNumberCurvePrimitive): boolean; appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail[]): number; clone(): LineSegment3d; - clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined; - cloneTransformed(transform: Transform): CurvePrimitive; + clonePartialCurve(fractionA: number, fractionB: number): LineSegment3d; + cloneTransformed(transform: Transform): LineSegment3d; closestPoint(spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail): CurveLocationDetail; computeStrokeCountForOptions(options?: StrokeOptions): number; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; @@ -3175,8 +3176,8 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { appendStrokePoint(point: Point3d, fraction?: number): void; clear(): void; clone(): LineString3d; - clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined; - cloneTransformed(transform: Transform): CurvePrimitive; + clonePartialCurve(fractionA: number, fractionB: number): LineString3d; + cloneTransformed(transform: Transform): LineString3d; closestPoint(spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail): CurveLocationDetail; collectCurvePrimitivesGo(collectorArray: CurvePrimitive[], _smallestPossiblePrimitives: boolean, explodeLinestrings?: boolean): void; computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentStrokeMap?: StrokeCountMap): void; @@ -4547,6 +4548,9 @@ export class PowerPolynomial { // @public export abstract class ProxyCurve extends CurvePrimitive { constructor(proxyCurve: CurvePrimitive); + abstract clone(): ProxyCurve; + clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined; + cloneTransformed(transform: Transform): ProxyCurve | undefined; computeStrokeCountForOptions(options?: StrokeOptions): number; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; // (undocumented) @@ -5616,6 +5620,9 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { } | undefined; static averageCurvature(radiusLimits: Segment1d): number; static averageCurvatureR0R1(r0: number, r1: number): number; + abstract clone(): TransitionSpiral3d; + clonePartialCurve(fractionA: number, fractionB: number): TransitionSpiral3d; + cloneTransformed(transform: Transform): TransitionSpiral3d; constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined; static curvatureToRadius(curvature: number): number; get designProperties(): TransitionConditionalProperties | undefined; @@ -5628,6 +5635,7 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { static radiusRadiusLengthToSweepRadians(radius0: number, radius1: number, arcLength: number): number; static radiusRadiusSweepRadiansToArcLength(radius0: number, radius1: number, sweepRadians: number): number; static radiusToCurvature(radius: number): number; + abstract refreshComputedProperties(): void; // (undocumented) get spiralType(): string; protected _spiralType: string; diff --git a/common/api/core-react.api.md b/common/api/core-react.api.md index ded54bac3f1f..00d72b8eaadb 100644 --- a/common/api/core-react.api.md +++ b/common/api/core-react.api.md @@ -2017,13 +2017,13 @@ export interface SvgPathProps extends CommonProps { viewBoxWidth: number; } -// @public +// @public @deprecated export class SvgSprite extends React.PureComponent { // (undocumented) render(): JSX.Element; } -// @public +// @public @deprecated export interface SvgSpriteProps extends CommonProps { src: string; } @@ -2474,7 +2474,7 @@ export function useRefs(...refs: ReadonlyArray>): (instance: T | export function useRefState(): [React.Ref, T | undefined]; // @internal -export function useResizeObserver(onResize?: (width: number, height: number) => void): (instance: Element | null) => void; +export function useResizeObserver(onResize?: (width: number, height: number) => void): (instance: T | null) => void; // @public export function useSaveBeforeActivatingNewSettingsTab(settingsManager: SettingsManager, saveFunction: (tabSelectionFunc: (args: any) => void, requestedSettingsTabId?: string) => void): void; diff --git a/common/api/editor-frontend.api.md b/common/api/editor-frontend.api.md index 9e6310bbc61c..a539ff97f5cc 100644 --- a/common/api/editor-frontend.api.md +++ b/common/api/editor-frontend.api.md @@ -18,6 +18,7 @@ import { ChamferMode } from '@itwin/editor-common'; import { ClipShape } from '@itwin/core-geometry'; import { ClipVector } from '@itwin/core-geometry'; import { CoordinateLockOverrides } from '@itwin/core-frontend'; +import { CurveCollection } from '@itwin/core-geometry'; import { CurvePrimitive } from '@itwin/core-geometry'; import { DecorateContext } from '@itwin/core-frontend'; import { DialogItem } from '@itwin/appui-abstract'; @@ -150,6 +151,36 @@ export abstract class BooleanOperationTool extends ElementGeometryCacheTool { protected get requiredElementCount(): number; } +// @alpha +export class BreakCurveTool extends ModifyCurveTool { + // (undocumented) + protected acceptCurve(curve: CurveCollection | CurvePrimitive): boolean; + // (undocumented) + protected doBreakCurve(ev: BeButtonEvent): void; + // (undocumented) + static iconSpec: string; + // (undocumented) + protected modifyCurve(_ev: BeButtonEvent, _isAccept: boolean): CurveCollection | CurvePrimitive | undefined; + // (undocumented) + protected modifyOriginal: boolean; + // (undocumented) + onRestartTool(): Promise; + // (undocumented) + processAgenda(ev: BeButtonEvent): Promise; + // (undocumented) + protected provideToolAssistance(_mainInstrText?: string, _additionalInstr?: ToolAssistanceInstruction[]): void; + // (undocumented) + protected resultA?: CurveCollection | CurvePrimitive; + // (undocumented) + protected resultB?: CurveCollection | CurvePrimitive; + // (undocumented) + static toolId: string; + // (undocumented) + protected get wantAccuSnap(): boolean; + // (undocumented) + protected get wantModifyOriginal(): boolean; +} + // @alpha export class ChamferEdgesTool extends BlendEdgesTool { // (undocumented) @@ -656,6 +687,17 @@ export class CreateRectangleTool extends CreateOrContinuePathTool { get useRadiusProperty(): DialogProperty; } +// @alpha (undocumented) +export class CurveData { + constructor(props: GeometricElementProps, params: GeometryParams, geom: CurveCollection | CurvePrimitive); + // (undocumented) + geom: CurveCollection | CurvePrimitive; + // (undocumented) + params: GeometryParams; + // (undocumented) + props: GeometricElementProps; +} + // @alpha export class CutSolidElementsTool extends ElementGeometryCacheTool { // (undocumented) @@ -915,6 +957,30 @@ export class EmbossSolidElementsTool extends ElementGeometryCacheTool { static toolId: string; } +// @alpha +export class ExtendCurveTool extends ModifyCurveTool { + // (undocumented) + protected acceptCurve(curve: CurveCollection | CurvePrimitive): boolean; + // (undocumented) + static iconSpec: string; + // (undocumented) + protected modifyCurve(ev: BeButtonEvent, _isAccept: boolean): CurveCollection | CurvePrimitive | undefined; + // (undocumented) + onRestartTool(): Promise; + // (undocumented) + protected provideToolAssistance(_mainInstrText?: string, _additionalInstr?: ToolAssistanceInstruction[]): void; + // (undocumented) + protected setupAccuDraw(): void; + // (undocumented) + static toolId: string; + // (undocumented) + protected get wantAccuSnap(): boolean; + // (undocumented) + protected get wantAgendaAppearanceOverride(): boolean; + // (undocumented) + protected get wantDynamics(): boolean; +} + // @alpha (undocumented) export class FaceLocationData { constructor(point: Point3d, normal: Vector3d); @@ -1190,6 +1256,93 @@ export class LoftProfilesTool extends ElementGeometryCacheTool { static toolId: string; } +// @alpha +export abstract class ModifyCurveTool extends ElementSetTool implements FeatureOverrideProvider { + // (undocumented) + protected acceptCurve(_curve: CurveCollection | CurvePrimitive): boolean; + // (undocumented) + protected acceptElementForOperation(id: Id64String): Promise; + // (undocumented) + addFeatureOverrides(overrides: FeatureSymbology.Overrides, _vp: Viewport): void; + // (undocumented) + protected agendaAppearance(isDynamics: boolean): FeatureAppearance; + // (undocumented) + protected _agendaAppearanceDefault?: FeatureAppearance; + // (undocumented) + protected _agendaAppearanceDynamic?: FeatureAppearance; + // (undocumented) + protected allowView(_vp: Viewport): boolean; + // (undocumented) + protected applyAgendaOperation(ev: BeButtonEvent): Promise; + // (undocumented) + static callCommand(method: T, ...args: Parameters): ReturnType; + // (undocumented) + protected readonly _checkedIds: Map; + // (undocumented) + protected clearGraphics(): void; + // (undocumented) + protected createGraphics(ev: BeButtonEvent): Promise; + // (undocumented) + protected curveData?: CurveData; + // (undocumented) + protected _firstResult: boolean; + // (undocumented) + protected getCurveData(id: Id64String): Promise; + // (undocumented) + protected getElementProps(ev: BeButtonEvent): GeometricElementProps | undefined; + // (undocumented) + protected getGeometryProps(ev: BeButtonEvent, isAccept: boolean): JsonGeometryStream | FlatBufferGeometryStream | undefined; + // (undocumented) + protected _graphicsProvider?: DynamicGraphicsProvider; + // (undocumented) + isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean; + // (undocumented) + protected isElementValidForOperation(hit: HitDetail, out?: LocateResponse): Promise; + // (undocumented) + static isSingleCurve(info: ElementGeometryInfo): { + curve: CurveCollection | CurvePrimitive; + params: GeometryParams; + } | undefined; + // (undocumented) + protected modifyCurve(_ev: BeButtonEvent, _isAccept: boolean): CurveCollection | CurvePrimitive | undefined; + // (undocumented) + protected onAgendaModified(): Promise; + // (undocumented) + onCleanup(): Promise; + // (undocumented) + onDynamicFrame(_ev: BeButtonEvent, context: DynamicsContext): void; + // (undocumented) + protected onGeometryFilterChanged(): void; + // (undocumented) + onMouseMotion(ev: BeButtonEvent): Promise; + // (undocumented) + onPostInstall(): Promise; + // (undocumented) + onProcessComplete(): Promise; + // (undocumented) + onSuspend(): Promise; + // (undocumented) + onUnsuspend(): Promise; + // (undocumented) + processAgenda(ev: BeButtonEvent): Promise; + // (undocumented) + protected setupAccuDraw(): void; + // (undocumented) + protected setupAndPromptForNextAction(): void; + // (undocumented) + protected startCommand(): Promise; + // (undocumented) + protected _startedCmd?: string; + // (undocumented) + protected updateAgendaAppearanceProvider(drop?: true): void; + // (undocumented) + protected get wantAgendaAppearanceOverride(): boolean; + // (undocumented) + protected get wantContinueWithPreviousResult(): boolean; + // (undocumented) + protected get wantModifyOriginal(): boolean; +} + // @alpha export class MoveElementsTool extends TransformElementsTool { // (undocumented) @@ -1204,6 +1357,53 @@ export class MoveElementsTool extends TransformElementsTool { static toolId: string; } +// @alpha +export class OffsetCurveTool extends ModifyCurveTool { + // (undocumented) + protected acceptCurve(curve: CurveCollection | CurvePrimitive): boolean; + // (undocumented) + applyToolSettingPropertyChange(updatedValue: DialogPropertySyncItem): Promise; + // (undocumented) + get distance(): number; + set distance(value: number); + // (undocumented) + get distanceProperty(): DialogProperty; + // (undocumented) + protected getToolSettingPropertyLocked(property: DialogProperty): DialogProperty | undefined; + // (undocumented) + static iconSpec: string; + // (undocumented) + get makeCopy(): boolean; + set makeCopy(value: boolean); + // (undocumented) + get makeCopyProperty(): DialogProperty; + // (undocumented) + protected modifyCurve(ev: BeButtonEvent, isAccept: boolean): CurveCollection | CurvePrimitive | undefined; + // (undocumented) + onRestartTool(): Promise; + // (undocumented) + protected provideToolAssistance(_mainInstrText?: string, _additionalInstr?: ToolAssistanceInstruction[]): void; + // (undocumented) + protected setupAccuDraw(): void; + // (undocumented) + supplyToolSettingsProperties(): DialogItem[] | undefined; + // (undocumented) + static toolId: string; + // (undocumented) + get useDistance(): boolean; + set useDistance(value: boolean); + // (undocumented) + get useDistanceProperty(): DialogProperty; + // (undocumented) + protected get wantAccuSnap(): boolean; + // (undocumented) + protected get wantContinueWithPreviousResult(): boolean; + // (undocumented) + protected get wantDynamics(): boolean; + // (undocumented) + protected get wantModifyOriginal(): boolean; +} + // @alpha export class OffsetFacesTool extends LocateSubEntityTool { // (undocumented) diff --git a/common/api/presentation-backend.api.md b/common/api/presentation-backend.api.md index 4dbb13da6e82..9a4971fbc2e1 100644 --- a/common/api/presentation-backend.api.md +++ b/common/api/presentation-backend.api.md @@ -67,6 +67,9 @@ export function getElementKey(imodel: IModelDb, id: Id64String): InstanceKey | u // @internal (undocumented) export function getKeysForContentRequest(keys: Readonly, classInstanceKeysProcessor?: (keys: Map>) => void): NativePresentationKeySetJSON; +// @internal (undocumented) +export const getLocalesDirectory: (assetsDirectory: string) => string; + // @beta export type HierarchyCacheConfig = MemoryHierarchyCacheConfig | DiskHierarchyCacheConfig | HybridCacheConfig; diff --git a/common/api/presentation-common.api.md b/common/api/presentation-common.api.md index ab5a68584da3..17ddbc6f25c6 100644 --- a/common/api/presentation-common.api.md +++ b/common/api/presentation-common.api.md @@ -141,7 +141,7 @@ export interface CategoryDescriptionJSON { // @public export type CategoryIdentifier = ParentCategoryIdentifier | RootCategoryIdentifier | IdCategoryIdentifier; -// @public +// @public @deprecated export interface CheckBoxRule extends RuleBase, ConditionContainer { condition?: string; defaultValue?: boolean; @@ -270,6 +270,7 @@ export enum ContentFlags { KeysOnly = 1, MergeResults = 8, NoFields = 32, + // @deprecated ShowImages = 2, ShowLabels = 4 } @@ -363,6 +364,7 @@ export interface ContentSpecificationBase extends ContentModifiersList { onlyIfNotHandled?: boolean; priority?: number; relatedInstances?: RelatedInstanceSpecification[]; + // @deprecated showImages?: boolean; specType: ContentSpecificationTypes; } @@ -384,8 +386,11 @@ export type ContentUpdateInfo = typeof UPDATE_FULL; export function createFieldHierarchies(fields: Field[], ignoreCategories?: Boolean): FieldHierarchy[]; // @public -export type CustomizationRule = InstanceLabelOverride | CheckBoxRule | GroupingRule | ImageIdOverride | LabelOverride | // eslint-disable-line deprecation/deprecation -SortingRule | StyleOverride | ExtendedDataRule | NodeArtifactsRule; +export type CustomizationRule = InstanceLabelOverride | CheckBoxRule | // eslint-disable-line deprecation/deprecation +GroupingRule | ImageIdOverride | // eslint-disable-line deprecation/deprecation +LabelOverride | // eslint-disable-line deprecation/deprecation +SortingRule | StyleOverride | // eslint-disable-line deprecation/deprecation +ExtendedDataRule | NodeArtifactsRule; // @public export interface CustomNodeSpecification extends ChildNodeSpecificationBase { @@ -927,9 +932,6 @@ export const getFieldByName: (fields: Field[], name: string | undefined, recurse // @public export const getInstancesCount: (keys: Readonly) => number; -// @internal (undocumented) -export const getLocalesDirectory: (assetsDirectory: string) => string; - // @public export interface GroupingNodeKey extends BaseNodeKey { groupedInstancesCount: number; @@ -1129,7 +1131,7 @@ export interface IdCategoryIdentifier { type: "Id"; } -// @public +// @public @deprecated export interface ImageIdOverride extends RuleBase, ConditionContainer { condition?: string; imageIdExpression: string; @@ -1313,6 +1315,7 @@ export class Item { [key: string]: any; }; static fromJSON(json: ItemJSON | string | undefined): Item | undefined; + // @deprecated imageId: string; // @beta inputKeys?: InstanceKey[]; @@ -1336,7 +1339,7 @@ export interface ItemJSON { extendedData?: { [key: string]: any; }; - // (undocumented) + // @deprecated (undocumented) imageId: string; // @beta (undocumented) inputKeys?: InstanceKeyJSON[]; @@ -1472,7 +1475,7 @@ export interface LabelGroupingNodeKeyJSON extends GroupingNodeKeyJSON { type: StandardNodeTypes.DisplayLabelGroupingNode; } -// @public +// @public @deprecated export interface LabelOverride extends RuleBase, ConditionContainer { condition?: string; description?: string; @@ -1592,17 +1595,24 @@ export interface NoCategoryIdentifier { // @public export interface Node { + // @deprecated backColor?: string; description?: string; extendedData?: { [key: string]: any; }; + // @deprecated fontStyle?: string; + // @deprecated foreColor?: string; hasChildren?: boolean; + // @deprecated imageId?: string; + // @deprecated isCheckboxEnabled?: boolean; + // @deprecated isCheckboxVisible?: boolean; + // @deprecated isChecked?: boolean; isEditable?: boolean; isExpanded?: boolean; @@ -1675,7 +1685,7 @@ export interface NodeInsertionInfoJSON { // @public export interface NodeJSON { - // (undocumented) + // @deprecated (undocumented) backColor?: string; // (undocumented) description?: string; @@ -1683,19 +1693,19 @@ export interface NodeJSON { extendedData?: { [key: string]: any; }; - // (undocumented) + // @deprecated (undocumented) fontStyle?: string; - // (undocumented) + // @deprecated (undocumented) foreColor?: string; // (undocumented) hasChildren?: boolean; - // (undocumented) + // @deprecated (undocumented) imageId?: string; - // (undocumented) + // @deprecated (undocumented) isCheckboxEnabled?: boolean; - // (undocumented) + // @deprecated (undocumented) isCheckboxVisible?: boolean; - // (undocumented) + // @deprecated (undocumented) isChecked?: boolean; // (undocumented) isEditable?: boolean; @@ -2808,7 +2818,7 @@ export interface StructTypeDescription extends BaseTypeDescription { valueFormat: PropertyValueFormat.Struct; } -// @public +// @public @deprecated export interface StyleOverride extends RuleBase, ConditionContainer { backColor?: string; condition?: string; diff --git a/common/api/presentation-components.api.md b/common/api/presentation-components.api.md index 5179a57bb455..cfd0b4c2a1de 100644 --- a/common/api/presentation-components.api.md +++ b/common/api/presentation-components.api.md @@ -500,6 +500,8 @@ export interface PresentationTreeDataProviderDataSourceEntryPoints { export interface PresentationTreeDataProviderProps extends DiagnosticsProps { appendChildrenCountForGroupingNodes?: boolean; // @beta + customizeTreeNodeItem?: (item: Partial, node: Partial) => void; + // @beta dataSourceOverrides?: Partial; imodel: IModelConnection; pagingSize?: number; diff --git a/common/api/presentation-testing.api.md b/common/api/presentation-testing.api.md index e1d6511f172b..001f7e1e7358 100644 --- a/common/api/presentation-testing.api.md +++ b/common/api/presentation-testing.api.md @@ -31,6 +31,7 @@ export class ContentBuilder { // @public export interface ContentBuilderProps { dataProvider?: IContentBuilderDataProvider; + decimalPrecision?: number; imodel: IModelConnection; } diff --git a/common/api/summary/components-react.exports.csv b/common/api/summary/components-react.exports.csv index 73f315d906d1..ec3f80970582 100644 --- a/common/api/summary/components-react.exports.csv +++ b/common/api/summary/components-react.exports.csv @@ -322,11 +322,17 @@ public;SharedTableNonPrimitiveValueRendererProps internal;ShortDateTimePropertyEditor public;ShortDateTypeConverter public;ShowHideDialog +deprecated;ShowHideDialog public;ShowHideDialogProps +deprecated;ShowHideDialogProps public;ShowHideID = string | number | symbol +deprecated;ShowHideID = string | number | symbol public;ShowHideItem +deprecated;ShowHideItem public;ShowHideMenu +deprecated;ShowHideMenu public;ShowHideMenuProps +deprecated;ShowHideMenuProps public;SimplePropertyDataProvider public;SimpleTableDataProvider public;SimpleTreeDataProvider diff --git a/common/api/summary/core-bentley.exports.csv b/common/api/summary/core-bentley.exports.csv index 92c8e2ac8832..4bb63a364398 100644 --- a/common/api/summary/core-bentley.exports.csv +++ b/common/api/summary/core-bentley.exports.csv @@ -104,6 +104,7 @@ public;ProcessDetector public;PromiseReturnType public;ReadonlyOrderedSet public;ReadonlySortedArray +alpha;RealityDataStatus beta;RepositoryStatus beta;RpcInterfaceStatus public;shallowClone @@ -114,4 +115,6 @@ public;TransientIdSequence public;UnexpectedErrors public;using public;utf8ToString(utf8: Uint8Array): string | undefined -internal;utf8ToStringPolyfill(utf8: Uint8Array): string | undefined \ No newline at end of file +internal;utf8ToStringPolyfill(utf8: Uint8Array): string | undefined +internal;YieldManager +internal;YieldManagerOptions \ No newline at end of file diff --git a/common/api/summary/core-common.exports.csv b/common/api/summary/core-common.exports.csv index 0cca09f09bce..e8f55ad0ea17 100644 --- a/common/api/summary/core-common.exports.csv +++ b/common/api/summary/core-common.exports.csv @@ -112,7 +112,7 @@ public;CodeProps public;CodeScopeProps = Id64String | GuidString public;CodeScopeSpec public;CodeSpec -public;ColorByName +public;ColorByName: public;ColorDef public;ColorDefProps = number internal;ColorIndex diff --git a/common/api/summary/core-frontend.exports.csv b/common/api/summary/core-frontend.exports.csv index 580f872f42b9..69bdc82417b5 100644 --- a/common/api/summary/core-frontend.exports.csv +++ b/common/api/summary/core-frontend.exports.csv @@ -24,6 +24,7 @@ public;AccuSnap public;AccuSnap public;ACSDisplayOptions public;ACSType +alpha;ActivationEvent public;ActivityMessageDetails public;ActivityMessageEndReason internal;addRangeGraphic(builder: GraphicBuilder, range: Range3d, is2d: boolean): void @@ -71,8 +72,11 @@ internal;BingMapsImageryLayerProvider public;BlankConnection public;BlankConnectionProps public;BriefcaseConnection +alpha;BriefcaseEditorToolSettings public;class BriefcaseNotificationHandler public;BriefcaseTxns +alpha;BuildExtensionManifest +alpha;BuiltInExtensionLoaderProps internal;CachedDecoration = internal;CachedIModelCoordinatesResponseProps public;calculateEcefToDbTransformAtLocation(originIn: Point3d, iModel: IModelConnection): Promise @@ -156,6 +160,12 @@ public;EntityState internal;EnvironmentDecorations public;EventController public;EventHandled +alpha;ExtensionAdmin +alpha;ExtensionHost +alpha;ExtensionImpl +alpha;ExtensionLoader +alpha;ExtensionLoaderProps +alpha;ExtensionManifest public;ExtentLimits internal;ExternalTileStatistics public;extractImageSourceDimensions(source: ImageSource): Promise @@ -272,7 +282,7 @@ public;imageBufferToBase64EncodedPng(buffer: ImageBuffer, preserveAlpha?: boolea public;imageBufferToCanvas(buffer: ImageBuffer, preserveAlpha?: boolean): HTMLCanvasElement | undefined public;imageBufferToPngDataUrl(buffer: ImageBuffer, preserveAlpha?: boolean): string | undefined public;imageElementFromImageSource(source: ImageSource): Promise -public;imageElementFromUrl(url: string): Promise +public;imageElementFromUrl(url: string, skipCrossOriginCheck?: boolean): Promise internal;ImageryMapLayerFormat internal;ImageryMapLayerTreeReference internal;ImageryMapTile @@ -312,10 +322,12 @@ public;isTextInputFormatPropEditorSpec: (item: CustomFormatPropEditorSpec) => it public;isTextSelectFormatPropEditorSpec: (item: CustomFormatPropEditorSpec) => item is TextSelectFormatPropEditorSpec alpha;ItemField beta;ITwinIdArg +public;ITWINJS_CORE_VERSION: string public;KeyinParseError internal;KeyinStatus beta;LengthDescription internal;linePlaneIntersect(outP: Point3d, linePt: Point3d, lineNormal: Vector3d | undefined, planePt: Point3d, planeNormal: Vector3d, perpendicular: boolean): void +alpha;LocalExtensionProps internal;LocalhostIpcApp internal;LocalHostIpcAppOpts beta;LocalUnitFormatProvider @@ -335,9 +347,12 @@ internal;LRUTileListNode public;ManipulatorToolEvent internal;MapBoxLayerImageryProvider internal;MapCartoRectangle +alpha;MapFeatureInfo +alpha;MapFeatureInfoRecord internal;MapLayerAuthenticationInfo beta;MapLayerAuthType internal;MapLayerClassifiers = Map +alpha;MapLayerFeatureInfo internal;MapLayerFormat internal;MapLayerFormatRegistry internal;MapLayerFormatType = typeof MapLayerFormat @@ -350,6 +365,7 @@ internal;MapLayerSourceStatus internal;MapLayerSourceValidation internal;class MapLayerTileTreeReference internal;MapLayerTokenEndpoint +alpha;MapSubLayerFeatureInfo internal;MapTile internal;MapTiledGraphicsProvider internal;MapTileLoader @@ -461,6 +477,7 @@ public;ReadGltfGraphicsArgs public;ReadImageBufferArgs internal;ReadonlyTileUserSet internal;readPointCloudTileContent(stream: ByteStream, iModel: IModelConnection, modelId: Id64String, _is3d: boolean, range: ElementAlignedBox3d, system: RenderSystem): Promise +alpha;RealityDataError beta;RealityDataSource beta;RealityDataSource internal;createCesiumIonAssetKey(osmAssetId: number, requestKey: string): RealityDataSourceKey @@ -506,6 +523,7 @@ internal;RenderTargetDebugControl internal;class RenderTerrainGeometry internal;class RenderTextureDrape internal;RequestTileTreePropsFunc = (iModel: IModelConnection, treeId: string) => Promise +alpha;ResolveFunc = () => Promise internal;RootIModelTile = Tile & public;RotateViewTool alpha;RotationMode @@ -625,8 +643,6 @@ public;TileVisibility beta;TokenArg public;Tool public;ToolAdmin -public;ToolAdmin -alpha;ActiveSettings public;ToolAssistance public;ToolAssistanceImage public;ToolAssistanceInputMethod @@ -635,6 +651,7 @@ public;ToolAssistanceInstructions public;ToolAssistanceKeyboardInfo public;ToolAssistanceSection public;ToolList = ToolType[] +alpha;ToolProvider public;ToolRegistry public;ToolSettings internal;ToolSettingsState @@ -646,7 +663,7 @@ internal;TouchCursor internal;TraversalChildrenDetails internal;TraversalDetails internal;TraversalSelectionContext -public;tryImageElementFromUrl(url: string): Promise +public;tryImageElementFromUrl(url: string, skipCrossOriginCheck?: boolean): Promise public;TwoWayViewportFrustumSync public;TwoWayViewportSync public;Uniform diff --git a/common/api/summary/core-react.exports.csv b/common/api/summary/core-react.exports.csv index 73c366d5a8e8..f77512ce4d0b 100644 --- a/common/api/summary/core-react.exports.csv +++ b/common/api/summary/core-react.exports.csv @@ -306,7 +306,9 @@ deprecated;Subheading2(props: TextProps): JSX.Element public;SvgPath public;SvgPathProps public;SvgSprite +deprecated;SvgSprite public;SvgSpriteProps +deprecated;SvgSpriteProps public;TabLabel public;Tabs public;TabsProps diff --git a/common/api/summary/editor-frontend.exports.csv b/common/api/summary/editor-frontend.exports.csv index 54c64014d9a0..6fa318a947e4 100644 --- a/common/api/summary/editor-frontend.exports.csv +++ b/common/api/summary/editor-frontend.exports.csv @@ -4,6 +4,7 @@ alpha;ArcMethod alpha;BCurveMethod alpha;class BlendEdgesTool alpha;class BooleanOperationTool +alpha;BreakCurveTool alpha;ChamferEdgesTool alpha;CircleMethod alpha;computeChordToleranceFromPoint(vp: Viewport, pt: Point3d, radius?: number): number @@ -17,6 +18,7 @@ alpha;CreateEllipseTool alpha;CreateLineStringTool alpha;class CreateOrContinuePathTool alpha;CreateRectangleTool +alpha;CurveData alpha;CutSolidElementsTool alpha;DeleteElementsTool alpha;DeleteSubEntitiesTool @@ -26,6 +28,7 @@ alpha;EditTools alpha;class ElementGeometryCacheTool alpha;ElementGeometryGraphicsProvider alpha;EmbossSolidElementsTool +alpha;ExtendCurveTool alpha;FaceLocationData alpha;HollowFacesTool alpha;ImprintSolidElementsTool @@ -35,7 +38,9 @@ alpha;isSameSubEntity(a: SubEntityProps, b: SubEntityProps): boolean alpha;class LocateFaceOrProfileTool alpha;class LocateSubEntityTool alpha;LoftProfilesTool +alpha;class ModifyCurveTool alpha;MoveElementsTool +alpha;OffsetCurveTool alpha;OffsetFacesTool alpha;ProfileLocationData beta;ProjectExtentsClipDecoration diff --git a/common/api/summary/presentation-backend.exports.csv b/common/api/summary/presentation-backend.exports.csv index c1c64cbbafcd..dd6ecc091adf 100644 --- a/common/api/summary/presentation-backend.exports.csv +++ b/common/api/summary/presentation-backend.exports.csv @@ -4,6 +4,7 @@ public;ContentCacheConfig beta;DiskHierarchyCacheConfig internal;getElementKey(imodel: IModelDb, id: Id64String): InstanceKey | undefined internal;getKeysForContentRequest(keys: Readonly +internal;getLocalesDirectory: (assetsDirectory: string) => string beta;HierarchyCacheConfig = MemoryHierarchyCacheConfig | DiskHierarchyCacheConfig | HybridCacheConfig beta;HierarchyCacheConfigBase beta;HierarchyCacheMode diff --git a/common/api/summary/presentation-common.exports.csv b/common/api/summary/presentation-common.exports.csv index 4a2c1835d165..9ff2d416c4de 100644 --- a/common/api/summary/presentation-common.exports.csv +++ b/common/api/summary/presentation-common.exports.csv @@ -16,6 +16,7 @@ public;CategoryDescription public;CategoryDescriptionJSON public;CategoryIdentifier = ParentCategoryIdentifier | RootCategoryIdentifier | IdCategoryIdentifier public;CheckBoxRule +deprecated;CheckBoxRule public;ChildNodeRule public;ChildNodeSpecification = CustomNodeSpecification | InstanceNodesOfSpecificClassesSpecification | RelatedInstanceNodesSpecification | CustomQueryInstanceNodesSpecification public;ChildNodeSpecificationBase @@ -129,7 +130,6 @@ public;FilterByTextHierarchyRequestOptions public;FilterByTextHierarchyRpcRequestOptions = PresentationRpcRequestOptions internal;getFieldByName: (fields: Field[], name: string | undefined, recurse?: boolean | undefined) => Field | undefined public;getInstancesCount: (keys: Readonly -internal;getLocalesDirectory: (assetsDirectory: string) => string public;GroupingNodeKey public;GroupingNodeKeyJSON public;GroupingRule @@ -155,6 +155,7 @@ public;Id64sRulesetVariable public;Id64sRulesetVariableJSON public;IdCategoryIdentifier public;ImageIdOverride +deprecated;ImageIdOverride public;InstanceId = Id64String public;InstanceKey public;InstanceKey @@ -197,6 +198,7 @@ public;LabelDefinitionJSON public;LabelGroupingNodeKey public;LabelGroupingNodeKeyJSON public;LabelOverride +deprecated;LabelOverride public;LabelRawValue = string | number | boolean | LabelCompositeValue public;LabelRawValueJSON = string | number | boolean | LabelCompositeValueJSON beta;MultiElementPropertiesRequestOptions @@ -368,6 +370,7 @@ public;StrippedRelationshipPath = StrippedRelatedClassInfo[] public;StructFieldMemberDescription public;StructTypeDescription public;StyleOverride +deprecated;StyleOverride public;SubCondition public;Subtract public;SupplementationInfo diff --git a/common/api/webgl-compatibility.api.md b/common/api/webgl-compatibility.api.md index 4beeb12a9aa7..f68be618472b 100644 --- a/common/api/webgl-compatibility.api.md +++ b/common/api/webgl-compatibility.api.md @@ -152,6 +152,7 @@ export interface WebGLRenderCompatibilityInfo { unmaskedRenderer?: string; unmaskedVendor?: string; userAgent: string; + usingIntegratedGraphics?: boolean; } // @public diff --git a/common/changes/@bentley/imodelbank-client/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@bentley/imodelbank-client/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@bentley/imodelbank-client/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@bentley/imodelbank-client/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@bentley/imodelbank-client/update-deps_2022-01-27-21-26.json b/common/changes/@bentley/imodelbank-client/update-deps_2022-01-27-21-26.json deleted file mode 100644 index c35f0eafc3f0..000000000000 --- a/common/changes/@bentley/imodelbank-client/update-deps_2022-01-27-21-26.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@bentley/imodelbank-client", - "comment": "", - "type": "none" - } - ], - "packageName": "@bentley/imodelbank-client" -} \ No newline at end of file diff --git a/common/changes/@itwin/analytical-backend/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/analytical-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/analytical-backend/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/analytical-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/appui-abstract/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/appui-abstract/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/appui-abstract/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/appui-abstract/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/appui-abstract/fixMiscUiBugs_2022-03-17-22-29.json b/common/changes/@itwin/appui-abstract/fixMiscUiBugs_2022-03-17-22-29.json new file mode 100644 index 000000000000..a13a2535af6c --- /dev/null +++ b/common/changes/@itwin/appui-abstract/fixMiscUiBugs_2022-03-17-22-29.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-abstract", + "comment": "Fix missing parameter in UiManager.getWidgets call and pass provider to isSupportedStage function.", + "type": "none" + } + ], + "packageName": "@itwin/appui-abstract" +} \ No newline at end of file diff --git a/common/changes/@itwin/appui-abstract/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/appui-abstract/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..28e49225d58a --- /dev/null +++ b/common/changes/@itwin/appui-abstract/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-abstract", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/appui-abstract" +} \ No newline at end of file diff --git a/common/changes/@itwin/appui-abstract/ui-icon-loading_2022-03-15-22-30.json b/common/changes/@itwin/appui-abstract/ui-icon-loading_2022-03-15-22-30.json new file mode 100644 index 000000000000..772385955720 --- /dev/null +++ b/common/changes/@itwin/appui-abstract/ui-icon-loading_2022-03-15-22-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-abstract", + "comment": "Implement svg icons loading as a web component.", + "type": "none" + } + ], + "packageName": "@itwin/appui-abstract" +} \ No newline at end of file diff --git a/common/changes/@itwin/appui-layout-react/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/appui-layout-react/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/appui-layout-react/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/appui-layout-react/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/appui-layout-react/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/appui-layout-react/kill-old-ext-api_2022-03-14-19-00.json similarity index 74% rename from common/changes/@itwin/appui-layout-react/vyki-itwinui-update-1_2022-01-25-19-30.json rename to common/changes/@itwin/appui-layout-react/kill-old-ext-api_2022-03-14-19-00.json index 68e33a0ae688..d19f639ab6ef 100644 --- a/common/changes/@itwin/appui-layout-react/vyki-itwinui-update-1_2022-01-25-19-30.json +++ b/common/changes/@itwin/appui-layout-react/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-layout-react", - "comment": "Update to latest itwinui-react", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/appui-layout-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/appui-layout-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json similarity index 70% rename from common/changes/@itwin/appui-layout-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/appui-layout-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json index 01eec81dafa9..825190f8a1b1 100644 --- a/common/changes/@itwin/appui-layout-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/appui-layout-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-layout-react", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "Update itwinui-css version", "type": "none" } ], diff --git a/common/changes/@itwin/appui-layout-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json b/common/changes/@itwin/appui-layout-react/ui-icon-loading_2022-03-15-22-30.json similarity index 65% rename from common/changes/@itwin/appui-layout-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json rename to common/changes/@itwin/appui-layout-react/ui-icon-loading_2022-03-15-22-30.json index 0d84ff064600..797686329f0d 100644 --- a/common/changes/@itwin/appui-layout-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json +++ b/common/changes/@itwin/appui-layout-react/ui-icon-loading_2022-03-15-22-30.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-layout-react", - "comment": "Add data attributes to identify item and its UI provider.", + "comment": "Implement svg icons loading as a web component.", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/appui-react/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/appui-react/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/appui-react/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/appui-react/ui-updateContextMenuToDropdownMenu_2022-02-16-15-19.json b/common/changes/@itwin/appui-react/fix-audit-errors_2022-03-22-21-26.json similarity index 100% rename from common/changes/@itwin/appui-react/ui-updateContextMenuToDropdownMenu_2022-02-16-15-19.json rename to common/changes/@itwin/appui-react/fix-audit-errors_2022-03-22-21-26.json diff --git a/common/changes/@itwin/appui-react/ui-check-widget-visibility_2022-02-16-21-30.json b/common/changes/@itwin/appui-react/fixMiscUiBugs_2022-03-17-22-29.json similarity index 53% rename from common/changes/@itwin/appui-react/ui-check-widget-visibility_2022-02-16-21-30.json rename to common/changes/@itwin/appui-react/fixMiscUiBugs_2022-03-17-22-29.json index d79539e8bfd5..bd573409beeb 100644 --- a/common/changes/@itwin/appui-react/ui-check-widget-visibility_2022-02-16-21-30.json +++ b/common/changes/@itwin/appui-react/fixMiscUiBugs_2022-03-17-22-29.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Add FrontstageDef.isWidgetDisplayed() to allow apps to query whether their widget is visible.", + "comment": "Fix missing parameter in UiManager.getWidgets call and pass provider to isSupportedStage function.", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/appui-react/kill-old-ext-api_2022-03-14-19-00.json similarity index 68% rename from common/changes/@itwin/appui-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/appui-react/kill-old-ext-api_2022-03-14-19-00.json index f6c6b193c334..3393c35368c5 100644 --- a/common/changes/@itwin/appui-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/appui-react/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/ui-map-layers-providers_2022-01-15-00-48.json b/common/changes/@itwin/appui-react/master_2022-03-09-13-16.json similarity index 60% rename from common/changes/@itwin/appui-react/ui-map-layers-providers_2022-01-15-00-48.json rename to common/changes/@itwin/appui-react/master_2022-03-09-13-16.json index d0981dfbb160..144ba5ccc80b 100644 --- a/common/changes/@itwin/appui-react/ui-map-layers-providers_2022-01-15-00-48.json +++ b/common/changes/@itwin/appui-react/master_2022-03-09-13-16.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Change initializeNineZoneState to properly handle floating widgets.", + "comment": "Allow initial UI version to be set when UIFramework is initialized.", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/rd-client-0.7.2_2022-03-17-18-51.json b/common/changes/@itwin/appui-react/rd-client-0.7.2_2022-03-17-18-51.json new file mode 100644 index 000000000000..b91bd1f697c7 --- /dev/null +++ b/common/changes/@itwin/appui-react/rd-client-0.7.2_2022-03-17-18-51.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/appui-react", + "comment": "ListBox component: `onKeyPress` has been deprecated, switch to `onKeyDown`", + "type": "none" + } + ], + "packageName": "@itwin/appui-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/appui-react/ui-FloatingContentControl_2022-01-19-20-41.json b/common/changes/@itwin/appui-react/ui-FloatingContentControl_2022-01-19-20-41.json deleted file mode 100644 index 51847057bcd0..000000000000 --- a/common/changes/@itwin/appui-react/ui-FloatingContentControl_2022-01-19-20-41.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/appui-react", - "comment": "Added ContentDialogManager, ContentDialog, and FloatingViewportContentControl to allow imodel viewport in a modeless dialog.", - "type": "none" - } - ], - "packageName": "@itwin/appui-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/appui-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json b/common/changes/@itwin/appui-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json deleted file mode 100644 index 325d37465af1..000000000000 --- a/common/changes/@itwin/appui-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/appui-react", - "comment": "Provide FrontstageManager.clearFrontstageProviders method to clear out static maps.", - "type": "none" - } - ], - "packageName": "@itwin/appui-react" -} diff --git a/common/changes/@itwin/appui-react/ui-viewport-docs_2022-01-28-22-15.json b/common/changes/@itwin/appui-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json similarity index 67% rename from common/changes/@itwin/appui-react/ui-viewport-docs_2022-01-28-22-15.json rename to common/changes/@itwin/appui-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json index 678975b379da..a7d34e077e29 100644 --- a/common/changes/@itwin/appui-react/ui-viewport-docs_2022-01-28-22-15.json +++ b/common/changes/@itwin/appui-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Fix spelling error in function documentation.", + "comment": "Update itwinui-css version", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json b/common/changes/@itwin/appui-react/ui-icon-loading_2022-03-15-22-30.json similarity index 63% rename from common/changes/@itwin/appui-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json rename to common/changes/@itwin/appui-react/ui-icon-loading_2022-03-15-22-30.json index 86a41af8b8b8..025f39159886 100644 --- a/common/changes/@itwin/appui-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json +++ b/common/changes/@itwin/appui-react/ui-icon-loading_2022-03-15-22-30.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Add data attributes to identify item and its UI provider.", + "comment": "Implement svg icons loading as a web component.", "type": "none" } ], diff --git a/common/changes/@itwin/appui-react/update-deps_2022-01-25-17-24.json b/common/changes/@itwin/appui-react/update-deps_2022-01-25-17-24.json deleted file mode 100644 index 9c1115e0eb1c..000000000000 --- a/common/changes/@itwin/appui-react/update-deps_2022-01-25-17-24.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/appui-react", - "comment": "Remove unecessary dependency on itwin/browser-authorization", - "type": "none" - } - ], - "packageName": "@itwin/appui-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/appui-react/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/appui-react/vyki-itwinui-update-1_2022-01-25-19-30.json deleted file mode 100644 index e2a652dbd2f0..000000000000 --- a/common/changes/@itwin/appui-react/vyki-itwinui-update-1_2022-01-25-19-30.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/appui-react", - "comment": "Update to latest itwinui-react - requires new compile option allowSyntheticDefaultImports=true.", - "type": "none" - } - ], - "packageName": "@itwin/appui-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/appui-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json b/common/changes/@itwin/appui-react/webpack5-support_2022-03-11-21-28.json similarity index 63% rename from common/changes/@itwin/appui-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json rename to common/changes/@itwin/appui-react/webpack5-support_2022-03-11-21-28.json index 4195a26f637e..0fb5d17e6bcd 100644 --- a/common/changes/@itwin/appui-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json +++ b/common/changes/@itwin/appui-react/webpack5-support_2022-03-11-21-28.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/appui-react", - "comment": "Update ToolbarAutoHidePopup context when widgets autohide.", + "comment": "use `setTimeout` instead of `setImmediate`", "type": "none" } ], diff --git a/common/changes/@itwin/backend-webpack-tools/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/backend-webpack-tools/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/backend-webpack-tools/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/backend-webpack-tools/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/build-tools/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/build-tools/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/build-tools/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/build-tools/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/build-tools/bump-typedoc-version_2022-01-18-16-57.json b/common/changes/@itwin/build-tools/bump-typedoc-version_2022-01-18-16-57.json deleted file mode 100644 index a9db67aec54a..000000000000 --- a/common/changes/@itwin/build-tools/bump-typedoc-version_2022-01-18-16-57.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/build-tools", - "comment": "Bumped Typedoc patch version", - "type": "none" - } - ], - "packageName": "@itwin/build-tools" -} \ No newline at end of file diff --git a/common/changes/@itwin/build-tools/packageroot-on-docs_2022-01-26-22-19.json b/common/changes/@itwin/build-tools/packageroot-on-docs_2022-01-26-22-19.json deleted file mode 100644 index c96a6dde9def..000000000000 --- a/common/changes/@itwin/build-tools/packageroot-on-docs_2022-01-26-22-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/build-tools", - "comment": "Added packageRoot property to Typedoc output", - "type": "none" - } - ], - "packageName": "@itwin/build-tools" -} \ No newline at end of file diff --git a/common/changes/@itwin/certa/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/certa/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/certa/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/certa/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/certa/native-3.1.5_2022-02-09-21-46.json b/common/changes/@itwin/certa/native-3.1.5_2022-02-09-21-46.json deleted file mode 100644 index 7754923ba420..000000000000 --- a/common/changes/@itwin/certa/native-3.1.5_2022-02-09-21-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/certa", - "comment": "Stop exiting with process.exit() and add ability for a \"backendInitModule\" to supply a cleanup callback to execute after tests complete.", - "type": "none" - } - ], - "packageName": "@itwin/certa" -} \ No newline at end of file diff --git a/common/changes/@itwin/components-react/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/components-react/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/components-react/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/components-react/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/components-react/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/components-react/fix-audit-errors_2022-03-22-21-26.json similarity index 73% rename from common/changes/@itwin/components-react/vyki-itwinui-update-1_2022-01-25-19-30.json rename to common/changes/@itwin/components-react/fix-audit-errors_2022-03-22-21-26.json index 22e972280b73..d2d24b087cf6 100644 --- a/common/changes/@itwin/components-react/vyki-itwinui-update-1_2022-01-25-19-30.json +++ b/common/changes/@itwin/components-react/fix-audit-errors_2022-03-22-21-26.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/components-react", - "comment": "Update to latest itwinui-react.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/components-react/kill-old-ext-api_2022-03-14-19-00.json similarity index 70% rename from common/changes/@itwin/components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/components-react/kill-old-ext-api_2022-03-14-19-00.json index 65c35f682ff6..d2d24b087cf6 100644 --- a/common/changes/@itwin/components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/components-react/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/components-react", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json b/common/changes/@itwin/components-react/presentation-docs-property-value-renderers_2022-03-17-09-55.json similarity index 65% rename from common/changes/@itwin/components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json rename to common/changes/@itwin/components-react/presentation-docs-property-value-renderers_2022-03-17-09-55.json index f94c5e4b8ef8..d2d24b087cf6 100644 --- a/common/changes/@itwin/components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json +++ b/common/changes/@itwin/components-react/presentation-docs-property-value-renderers_2022-03-17-09-55.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/components-react", - "comment": "Add data attributes to identify item and its UI provider.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/components-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json b/common/changes/@itwin/components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json similarity index 62% rename from common/changes/@itwin/components-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json rename to common/changes/@itwin/components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json index 9c53334250a8..89aebdeb5fef 100644 --- a/common/changes/@itwin/components-react/ui-fixAutoHideOfToolPanels_2022-02-11-20-21.json +++ b/common/changes/@itwin/components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/components-react", - "comment": "Use ToolbarAutoHidePopupContext to monitor widgets' authoidden state.", + "comment": "Update itwinui-css version", "type": "none" } ], diff --git a/common/changes/@itwin/components-react/ui-icon-loading_2022-03-15-22-30.json b/common/changes/@itwin/components-react/ui-icon-loading_2022-03-15-22-30.json new file mode 100644 index 000000000000..2c22d33f38af --- /dev/null +++ b/common/changes/@itwin/components-react/ui-icon-loading_2022-03-15-22-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/components-react", + "comment": "Implement svg icons loading as a web component.", + "type": "none" + } + ], + "packageName": "@itwin/components-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/components-react/webpack5-support_2022-03-11-21-28.json b/common/changes/@itwin/components-react/webpack5-support_2022-03-11-21-28.json new file mode 100644 index 000000000000..09ecac73b446 --- /dev/null +++ b/common/changes/@itwin/components-react/webpack5-support_2022-03-11-21-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/components-react", + "comment": "use `setTimeout` instead of `setImmediate`", + "type": "none" + } + ], + "packageName": "@itwin/components-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-backend/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-backend/deprecate-get-view-thumbnail_2022-01-31-15-31.json b/common/changes/@itwin/core-backend/error-on-no-hub-access_2022-03-21-15-17.json similarity index 64% rename from common/changes/@itwin/core-backend/deprecate-get-view-thumbnail_2022-01-31-15-31.json rename to common/changes/@itwin/core-backend/error-on-no-hub-access_2022-03-21-15-17.json index e40b29c4f2f7..cdc12470b55d 100644 --- a/common/changes/@itwin/core-backend/deprecate-get-view-thumbnail_2022-01-31-15-31.json +++ b/common/changes/@itwin/core-backend/error-on-no-hub-access_2022-03-21-15-17.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-backend", - "comment": "Deprecate IModelReadRpcInterface.getViewThumbnail", + "comment": "Improved error message for undefined IModelHost.hubAccess", "type": "none" } ], diff --git a/common/changes/@itwin/core-backend/fix-generated-class-predecessors_2022-01-10-21-46.json b/common/changes/@itwin/core-backend/fix-generated-class-predecessors_2022-01-10-21-46.json deleted file mode 100644 index 4c79ae563f32..000000000000 --- a/common/changes/@itwin/core-backend/fix-generated-class-predecessors_2022-01-10-21-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "generated element classes now have a default implementation of collectPredecessors returning all set navigation properties", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/fix-return-status_2022-01-20-15-05.json b/common/changes/@itwin/core-backend/fix-return-status_2022-01-20-15-05.json deleted file mode 100644 index a5ad7b159980..000000000000 --- a/common/changes/@itwin/core-backend/fix-return-status_2022-01-20-15-05.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "Correct return status for processGeometryStream and createBRepGeometry.", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/fix-types-ws_2022-02-03-19-05.json b/common/changes/@itwin/core-backend/fix-types-ws_2022-02-03-19-05.json deleted file mode 100644 index 99b35bb89b62..000000000000 --- a/common/changes/@itwin/core-backend/fix-types-ws_2022-02-03-19-05.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/native-3.1.6_2022-02-22-15-08.json b/common/changes/@itwin/core-backend/native-3.1.6_2022-02-22-15-08.json deleted file mode 100644 index 99b35bb89b62..000000000000 --- a/common/changes/@itwin/core-backend/native-3.1.6_2022-02-22-15-08.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/core-backend/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index 99b35bb89b62..000000000000 --- a/common/changes/@itwin/core-backend/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/azure-gov_2022-02-17-15-59.json b/common/changes/@itwin/core-backend/reimplement-get-view-thumbnail_2022-03-07-17-37.json similarity index 100% rename from common/changes/@itwin/core-backend/azure-gov_2022-02-17-15-59.json rename to common/changes/@itwin/core-backend/reimplement-get-view-thumbnail_2022-03-07-17-37.json diff --git a/common/changes/@itwin/core-backend/remove-element-geometry-update_2022-01-14-18-19.json b/common/changes/@itwin/core-backend/remove-element-geometry-update_2022-01-14-18-19.json deleted file mode 100644 index 3ba6640c558e..000000000000 --- a/common/changes/@itwin/core-backend/remove-element-geometry-update_2022-01-14-18-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "Remove IModelDb.elementGeometryUpdate.", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/samw-element-geometry-builder-params_2022-01-12-11-53.json b/common/changes/@itwin/core-backend/samw-element-geometry-builder-params_2022-01-12-11-53.json deleted file mode 100644 index b5b5caa60d5d..000000000000 --- a/common/changes/@itwin/core-backend/samw-element-geometry-builder-params_2022-01-12-11-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "You may specify an element's geometry in terms of an ElementGeometryDataEntry array", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/update-deps_2022-01-28-15-19.json b/common/changes/@itwin/core-backend/update-deps_2022-01-28-15-19.json deleted file mode 100644 index 99b35bb89b62..000000000000 --- a/common/changes/@itwin/core-backend/update-deps_2022-01-28-15-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-backend/web-ipc-reload-fix_2022-01-25-15-56.json b/common/changes/@itwin/core-backend/web-ipc-reload-fix_2022-01-25-15-56.json deleted file mode 100644 index 63a4a8c51875..000000000000 --- a/common/changes/@itwin/core-backend/web-ipc-reload-fix_2022-01-25-15-56.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-backend", - "comment": "Web IPC fix (when reloading frontend).", - "type": "none" - } - ], - "packageName": "@itwin/core-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-bentley/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-bentley/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-bentley/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-bentley/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-bentley/fix-generated-class-predecessors_2022-01-10-21-46.json b/common/changes/@itwin/core-bentley/fix-generated-class-predecessors_2022-01-10-21-46.json deleted file mode 100644 index ecbdce8625cb..000000000000 --- a/common/changes/@itwin/core-bentley/fix-generated-class-predecessors_2022-01-10-21-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-bentley", - "comment": "added ClassUtils.isProperSubclassOf utility", - "type": "none" - } - ], - "packageName": "@itwin/core-bentley" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-bentley/marc.bedard8-RealityDataError_2022-02-18-13-56.json b/common/changes/@itwin/core-bentley/kill-old-ext-api_2022-03-14-19-00.json similarity index 76% rename from common/changes/@itwin/core-bentley/marc.bedard8-RealityDataError_2022-02-18-13-56.json rename to common/changes/@itwin/core-bentley/kill-old-ext-api_2022-03-14-19-00.json index a8b655714029..f2bd3c5133b7 100644 --- a/common/changes/@itwin/core-bentley/marc.bedard8-RealityDataError_2022-02-18-13-56.json +++ b/common/changes/@itwin/core-bentley/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-bentley", - "comment": "Add realityDataStatus", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/core-common/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-common/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-common/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-common/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-common/Bim-map-layers_2022-02-11-13-14.json b/common/changes/@itwin/core-common/Bim-map-layers_2022-02-11-13-14.json deleted file mode 100644 index 6fa3e2b76eb0..000000000000 --- a/common/changes/@itwin/core-common/Bim-map-layers_2022-02-11-13-14.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-common", - "comment": "Add support for map layers using model geometry.", - "type": "none" - } - ], - "packageName": "@itwin/core-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-common/deprecate-get-view-thumbnail_2022-01-31-15-31.json b/common/changes/@itwin/core-common/deprecate-get-view-thumbnail_2022-01-31-15-31.json deleted file mode 100644 index 1e143cfa4ede..000000000000 --- a/common/changes/@itwin/core-common/deprecate-get-view-thumbnail_2022-01-31-15-31.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-common", - "comment": "Deprecate IModelReadRpcInterface.getViewThumbnail", - "type": "none" - } - ], - "packageName": "@itwin/core-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-common/geo-mapbox_fix_2022-01-28-17-30.json b/common/changes/@itwin/core-common/geo-mapbox_fix_2022-01-28-17-30.json deleted file mode 100644 index cb276e50fe54..000000000000 --- a/common/changes/@itwin/core-common/geo-mapbox_fix_2022-01-28-17-30.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-common", - "comment": "Migrated from deprecated MapBox api.", - "type": "none" - } - ], - "packageName": "@itwin/core-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-common/native-3.1.3_2022-02-03-21-08.json b/common/changes/@itwin/core-common/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/core-common/native-3.1.3_2022-02-03-21-08.json rename to common/changes/@itwin/core-common/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/core-common/skip-empty-url-segments_2022-01-25-10-09.json b/common/changes/@itwin/core-common/pmc-fix-background-map-ui_2022-03-11-22-25.json similarity index 72% rename from common/changes/@itwin/core-common/skip-empty-url-segments_2022-01-25-10-09.json rename to common/changes/@itwin/core-common/pmc-fix-background-map-ui_2022-03-11-22-25.json index d1ac065f5d72..3326030dc210 100644 --- a/common/changes/@itwin/core-common/skip-empty-url-segments_2022-01-25-10-09.json +++ b/common/changes/@itwin/core-common/pmc-fix-background-map-ui_2022-03-11-22-25.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-common", - "comment": "", + "comment": "Add BackgroundMapProvider.clone.", "type": "none" } ], diff --git a/common/changes/@itwin/core-common/graphicbuilder-addimage_2022-01-13-22-24.json b/common/changes/@itwin/core-common/pmc-validate-color-def_2022-03-15-15-16.json similarity index 52% rename from common/changes/@itwin/core-common/graphicbuilder-addimage_2022-01-13-22-24.json rename to common/changes/@itwin/core-common/pmc-validate-color-def_2022-03-15-15-16.json index fdc4c7eb5a08..3ad34840cf92 100644 --- a/common/changes/@itwin/core-common/graphicbuilder-addimage_2022-01-13-22-24.json +++ b/common/changes/@itwin/core-common/pmc-validate-color-def_2022-03-15-15-16.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/core-common", - "comment": "Deprecate RenderMaterial.Params in favor of CreateRenderMaterialArgs (core-frontend).", + "comment": "Add methods to validate ColorDefProps and color strings; fix failure to find duplicate color names.", "type": "none" } ], "packageName": "@itwin/core-common" -} \ No newline at end of file +} diff --git a/common/changes/@itwin/core-common/remove-element-geometry-update_2022-01-14-18-19.json b/common/changes/@itwin/core-common/remove-element-geometry-update_2022-01-14-18-19.json deleted file mode 100644 index 857462a1e64e..000000000000 --- a/common/changes/@itwin/core-common/remove-element-geometry-update_2022-01-14-18-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-common", - "comment": "Remove IModelDb.elementGeometryUpdate.", - "type": "none" - } - ], - "packageName": "@itwin/core-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-common/web-ipc-reload-fix_2022-01-25-15-56.json b/common/changes/@itwin/core-common/web-ipc-reload-fix_2022-01-25-15-56.json deleted file mode 100644 index 366838361628..000000000000 --- a/common/changes/@itwin/core-common/web-ipc-reload-fix_2022-01-25-15-56.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-common", - "comment": "Web IPC fix (when reloading frontend).", - "type": "none" - } - ], - "packageName": "@itwin/core-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-common/samw-element-geometry-builder-params_2022-01-12-11-53.json b/common/changes/@itwin/core-common/webpack5-support_2022-03-11-21-28.json similarity index 66% rename from common/changes/@itwin/core-common/samw-element-geometry-builder-params_2022-01-12-11-53.json rename to common/changes/@itwin/core-common/webpack5-support_2022-03-11-21-28.json index e202b713ff61..2849562ffba0 100644 --- a/common/changes/@itwin/core-common/samw-element-geometry-builder-params_2022-01-12-11-53.json +++ b/common/changes/@itwin/core-common/webpack5-support_2022-03-11-21-28.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-common", - "comment": "ElementGeometryBuilderParams", + "comment": "use proper node polyfills for webpack 5 support", "type": "none" } ], diff --git a/common/changes/@itwin/core-electron/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-electron/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-electron/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-electron/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-extension/webpack5-support_2022-03-11-21-28.json b/common/changes/@itwin/core-extension/webpack5-support_2022-03-11-21-28.json new file mode 100644 index 000000000000..0310f2f7518c --- /dev/null +++ b/common/changes/@itwin/core-extension/webpack5-support_2022-03-11-21-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-extension", + "comment": "use `import.meta.url`", + "type": "none" + } + ], + "packageName": "@itwin/core-extension" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-frontend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-frontend/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-frontend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-frontend/web-ipc-reload-fix_2022-01-25-15-56.json b/common/changes/@itwin/core-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json similarity index 70% rename from common/changes/@itwin/core-frontend/web-ipc-reload-fix_2022-01-25-15-56.json rename to common/changes/@itwin/core-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json index 02fc1be3a55e..15c9d165df6c 100644 --- a/common/changes/@itwin/core-frontend/web-ipc-reload-fix_2022-01-25-15-56.json +++ b/common/changes/@itwin/core-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Web IPC fix (when reloading frontend).", + "comment": "CurvePrimitive.clone narrowing", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/ao-nonpickable-fixes_2022-01-24-14-59.json b/common/changes/@itwin/core-frontend/briefcase-active-settings_2022-03-11-11-43.json similarity index 57% rename from common/changes/@itwin/core-frontend/ao-nonpickable-fixes_2022-01-24-14-59.json rename to common/changes/@itwin/core-frontend/briefcase-active-settings_2022-03-11-11-43.json index c390605e8a49..a0dd042dcb1e 100644 --- a/common/changes/@itwin/core-frontend/ao-nonpickable-fixes_2022-01-24-14-59.json +++ b/common/changes/@itwin/core-frontend/briefcase-active-settings_2022-03-11-11-43.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Non-pickable decorations used to fail to render if Ambient Occlusion was enabled.", + "comment": "Move ToolAdmin.activeSettings to BriefcaseConnection and add PrimitiveTool.briefcase.", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/drape-support-for-reality-meshes_2022-01-20-17-09.json b/common/changes/@itwin/core-frontend/drape-support-for-reality-meshes_2022-01-20-17-09.json deleted file mode 100644 index 4afa57ec8daa..000000000000 --- a/common/changes/@itwin/core-frontend/drape-support-for-reality-meshes_2022-01-20-17-09.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Add support for obtaining polyfaces from tile geometry using TileGeometryCollector and GeometryTileTreeReference.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/AttachAnyCesiumIonAssets_2022-01-26-19-24.json b/common/changes/@itwin/core-frontend/dta-active-settings_2022-03-09-12-59.json similarity index 100% rename from common/changes/@itwin/core-frontend/AttachAnyCesiumIonAssets_2022-01-26-19-24.json rename to common/changes/@itwin/core-frontend/dta-active-settings_2022-03-09-12-59.json diff --git a/common/changes/@itwin/core-frontend/dynamic-import_2022-01-25-18-01.json b/common/changes/@itwin/core-frontend/dynamic-import_2022-01-25-18-01.json deleted file mode 100644 index 2c02d9ad8462..000000000000 --- a/common/changes/@itwin/core-frontend/dynamic-import_2022-01-25-18-01.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Dynamically import approximate terrain heights instead of fetching as JSON.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/geo-mapbox_fix_2022-01-28-17-30.json b/common/changes/@itwin/core-frontend/export-core-ver_2022-03-01-17-44.json similarity index 68% rename from common/changes/@itwin/core-frontend/geo-mapbox_fix_2022-01-28-17-30.json rename to common/changes/@itwin/core-frontend/export-core-ver_2022-03-01-17-44.json index 3b008b61f34e..642d138f13bf 100644 --- a/common/changes/@itwin/core-frontend/geo-mapbox_fix_2022-01-28-17-30.json +++ b/common/changes/@itwin/core-frontend/export-core-ver_2022-03-01-17-44.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Fixed MapBox imagery failing to display.", + "comment": "Expose iTwin.js Core Version for extensions", "type": "none" } ], "packageName": "@itwin/core-frontend" -} +} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/fix-aa-planar-edges_2022-01-31-15-46.json b/common/changes/@itwin/core-frontend/fix-aa-planar-edges_2022-01-31-15-46.json deleted file mode 100644 index 8091c95f2947..000000000000 --- a/common/changes/@itwin/core-frontend/fix-aa-planar-edges_2022-01-31-15-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Fixed interaction between linear elements and planar elements when antialiasing is turned on.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/dta-save-image_2022-02-02-15-26.json b/common/changes/@itwin/core-frontend/fix-background-base-color_2022-03-08-15-02.json similarity index 58% rename from common/changes/@itwin/core-frontend/dta-save-image_2022-02-02-15-26.json rename to common/changes/@itwin/core-frontend/fix-background-base-color_2022-03-08-15-02.json index 51051cd56639..88adbed5edb6 100644 --- a/common/changes/@itwin/core-frontend/dta-save-image_2022-02-02-15-26.json +++ b/common/changes/@itwin/core-frontend/fix-background-base-color_2022-03-08-15-02.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Fix openImageDataUrlInNewWindow displaying an empty window in Electron.", + "comment": "Fix regression that caused solid color background map base to fail to display.", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/pnts-spec-conformance_2022-02-10-10-58.json b/common/changes/@itwin/core-frontend/floating-point-decorations_2022-03-03-21-24.json similarity index 53% rename from common/changes/@itwin/core-frontend/pnts-spec-conformance_2022-02-10-10-58.json rename to common/changes/@itwin/core-frontend/floating-point-decorations_2022-03-03-21-24.json index c4326975fd49..85ddce903f61 100644 --- a/common/changes/@itwin/core-frontend/pnts-spec-conformance_2022-02-10-10-58.json +++ b/common/changes/@itwin/core-frontend/floating-point-decorations_2022-03-03-21-24.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Fully implement the point cloud 3d tile specification.", + "comment": "Increase precision for vertex positions when producing decoration graphics, to reduce visual artifacts.", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/frontend-missing-localization-namespace_2022-02-08-00-00.json b/common/changes/@itwin/core-frontend/frontend-missing-localization-namespace_2022-02-08-00-00.json deleted file mode 100644 index 74cbb9828af1..000000000000 --- a/common/changes/@itwin/core-frontend/frontend-missing-localization-namespace_2022-02-08-00-00.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Supplied missing 'iModelJs' namespace in some calls to getLocalizedString.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/promoteQuantityFormatterToPublic_2022-02-17-13-01.json b/common/changes/@itwin/core-frontend/geo-validateEsriMapService_2022-03-08-20-15.json similarity index 63% rename from common/changes/@itwin/core-frontend/promoteQuantityFormatterToPublic_2022-02-17-13-01.json rename to common/changes/@itwin/core-frontend/geo-validateEsriMapService_2022-03-08-20-15.json index c1a0c1c3bafd..a621c51fac97 100644 --- a/common/changes/@itwin/core-frontend/promoteQuantityFormatterToPublic_2022-02-17-13-01.json +++ b/common/changes/@itwin/core-frontend/geo-validateEsriMapService_2022-03-08-20-15.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Promote QuantityFormatter from beta to public.", + "comment": "Improved validation of ESRI services before adding map layer", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/graphicbuilder-addimage_2022-01-13-22-24.json b/common/changes/@itwin/core-frontend/graphicbuilder-addimage_2022-01-13-22-24.json deleted file mode 100644 index dfc62417b463..000000000000 --- a/common/changes/@itwin/core-frontend/graphicbuilder-addimage_2022-01-13-22-24.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Simplify RenderMaterial creation by deprecating RenderSystem.createMaterial in favor of RenderSystem.createRenderMaterial.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/imodelapp-debugger_2022-02-15-15-34.json b/common/changes/@itwin/core-frontend/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/core-frontend/imodelapp-debugger_2022-02-15-15-34.json rename to common/changes/@itwin/core-frontend/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/core-frontend/marc.bedard8-RealityDataError_2022-02-18-13-56.json b/common/changes/@itwin/core-frontend/marc.bedard8-RealityDataError_2022-02-18-13-56.json deleted file mode 100644 index 062fe3070946..000000000000 --- a/common/changes/@itwin/core-frontend/marc.bedard8-RealityDataError_2022-02-18-13-56.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Add RealityDataError in RealityDataSource API", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/draco-decode_2022-01-27-21-08.json b/common/changes/@itwin/core-frontend/pmc-fix-background-map-ui_2022-03-11-22-25.json similarity index 51% rename from common/changes/@itwin/core-frontend/draco-decode_2022-01-27-21-08.json rename to common/changes/@itwin/core-frontend/pmc-fix-background-map-ui_2022-03-11-22-25.json index 4f395472e0a4..ceaa8c43a90c 100644 --- a/common/changes/@itwin/core-frontend/draco-decode_2022-01-27-21-08.json +++ b/common/changes/@itwin/core-frontend/pmc-fix-background-map-ui_2022-03-11-22-25.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Add support for decoding draco-compressed point clouds and glTF meshes.", + "comment": "Fix bug in which DisplayStyleState.changeBackgroundMapProvider failed to preserve previous values as advertised.", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/core-frontend/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index b4fad1d23ec1..000000000000 --- a/common/changes/@itwin/core-frontend/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Now initializing Unit alternate display labels from UNIT_EXTRA_DATA. Minimal changes to support Units schema retrieval from backend iModels.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/marcb-RealityDataSource_SpatialExtents_2022-02-07-16-47.json b/common/changes/@itwin/core-frontend/reimplement-get-view-thumbnail_2022-03-07-17-37.json similarity index 100% rename from common/changes/@itwin/core-frontend/marcb-RealityDataSource_SpatialExtents_2022-02-07-16-47.json rename to common/changes/@itwin/core-frontend/reimplement-get-view-thumbnail_2022-03-07-17-37.json diff --git a/common/changes/@itwin/core-frontend/reinstate-margin-options_2022-02-02-13-06.json b/common/changes/@itwin/core-frontend/reinstate-margin-options_2022-02-02-13-06.json deleted file mode 100644 index 309555bb99b2..000000000000 --- a/common/changes/@itwin/core-frontend/reinstate-margin-options_2022-02-02-13-06.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Functions that fit a view to a volume accept an optional MarginOptions specifying how tightly to fit.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} diff --git a/common/changes/@itwin/core-frontend/schema-provider-updates_2022-02-18-17-24.json b/common/changes/@itwin/core-frontend/schema-provider-updates_2022-02-18-17-24.json deleted file mode 100644 index aa5767b088e1..000000000000 --- a/common/changes/@itwin/core-frontend/schema-provider-updates_2022-02-18-17-24.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Defaulting to the internal BasicUnitsProvider if QuantityFormatter units provider initialization fails. ", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/spatial-view-attachment-clip-transform_2022-02-16-19-58.json b/common/changes/@itwin/core-frontend/spatial-view-attachment-clip-transform_2022-02-16-19-58.json deleted file mode 100644 index 1ed94d63b58d..000000000000 --- a/common/changes/@itwin/core-frontend/spatial-view-attachment-clip-transform_2022-02-16-19-58.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Ensure view attachments referencing section drawings transform the spatial view's clip into sheet coordinates.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-frontend/deprecate-get-view-thumbnail_2022-01-31-18-47.json b/common/changes/@itwin/core-frontend/tcobbs-bentley-image-cross-origin_2022-03-18-21-58.json similarity index 53% rename from common/changes/@itwin/core-frontend/deprecate-get-view-thumbnail_2022-01-31-18-47.json rename to common/changes/@itwin/core-frontend/tcobbs-bentley-image-cross-origin_2022-03-18-21-58.json index 2664e8c9cacb..a0df4cf06571 100644 --- a/common/changes/@itwin/core-frontend/deprecate-get-view-thumbnail_2022-01-31-18-47.json +++ b/common/changes/@itwin/core-frontend/tcobbs-bentley-image-cross-origin_2022-03-18-21-58.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Deprecate IModelReadRpcInterface.getViewThumbnail", + "comment": "Add skipCrossOriginCheck parameter (default false) to imageElementFromUrl and tryImageElementFromUrl.", "type": "none" } ], diff --git a/common/changes/@itwin/core-frontend/tile-user_2022-01-20-10-11.json b/common/changes/@itwin/core-frontend/tile-user_2022-01-20-10-11.json deleted file mode 100644 index 5f11e3712962..000000000000 --- a/common/changes/@itwin/core-frontend/tile-user_2022-01-20-10-11.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-frontend", - "comment": "Generalize the concept of a TileUser to include types other than Viewports.", - "type": "none" - } - ], - "packageName": "@itwin/core-frontend" -} diff --git a/common/changes/@itwin/core-frontend/Bim-map-layers_2022-02-11-13-14.json b/common/changes/@itwin/core-frontend/webpack5-support_2022-03-11-21-28.json similarity index 64% rename from common/changes/@itwin/core-frontend/Bim-map-layers_2022-02-11-13-14.json rename to common/changes/@itwin/core-frontend/webpack5-support_2022-03-11-21-28.json index 071437221b67..c4c75ac06825 100644 --- a/common/changes/@itwin/core-frontend/Bim-map-layers_2022-02-11-13-14.json +++ b/common/changes/@itwin/core-frontend/webpack5-support_2022-03-11-21-28.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-frontend", - "comment": "Add support for map layers using model geometry.", + "comment": "use web downlaoder for OrbitGT instead of node downloader", "type": "none" } ], diff --git a/common/changes/@itwin/core-geometry/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-geometry/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-geometry/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-geometry/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-geometry/OffsetBsplineCurve_2022-02-14-04-53.json b/common/changes/@itwin/core-geometry/BsplineCurveClonePartial_2022-03-02-23-37.json similarity index 69% rename from common/changes/@itwin/core-geometry/OffsetBsplineCurve_2022-02-14-04-53.json rename to common/changes/@itwin/core-geometry/BsplineCurveClonePartial_2022-03-02-23-37.json index 4ed26773d90c..f9514622a6a4 100644 --- a/common/changes/@itwin/core-geometry/OffsetBsplineCurve_2022-02-14-04-53.json +++ b/common/changes/@itwin/core-geometry/BsplineCurveClonePartial_2022-03-02-23-37.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-geometry", - "comment": "Offset XY curve improvements", + "comment": "implement clonePartialCurve for B-splines", "type": "none" } ], diff --git a/common/changes/@itwin/core-geometry/EDL-ExtendedSpirals_2022-01-29-00-07.json b/common/changes/@itwin/core-geometry/EDL-ExtendedSpirals_2022-01-29-00-07.json deleted file mode 100644 index 43a79430d449..000000000000 --- a/common/changes/@itwin/core-geometry/EDL-ExtendedSpirals_2022-01-29-00-07.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-geometry", - "comment": "create spirals beyond [0,1]", - "type": "none" - } - ], - "packageName": "@itwin/core-geometry" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-geometry/EDL-TangentBooleans_2022-02-15-14-52.json b/common/changes/@itwin/core-geometry/EDL-TangentBooleans_2022-02-15-14-52.json deleted file mode 100644 index aae4293c98c0..000000000000 --- a/common/changes/@itwin/core-geometry/EDL-TangentBooleans_2022-02-15-14-52.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-geometry", - "comment": "Add secondary sort (based on curvature) to around-the-vertex ordering in planar subdivision with curves", - "type": "none" - } - ], - "packageName": "@itwin/core-geometry" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-geometry/DavidAssaf-MeshExtrudeEllipseAlongPath_2022-01-27-04-27.json b/common/changes/@itwin/core-geometry/LineString3dClonePartialCurveExtension_2022-03-08-00-27.json similarity index 62% rename from common/changes/@itwin/core-geometry/DavidAssaf-MeshExtrudeEllipseAlongPath_2022-01-27-04-27.json rename to common/changes/@itwin/core-geometry/LineString3dClonePartialCurveExtension_2022-03-08-00-27.json index a70e613cde0b..8c18eb5c985c 100644 --- a/common/changes/@itwin/core-geometry/DavidAssaf-MeshExtrudeEllipseAlongPath_2022-01-27-04-27.json +++ b/common/changes/@itwin/core-geometry/LineString3dClonePartialCurveExtension_2022-03-08-00-27.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-geometry", - "comment": "PolyfaceBuilder.addMiteredPipes now handles elliptical sections", + "comment": "allow LineString3d.clonePartialCurve to extend start/end segments", "type": "none" } ], diff --git a/common/changes/@itwin/core-geometry/Matrix4dInverse_2022-02-07-22-34.json b/common/changes/@itwin/core-geometry/Matrix4dInverse_2022-02-07-22-34.json deleted file mode 100644 index 28681dccda34..000000000000 --- a/common/changes/@itwin/core-geometry/Matrix4dInverse_2022-02-07-22-34.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-geometry", - "comment": "fix Matrix4d.createInverse failure", - "type": "none" - } - ], - "packageName": "@itwin/core-geometry" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-geometry/DavidAssaf-CurveTests_2022-01-22-21-58.json b/common/changes/@itwin/core-geometry/kill-old-ext-api_2022-03-14-19-00.json similarity index 78% rename from common/changes/@itwin/core-geometry/DavidAssaf-CurveTests_2022-01-22-21-58.json rename to common/changes/@itwin/core-geometry/kill-old-ext-api_2022-03-14-19-00.json index e010a6373764..9d7216f28509 100644 --- a/common/changes/@itwin/core-geometry/DavidAssaf-CurveTests_2022-01-22-21-58.json +++ b/common/changes/@itwin/core-geometry/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-geometry", - "comment": "add two geom tests", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/core-i18n/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-i18n/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-i18n/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-i18n/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-i18n/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/core-i18n/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..6e3adc7db470 --- /dev/null +++ b/common/changes/@itwin/core-i18n/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-i18n", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-i18n" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-markup/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-markup/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-markup/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-markup/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-markup/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/core-markup/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..7a94265251a1 --- /dev/null +++ b/common/changes/@itwin/core-markup/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-markup", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-markup" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-mobile/3.0.0-changelogs_2022-02-09-21-41.json b/common/changes/@itwin/core-mobile/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-mobile/3.0.0-changelogs_2022-02-09-21-41.json rename to common/changes/@itwin/core-mobile/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-mobile/fix-types-ws_2022-02-03-19-05.json b/common/changes/@itwin/core-mobile/fix-types-ws_2022-02-03-19-05.json deleted file mode 100644 index 55fa0784386a..000000000000 --- a/common/changes/@itwin/core-mobile/fix-types-ws_2022-02-03-19-05.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-mobile", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-mobile" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-mobile/mobile-release-tags_2021-12-04-14-41.json b/common/changes/@itwin/core-mobile/mobile-release-tags_2021-12-04-14-41.json deleted file mode 100644 index 55fa0784386a..000000000000 --- a/common/changes/@itwin/core-mobile/mobile-release-tags_2021-12-04-14-41.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-mobile", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-mobile" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-orbitgt/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/core-orbitgt/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-orbitgt/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/core-orbitgt/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-orbitgt/krovaken-fix_2022-02-05-00-38.json b/common/changes/@itwin/core-orbitgt/kill-old-ext-api_2022-03-14-19-00.json similarity index 68% rename from common/changes/@itwin/core-orbitgt/krovaken-fix_2022-02-05-00-38.json rename to common/changes/@itwin/core-orbitgt/kill-old-ext-api_2022-03-14-19-00.json index cefb3e06c529..11f81174ebb1 100644 --- a/common/changes/@itwin/core-orbitgt/krovaken-fix_2022-02-05-00-38.json +++ b/common/changes/@itwin/core-orbitgt/kill-old-ext-api_2022-03-14-19-00.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/core-orbitgt", - "comment": "Add well-known text parsing for KrovakEN", + "comment": "", "type": "none" } ], "packageName": "@itwin/core-orbitgt" -} +} \ No newline at end of file diff --git a/common/changes/@itwin/core-quantity/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/core-quantity/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-quantity/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/core-quantity/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-quantity/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/core-quantity/kill-old-ext-api_2022-03-14-19-00.json similarity index 58% rename from common/changes/@itwin/core-quantity/queryUnitsSchema_2022-02-01-19-53.json rename to common/changes/@itwin/core-quantity/kill-old-ext-api_2022-03-14-19-00.json index afd10bf43ecc..2bb40169d9fe 100644 --- a/common/changes/@itwin/core-quantity/queryUnitsSchema_2022-02-01-19-53.json +++ b/common/changes/@itwin/core-quantity/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-quantity", - "comment": "Refactor Format class to align with the Format class of @itwin/ecschema-metadata.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/core-react/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/core-react/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-react/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/core-react/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-react/core-react-checkbox-workaround_2022-02-02-10-47.json b/common/changes/@itwin/core-react/core-react-checkbox-workaround_2022-02-02-10-47.json deleted file mode 100644 index 2345d3c3836c..000000000000 --- a/common/changes/@itwin/core-react/core-react-checkbox-workaround_2022-02-02-10-47.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-react", - "comment": "`TreeNode`: Fix checkbox propagating click events to the parent element, resulting in unexpected TreeNodeProps.onClick invocations.", - "type": "none" - } - ], - "packageName": "@itwin/core-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/core-react/fix-audit-errors_2022-03-22-21-26.json similarity index 68% rename from common/changes/@itwin/core-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/core-react/fix-audit-errors_2022-03-22-21-26.json index 6b0d44da43c1..17ffb5584189 100644 --- a/common/changes/@itwin/core-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/core-react/fix-audit-errors_2022-03-22-21-26.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-react", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/core-react/ui-FloatingContentControl_2022-01-19-20-41.json b/common/changes/@itwin/core-react/kill-old-ext-api_2022-03-14-19-00.json similarity index 63% rename from common/changes/@itwin/core-react/ui-FloatingContentControl_2022-01-19-20-41.json rename to common/changes/@itwin/core-react/kill-old-ext-api_2022-03-14-19-00.json index 1efa3f51fd1a..17ffb5584189 100644 --- a/common/changes/@itwin/core-react/ui-FloatingContentControl_2022-01-19-20-41.json +++ b/common/changes/@itwin/core-react/kill-old-ext-api_2022-03-14-19-00.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/core-react", - "comment": "Add ability to keep Dialog within application window.", + "comment": "", "type": "none" } ], "packageName": "@itwin/core-react" -} +} \ No newline at end of file diff --git a/common/changes/@itwin/core-react/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/core-react/native-3.2.0_2022-03-14-16-53.json similarity index 53% rename from common/changes/@itwin/core-react/vyki-itwinui-update-1_2022-01-25-19-30.json rename to common/changes/@itwin/core-react/native-3.2.0_2022-03-14-16-53.json index 381f173c29cd..13f71362be1c 100644 --- a/common/changes/@itwin/core-react/vyki-itwinui-update-1_2022-01-25-19-30.json +++ b/common/changes/@itwin/core-react/native-3.2.0_2022-03-14-16-53.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-react", - "comment": "Update to latest itwinui-react - requires new compile option allowSyntheticDefaultImports=true.", + "comment": "skip eslint rule for deprecation in Listbox.tsx", "type": "none" } ], diff --git a/common/changes/@itwin/core-react/rd-client-0.7.2_2022-03-17-18-51.json b/common/changes/@itwin/core-react/rd-client-0.7.2_2022-03-17-18-51.json new file mode 100644 index 000000000000..d77416718bf2 --- /dev/null +++ b/common/changes/@itwin/core-react/rd-client-0.7.2_2022-03-17-18-51.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-react", + "comment": "ListBox component: `onKeyPress` has been deprecated, switch to `onKeyDown`", + "type": "none" + } + ], + "packageName": "@itwin/core-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json b/common/changes/@itwin/core-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json new file mode 100644 index 000000000000..90d33e686e4b --- /dev/null +++ b/common/changes/@itwin/core-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-react", + "comment": "Update itwinui-css version", + "type": "none" + } + ], + "packageName": "@itwin/core-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-react/ui-icon-loading_2022-03-15-22-30.json b/common/changes/@itwin/core-react/ui-icon-loading_2022-03-15-22-30.json new file mode 100644 index 000000000000..f82de9704848 --- /dev/null +++ b/common/changes/@itwin/core-react/ui-icon-loading_2022-03-15-22-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-react", + "comment": "Implement svg icons loading as a web component.", + "type": "none" + } + ], + "packageName": "@itwin/core-react" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-telemetry/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/core-telemetry/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-telemetry/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/core-telemetry/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-telemetry/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/core-telemetry/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..4a285b1fe311 --- /dev/null +++ b/common/changes/@itwin/core-telemetry/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-telemetry", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-telemetry" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/2022-01-24-14-00.json b/common/changes/@itwin/core-transformer/2022-01-24-14-00.json deleted file mode 100644 index 1055799ba380..000000000000 --- a/common/changes/@itwin/core-transformer/2022-01-24-14-00.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "changes": [ - { - "changeType": 0, - "newVersion": "3.0.0", - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer", - "email": "38288322+imodeljs-admin@users.noreply.github.com" -} diff --git a/common/changes/@itwin/core-transformer/3.0.2-changelogs_2022-03-10-21-24.json b/common/changes/@itwin/core-transformer/3.0.2-changelogs_2022-03-10-21-24.json new file mode 100644 index 000000000000..8383251bc1ee --- /dev/null +++ b/common/changes/@itwin/core-transformer/3.0.2-changelogs_2022-03-10-21-24.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "", + "type": "none", + "packageName": "@itwin/core-transformer" + } + ], + "packageName": "@itwin/core-transformer", + "email": "32379572+skirby1996@users.noreply.github.com" +} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/backend-drop-hub-dep_2021-10-13-13-36.json b/common/changes/@itwin/core-transformer/backend-drop-hub-dep_2021-10-13-13-36.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/backend-drop-hub-dep_2021-10-13-13-36.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/branch-transformation-update_2022-02-03-19-15.json b/common/changes/@itwin/core-transformer/branch-transformation-update_2022-02-03-19-15.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/branch-transformation-update_2022-02-03-19-15.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/change-cpx-dependency_2021-11-16-16-35.json b/common/changes/@itwin/core-transformer/change-cpx-dependency_2021-11-16-16-35.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/change-cpx-dependency_2021-11-16-16-35.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/check-dead-predecessors_2021-12-28-12-46.json b/common/changes/@itwin/core-transformer/check-dead-predecessors_2021-12-28-12-46.json deleted file mode 100644 index 76e86f32edad..000000000000 --- a/common/changes/@itwin/core-transformer/check-dead-predecessors_2021-12-28-12-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "add ignoreDeadPredecessors option to transformer, deprecate direct importer options access", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/cleanup-buildtools_2021-09-22-00-48.json b/common/changes/@itwin/core-transformer/cleanup-buildtools_2021-09-22-00-48.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/cleanup-buildtools_2021-09-22-00-48.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/cleanup-imodeljs-refs_2021-11-30-15-21.json b/common/changes/@itwin/core-transformer/cleanup-imodeljs-refs_2021-11-30-15-21.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/cleanup-imodeljs-refs_2021-11-30-15-21.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/cleanup-rush-logs_2021-09-29-15-16.json b/common/changes/@itwin/core-transformer/cleanup-rush-logs_2021-09-29-15-16.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/cleanup-rush-logs_2021-09-29-15-16.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/dual-builds_2021-10-04-19-28.json b/common/changes/@itwin/core-transformer/dual-builds_2021-10-04-19-28.json deleted file mode 100644 index 9b6f8a51ebb8..000000000000 --- a/common/changes/@itwin/core-transformer/dual-builds_2021-10-04-19-28.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "Upgrade target to ES2019", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/entity-is-not-entityprops_2022-01-18-14-16.json b/common/changes/@itwin/core-transformer/entity-is-not-entityprops_2022-01-18-14-16.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/entity-is-not-entityprops_2022-01-18-14-16.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/fix-deps_2021-11-18-21-21.json b/common/changes/@itwin/core-transformer/fix-deps_2021-11-18-21-21.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/fix-deps_2021-11-18-21-21.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/fix-generated-class-predecessors_2022-01-10-21-46.json b/common/changes/@itwin/core-transformer/fix-generated-class-predecessors_2022-01-10-21-46.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/fix-generated-class-predecessors_2022-01-10-21-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/fix-skybox-apis-and-loading_2021-11-07-19-35.json b/common/changes/@itwin/core-transformer/fix-skybox-apis-and-loading_2021-11-07-19-35.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/fix-skybox-apis-and-loading_2021-11-07-19-35.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/frontend-drop-hub-dep_2021-09-30-12-18.json b/common/changes/@itwin/core-transformer/frontend-drop-hub-dep_2021-09-30-12-18.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/frontend-drop-hub-dep_2021-09-30-12-18.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/integration-test-client-regression-pipeline_2021-09-16-18-58.json b/common/changes/@itwin/core-transformer/integration-test-client-regression-pipeline_2021-09-16-18-58.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/integration-test-client-regression-pipeline_2021-09-16-18-58.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/itwinid_2021-09-11-14-04.json b/common/changes/@itwin/core-transformer/itwinid_2021-09-11-14-04.json deleted file mode 100644 index ae4a0e14fba4..000000000000 --- a/common/changes/@itwin/core-transformer/itwinid_2021-09-11-14-04.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "rename contextId -> iTwinId", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/maint-rushCompileOnlyCjs_2021-10-15-18-00.json b/common/changes/@itwin/core-transformer/maint-rushCompileOnlyCjs_2021-10-15-18-00.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/maint-rushCompileOnlyCjs_2021-10-15-18-00.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/master_2022-01-13-16-02.json b/common/changes/@itwin/core-transformer/master_2022-01-13-16-02.json deleted file mode 100644 index 80d2d441a4e0..000000000000 --- a/common/changes/@itwin/core-transformer/master_2022-01-13-16-02.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "changes": [ - { - "changeType": 0, - "newVersion": "3.0.0", - "packageName": "@itwin/core-transformer", - "comment": "" - } - ], - "packageName": "@itwin/core-transformer", - "email": "38288322+imodeljs-admin@users.noreply.github.com" -} diff --git a/common/changes/@itwin/core-transformer/native-3.0.18_2021-11-19-16-23.json b/common/changes/@itwin/core-transformer/native-3.0.18_2021-11-19-16-23.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/native-3.0.18_2021-11-19-16-23.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/native-3.0.7_2021-08-31-20-48.json b/common/changes/@itwin/core-transformer/native-3.0.7_2021-08-31-20-48.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/native-3.0.7_2021-08-31-20-48.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/new-package-names_2021-09-23-17-20.json b/common/changes/@itwin/core-transformer/new-package-names_2021-09-23-17-20.json deleted file mode 100644 index f55e99a5d63d..000000000000 --- a/common/changes/@itwin/core-transformer/new-package-names_2021-09-23-17-20.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "rename to @itwin/core-transformer", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/node-16_2021-09-16-16-05.json b/common/changes/@itwin/core-transformer/node-16_2021-09-16-16-05.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/node-16_2021-09-16-16-05.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/normalize-line-endings_2021-10-06-13-40.json b/common/changes/@itwin/core-transformer/normalize-line-endings_2021-10-06-13-40.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/normalize-line-endings_2021-10-06-13-40.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/patrick-AuthorizationClientRework_2021-09-25-14-31.json b/common/changes/@itwin/core-transformer/patrick-AuthorizationClientRework_2021-09-25-14-31.json deleted file mode 100644 index d8dbb61b5807..000000000000 --- a/common/changes/@itwin/core-transformer/patrick-AuthorizationClientRework_2021-09-25-14-31.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "remove ClientRequestContext and its subclasses", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/pmc-remove-deprecations_2021-09-21-14-18.json b/common/changes/@itwin/core-transformer/pmc-remove-deprecations_2021-09-21-14-18.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/pmc-remove-deprecations_2021-09-21-14-18.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/remove-deprecated-transformer-api_2021-09-20-21-24.json b/common/changes/@itwin/core-transformer/remove-deprecated-transformer-api_2021-09-20-21-24.json deleted file mode 100644 index 1ad80a98cadc..000000000000 --- a/common/changes/@itwin/core-transformer/remove-deprecated-transformer-api_2021-09-20-21-24.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "removed deprecated API surface", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/remove-itwin-client_2022-01-12-02-18.json b/common/changes/@itwin/core-transformer/remove-itwin-client_2022-01-12-02-18.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/remove-itwin-client_2022-01-12-02-18.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/requestContext-imodel02_2021-09-17-13-30.json b/common/changes/@itwin/core-transformer/requestContext-imodel02_2021-09-17-13-30.json deleted file mode 100644 index 3e3f69da084b..000000000000 --- a/common/changes/@itwin/core-transformer/requestContext-imodel02_2021-09-17-13-30.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "remove ClientRequestContext.current", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/revision0-rename_2021-11-29-13-42.json b/common/changes/@itwin/core-transformer/revision0-rename_2021-11-29-13-42.json deleted file mode 100644 index d63958bcf4a9..000000000000 --- a/common/changes/@itwin/core-transformer/revision0-rename_2021-11-29-13-42.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "Renamed all occurrences of the term revision0 to version0.", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/rework-locks_2021-09-03-17-21.json b/common/changes/@itwin/core-transformer/rework-locks_2021-09-03-17-21.json deleted file mode 100644 index c5d4077429fc..000000000000 --- a/common/changes/@itwin/core-transformer/rework-locks_2021-09-03-17-21.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "remove requestContext argument from importSchemas", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/spencer-update-requestcontext-comments_2021-10-06-19-26.json b/common/changes/@itwin/core-transformer/spencer-update-requestcontext-comments_2021-10-06-19-26.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/spencer-update-requestcontext-comments_2021-10-06-19-26.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/split-out-imodel-transformer_2021-08-19-13-03.json b/common/changes/@itwin/core-transformer/split-out-imodel-transformer_2021-08-19-13-03.json deleted file mode 100644 index fd00096aa32e..000000000000 --- a/common/changes/@itwin/core-transformer/split-out-imodel-transformer_2021-08-19-13-03.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "create new imodel-transformer package separate from backend package", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer", - "email": "MichaelBelousov@users.noreply.github.com" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/transformer-deferred-aspect-export_2022-01-05-13-56.json b/common/changes/@itwin/core-transformer/transformer-deferred-aspect-export_2022-01-05-13-56.json deleted file mode 100644 index 014f5fbf4a63..000000000000 --- a/common/changes/@itwin/core-transformer/transformer-deferred-aspect-export_2022-01-05-13-56.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "fix bug where element aspect export could be mishandled when the element was deferred", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/transformer-filter-maintain-ids_2021-12-03-14-03.json b/common/changes/@itwin/core-transformer/transformer-filter-maintain-ids_2021-12-03-14-03.json deleted file mode 100644 index be94a27f4e16..000000000000 --- a/common/changes/@itwin/core-transformer/transformer-filter-maintain-ids_2021-12-03-14-03.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "add preserveElementIdsForFiltering option for transformations", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/ts-4.4_2021-09-22-05-21.json b/common/changes/@itwin/core-transformer/ts-4.4_2021-09-22-05-21.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/ts-4.4_2021-09-22-05-21.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/update-deps_2022-01-28-15-42.json b/common/changes/@itwin/core-transformer/update-deps_2022-01-28-15-42.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/update-deps_2022-01-28-15-42.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/update-github-refs_2021-10-27-15-12.json b/common/changes/@itwin/core-transformer/update-github-refs_2021-10-27-15-12.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/update-github-refs_2021-10-27-15-12.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-transformer/update-license-year_2022-01-03-18-38.json b/common/changes/@itwin/core-transformer/update-license-year_2022-01-03-18-38.json deleted file mode 100644 index 751f0e4758f9..000000000000 --- a/common/changes/@itwin/core-transformer/update-license-year_2022-01-03-18-38.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/core-transformer", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/core-transformer" -} \ No newline at end of file diff --git a/common/changes/@itwin/core-webpack-tools/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/core-webpack-tools/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/core-webpack-tools/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/core-webpack-tools/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/core-webpack-tools/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/core-webpack-tools/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..b17782ff877e --- /dev/null +++ b/common/changes/@itwin/core-webpack-tools/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-webpack-tools", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-webpack-tools" +} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-editing/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-editing/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-editing/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-editing/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-editing/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/ecschema-editing/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index 2814f3238edc..000000000000 --- a/common/changes/@itwin/ecschema-editing/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-editing", - "comment": "Now consuming FormatType from @itwin/core-quantity package.", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-editing" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-locaters/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-locaters/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-locaters/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-locaters/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-metadata/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-metadata/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-metadata/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-metadata/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-metadata/schema-provider-updates_2022-02-18-17-24.json b/common/changes/@itwin/ecschema-metadata/kill-old-ext-api_2022-03-14-19-00.json similarity index 51% rename from common/changes/@itwin/ecschema-metadata/schema-provider-updates_2022-02-18-17-24.json rename to common/changes/@itwin/ecschema-metadata/kill-old-ext-api_2022-03-14-19-00.json index b27675868d4c..5dd8c0e532c0 100644 --- a/common/changes/@itwin/ecschema-metadata/schema-provider-updates_2022-02-18-17-24.json +++ b/common/changes/@itwin/ecschema-metadata/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/ecschema-metadata", - "comment": "Simplifying the initialization of the SchemaUnitProvider by allowing a ISchemaLocater to be passed in during construction.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/ecschema-metadata/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/ecschema-metadata/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index fa37a245d8b7..000000000000 --- a/common/changes/@itwin/ecschema-metadata/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-metadata", - "comment": "Now consuming format type definitions from @itwin/core-quantity. Implementation of the SchemaUnitProvider class to retrieve Units from EC schemas.", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-metadata" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-rpcinterface-common/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-rpcinterface-common/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-rpcinterface-common/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-rpcinterface-common/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-rpcinterface-common/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/ecschema-rpcinterface-common/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index 1e60aec7e68b..000000000000 --- a/common/changes/@itwin/ecschema-rpcinterface-common/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-rpcinterface-common", - "comment": "Minor fixes to ECSchemaRpcInterface.", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-rpcinterface-common" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-rpcinterface-impl/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-rpcinterface-impl/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-rpcinterface-impl/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-rpcinterface-impl/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-rpcinterface-impl/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/ecschema-rpcinterface-impl/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index 1ec6c2ee47e2..000000000000 --- a/common/changes/@itwin/ecschema-rpcinterface-impl/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-rpcinterface-impl", - "comment": "Minor fixes to ECSchemaRpcInterface", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-rpcinterface-impl" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-rpcinterface-tests/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema-rpcinterface-tests/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema-rpcinterface-tests/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema-rpcinterface-tests/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/ecschema-rpcinterface-tests/update-deps_2022-01-25-17-24.json b/common/changes/@itwin/ecschema-rpcinterface-tests/update-deps_2022-01-25-17-24.json deleted file mode 100644 index 097a0a761e80..000000000000 --- a/common/changes/@itwin/ecschema-rpcinterface-tests/update-deps_2022-01-25-17-24.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-rpcinterface-tests", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-rpcinterface-tests" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema-rpcinterface-tests/update-imodels-client_2022-01-18-15-46.json b/common/changes/@itwin/ecschema-rpcinterface-tests/update-imodels-client_2022-01-18-15-46.json deleted file mode 100644 index 097a0a761e80..000000000000 --- a/common/changes/@itwin/ecschema-rpcinterface-tests/update-imodels-client_2022-01-18-15-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/ecschema-rpcinterface-tests", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/ecschema-rpcinterface-tests" -} \ No newline at end of file diff --git a/common/changes/@itwin/ecschema2ts/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/ecschema2ts/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/ecschema2ts/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/ecschema2ts/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/editor-backend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/editor-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/editor-backend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/editor-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/editor-backend/fix-return-status_2022-01-20-15-05.json b/common/changes/@itwin/editor-backend/fix-return-status_2022-01-20-15-05.json deleted file mode 100644 index 08c0db4b0452..000000000000 --- a/common/changes/@itwin/editor-backend/fix-return-status_2022-01-20-15-05.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/editor-backend", - "comment": "Correct return status for processGeometryStream and createBRepGeometry.", - "type": "none" - } - ], - "packageName": "@itwin/editor-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/editor-backend/remove-element-geometry-update_2022-01-14-18-19.json b/common/changes/@itwin/editor-backend/remove-element-geometry-update_2022-01-14-18-19.json deleted file mode 100644 index ac274642e5fe..000000000000 --- a/common/changes/@itwin/editor-backend/remove-element-geometry-update_2022-01-14-18-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/editor-backend", - "comment": "Remove IModelDb.elementGeometryUpdate.", - "type": "none" - } - ], - "packageName": "@itwin/editor-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/editor-common/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/editor-common/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/editor-common/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/editor-common/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/editor-common/remove-element-geometry-update_2022-01-14-18-19.json b/common/changes/@itwin/editor-common/kill-old-ext-api_2022-03-14-19-00.json similarity index 70% rename from common/changes/@itwin/editor-common/remove-element-geometry-update_2022-01-14-18-19.json rename to common/changes/@itwin/editor-common/kill-old-ext-api_2022-03-14-19-00.json index 455c820a89ba..72655a58332c 100644 --- a/common/changes/@itwin/editor-common/remove-element-geometry-update_2022-01-14-18-19.json +++ b/common/changes/@itwin/editor-common/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/editor-common", - "comment": "Remove IModelDb.elementGeometryUpdate.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/editor-frontend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/editor-frontend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/editor-frontend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/editor-frontend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/editor-frontend/accudraw-smart-rotation_2022-01-25-13-24.json b/common/changes/@itwin/editor-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json similarity index 69% rename from common/changes/@itwin/editor-frontend/accudraw-smart-rotation_2022-01-25-13-24.json rename to common/changes/@itwin/editor-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json index f5c758725460..daa277b378d3 100644 --- a/common/changes/@itwin/editor-frontend/accudraw-smart-rotation_2022-01-25-13-24.json +++ b/common/changes/@itwin/editor-frontend/BsplineCurveClonePartial_2022-03-02-23-37.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/editor-frontend", - "comment": "Make it easier to sketch on faces of solids.", + "comment": "CurvePrimitive.clone narrowing", "type": "none" } ], diff --git a/common/changes/@itwin/editor-frontend/briefcase-active-settings_2022-03-11-11-43.json b/common/changes/@itwin/editor-frontend/briefcase-active-settings_2022-03-11-11-43.json new file mode 100644 index 000000000000..8aa55b01d270 --- /dev/null +++ b/common/changes/@itwin/editor-frontend/briefcase-active-settings_2022-03-11-11-43.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/editor-frontend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/editor-frontend" +} \ No newline at end of file diff --git a/common/changes/@itwin/editor-frontend/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/editor-frontend/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..8aa55b01d270 --- /dev/null +++ b/common/changes/@itwin/editor-frontend/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/editor-frontend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/editor-frontend" +} \ No newline at end of file diff --git a/common/changes/@itwin/editor-frontend/modify-curve-tools_2022-03-10-20-20.json b/common/changes/@itwin/editor-frontend/modify-curve-tools_2022-03-10-20-20.json new file mode 100644 index 000000000000..7752741fd519 --- /dev/null +++ b/common/changes/@itwin/editor-frontend/modify-curve-tools_2022-03-10-20-20.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/editor-frontend", + "comment": "Tools for modifying path/region geometry.", + "type": "none" + } + ], + "packageName": "@itwin/editor-frontend" +} \ No newline at end of file diff --git a/common/changes/@itwin/eslint-plugin/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/eslint-plugin/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/eslint-plugin/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/eslint-plugin/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/express-server/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/express-server/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/express-server/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/express-server/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/frontend-devtools/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/frontend-devtools/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/frontend-devtools/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/frontend-devtools/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/frontend-devtools/Bim-map-layers_2022-02-11-13-14.json b/common/changes/@itwin/frontend-devtools/Bim-map-layers_2022-02-11-13-14.json deleted file mode 100644 index 02196c42c670..000000000000 --- a/common/changes/@itwin/frontend-devtools/Bim-map-layers_2022-02-11-13-14.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/frontend-devtools", - "comment": "Added `fdt attach model maplayer` keyin.", - "type": "none" - } - ], - "packageName": "@itwin/frontend-devtools" -} \ No newline at end of file diff --git a/common/changes/@itwin/frontend-devtools/drape-support-for-reality-meshes_2022-01-20-17-09.json b/common/changes/@itwin/frontend-devtools/drape-support-for-reality-meshes_2022-01-20-17-09.json deleted file mode 100644 index 3704c5ffd7e2..000000000000 --- a/common/changes/@itwin/frontend-devtools/drape-support-for-reality-meshes_2022-01-20-17-09.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/frontend-devtools", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/frontend-devtools" -} \ No newline at end of file diff --git a/common/changes/@itwin/frontend-devtools/AttachAnyCesiumIonAssets_2022-01-26-19-24.json b/common/changes/@itwin/frontend-devtools/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/frontend-devtools/AttachAnyCesiumIonAssets_2022-01-26-19-24.json rename to common/changes/@itwin/frontend-devtools/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/frontend-devtools/recursive-geometry-summary_2022-02-03-11-31.json b/common/changes/@itwin/frontend-devtools/recursive-geometry-summary_2022-02-03-11-31.json deleted file mode 100644 index 69c3b49a1ca8..000000000000 --- a/common/changes/@itwin/frontend-devtools/recursive-geometry-summary_2022-02-03-11-31.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/frontend-devtools", - "comment": "Add an option to InspectElementTool to also summarize the geometry of each part reference.", - "type": "none" - } - ], - "packageName": "@itwin/frontend-devtools" -} \ No newline at end of file diff --git a/common/changes/@itwin/frontend-devtools/tile-user_2022-01-20-10-11.json b/common/changes/@itwin/frontend-devtools/tile-user_2022-01-20-10-11.json deleted file mode 100644 index 3704c5ffd7e2..000000000000 --- a/common/changes/@itwin/frontend-devtools/tile-user_2022-01-20-10-11.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/frontend-devtools", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/frontend-devtools" -} \ No newline at end of file diff --git a/common/changes/@itwin/geonames-extension/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/geonames-extension/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/geonames-extension/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/geonames-extension/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/geonames-extension/fix-geonames-namespace_2022-02-11-22-32.json b/common/changes/@itwin/geonames-extension/fix-geonames-namespace_2022-02-11-22-32.json deleted file mode 100644 index 2eee543f070e..000000000000 --- a/common/changes/@itwin/geonames-extension/fix-geonames-namespace_2022-02-11-22-32.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/geonames-extension", - "comment": "Fix namespace", - "type": "none" - } - ], - "packageName": "@itwin/geonames-extension" -} \ No newline at end of file diff --git a/common/changes/@itwin/hypermodeling-frontend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/hypermodeling-frontend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/hypermodeling-frontend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/hypermodeling-frontend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/hypermodeling-frontend/kill-old-ext-api_2022-03-14-19-00.json b/common/changes/@itwin/hypermodeling-frontend/kill-old-ext-api_2022-03-14-19-00.json new file mode 100644 index 000000000000..43c6ffed45ca --- /dev/null +++ b/common/changes/@itwin/hypermodeling-frontend/kill-old-ext-api_2022-03-14-19-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/hypermodeling-frontend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/hypermodeling-frontend" +} \ No newline at end of file diff --git a/common/changes/@itwin/imodel-components-react/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/imodel-components-react/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/imodel-components-react/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/imodel-components-react/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/imodel-components-react/ui-FloatingContentControl_2022-01-19-20-41.json b/common/changes/@itwin/imodel-components-react/fix-audit-errors_2022-03-22-21-26.json similarity index 80% rename from common/changes/@itwin/imodel-components-react/ui-FloatingContentControl_2022-01-19-20-41.json rename to common/changes/@itwin/imodel-components-react/fix-audit-errors_2022-03-22-21-26.json index cb4b1fb56000..98181801665f 100644 --- a/common/changes/@itwin/imodel-components-react/ui-FloatingContentControl_2022-01-19-20-41.json +++ b/common/changes/@itwin/imodel-components-react/fix-audit-errors_2022-03-22-21-26.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/imodel-components-react", - "comment": "whitespace change", + "comment": "", "type": "none" } ], "packageName": "@itwin/imodel-components-react" -} +} \ No newline at end of file diff --git a/common/changes/@itwin/imodel-components-react/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/imodel-components-react/kill-old-ext-api_2022-03-14-19-00.json similarity index 75% rename from common/changes/@itwin/imodel-components-react/vyki-itwinui-update-1_2022-01-25-19-30.json rename to common/changes/@itwin/imodel-components-react/kill-old-ext-api_2022-03-14-19-00.json index 3a6a4b616550..98181801665f 100644 --- a/common/changes/@itwin/imodel-components-react/vyki-itwinui-update-1_2022-01-25-19-30.json +++ b/common/changes/@itwin/imodel-components-react/kill-old-ext-api_2022-03-14-19-00.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/imodel-components-react", - "comment": "Update to latest itwinui-react.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/imodel-components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/imodel-components-react/pmc-validate-color-def_2022-03-15-16-52.json similarity index 72% rename from common/changes/@itwin/imodel-components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/imodel-components-react/pmc-validate-color-def_2022-03-15-16-52.json index 274dc74e712d..98181801665f 100644 --- a/common/changes/@itwin/imodel-components-react/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/imodel-components-react/pmc-validate-color-def_2022-03-15-16-52.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/imodel-components-react", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/imodel-components-react/queryUnitsSchema_2022-02-01-19-53.json b/common/changes/@itwin/imodel-components-react/queryUnitsSchema_2022-02-01-19-53.json deleted file mode 100644 index 1265620351a7..000000000000 --- a/common/changes/@itwin/imodel-components-react/queryUnitsSchema_2022-02-01-19-53.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/imodel-components-react", - "comment": "Required updates based on @itwin/core-quantity format type definition related changes.", - "type": "none" - } - ], - "packageName": "@itwin/imodel-components-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/imodel-components-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json b/common/changes/@itwin/imodel-components-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json deleted file mode 100644 index aa0bb363a3de..000000000000 --- a/common/changes/@itwin/imodel-components-react/ui-addressShowcaseViewerIssues_2022-02-02-22-01.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/imodel-components-react", - "comment": "Avoid processing stale viewstates that reference closed imodels.", - "type": "none" - } - ], - "packageName": "@itwin/imodel-components-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/imodel-components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json b/common/changes/@itwin/imodel-components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json similarity index 70% rename from common/changes/@itwin/imodel-components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json rename to common/changes/@itwin/imodel-components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json index 107e21dca630..af0342ab43a5 100644 --- a/common/changes/@itwin/imodel-components-react/ui-addDataAttributeToButtonsWidgetAndStatusFields_2022-02-03-21-04.json +++ b/common/changes/@itwin/imodel-components-react/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/imodel-components-react", - "comment": "Add pointer cursor for ColorPicker close button.", + "comment": "Update itwinui-css version", "type": "none" } ], diff --git a/common/changes/@itwin/imodel-components-react/ui-updateContextMenuToDropdownMenu_2022-02-16-15-19.json b/common/changes/@itwin/imodel-components-react/ui-updateContextMenuToDropdownMenu_2022-02-16-15-19.json deleted file mode 100644 index fcab683ad15c..000000000000 --- a/common/changes/@itwin/imodel-components-react/ui-updateContextMenuToDropdownMenu_2022-02-16-15-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/imodel-components-react", - "comment": "Replace use of Context menu in Timeline with DropdownMenu.", - "type": "none" - } - ], - "packageName": "@itwin/imodel-components-react" -} \ No newline at end of file diff --git a/common/changes/@itwin/linear-referencing-backend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/linear-referencing-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/linear-referencing-backend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/linear-referencing-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/linear-referencing-backend/reinstate-linearly-located-base-impl_2022-01-25-12-07.json b/common/changes/@itwin/linear-referencing-backend/reinstate-linearly-located-base-impl_2022-01-25-12-07.json deleted file mode 100644 index d853bb2d2d6d..000000000000 --- a/common/changes/@itwin/linear-referencing-backend/reinstate-linearly-located-base-impl_2022-01-25-12-07.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/linear-referencing-backend", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/linear-referencing-backend" -} \ No newline at end of file diff --git a/common/changes/@itwin/linear-referencing-common/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/linear-referencing-common/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/linear-referencing-common/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/linear-referencing-common/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/map-layers/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/map-layers/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/map-layers/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/map-layers/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/map-layers/Bim-map-layers_2022-02-11-13-14.json b/common/changes/@itwin/map-layers/geo-fix_ResizeObserver_2022-03-08-13-33.json similarity index 60% rename from common/changes/@itwin/map-layers/Bim-map-layers_2022-02-11-13-14.json rename to common/changes/@itwin/map-layers/geo-fix_ResizeObserver_2022-03-08-13-33.json index 583e8ef01bb2..83f01b898748 100644 --- a/common/changes/@itwin/map-layers/Bim-map-layers_2022-02-11-13-14.json +++ b/common/changes/@itwin/map-layers/geo-fix_ResizeObserver_2022-03-08-13-33.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/map-layers", - "comment": "Add support for map layers using model geometry.", + "comment": "Fix 'ResizeObserver loop limit exceeded' error in MapLayers widget", "type": "none" } ], diff --git a/common/changes/@itwin/map-layers/ui-updateToLatestItwinCss_2022-01-21-20-59.json b/common/changes/@itwin/map-layers/geo-fix_outsideclick_handling_2022-03-07-21-03.json similarity index 55% rename from common/changes/@itwin/map-layers/ui-updateToLatestItwinCss_2022-01-21-20-59.json rename to common/changes/@itwin/map-layers/geo-fix_outsideclick_handling_2022-03-07-21-03.json index d84575203c0e..b8a57807aa64 100644 --- a/common/changes/@itwin/map-layers/ui-updateToLatestItwinCss_2022-01-21-20-59.json +++ b/common/changes/@itwin/map-layers/geo-fix_outsideclick_handling_2022-03-07-21-03.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/map-layers", - "comment": "Update to itwinui-css version \"0.44.0\".", + "comment": "Fixed issue that would close the new maplayer dialog when a new layer type was picked.", "type": "none" } ], diff --git a/common/changes/@itwin/map-layers/ui-FloatingContentControl_2022-01-19-20-41.json b/common/changes/@itwin/map-layers/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json similarity index 74% rename from common/changes/@itwin/map-layers/ui-FloatingContentControl_2022-01-19-20-41.json rename to common/changes/@itwin/map-layers/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json index 72d4c0099966..12a9b5d8a6c5 100644 --- a/common/changes/@itwin/map-layers/ui-FloatingContentControl_2022-01-19-20-41.json +++ b/common/changes/@itwin/map-layers/ui-convertToItwinUiDropdownMenu_2022-03-18-14-45.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/map-layers", - "comment": "Fix style on select", + "comment": "Update itwinui-css version", "type": "none" } ], diff --git a/common/changes/@itwin/map-layers/vyki-itwinui-update-1_2022-01-25-19-30.json b/common/changes/@itwin/map-layers/vyki-itwinui-update-1_2022-01-25-19-30.json deleted file mode 100644 index b22443fe12be..000000000000 --- a/common/changes/@itwin/map-layers/vyki-itwinui-update-1_2022-01-25-19-30.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/map-layers", - "comment": "Update to latest itwinui-react - requires new compile option allowSyntheticDefaultImports=true.", - "type": "none" - } - ], - "packageName": "@itwin/map-layers" -} \ No newline at end of file diff --git a/common/changes/@itwin/perf-tools/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/perf-tools/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/perf-tools/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/perf-tools/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/perf-tools/perf-reporter-date_2022-01-26-18-39.json b/common/changes/@itwin/perf-tools/perf-reporter-date_2022-01-26-18-39.json deleted file mode 100644 index 2d8ab5925213..000000000000 --- a/common/changes/@itwin/perf-tools/perf-reporter-date_2022-01-26-18-39.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/perf-tools", - "comment": "Add ability to set the Date for a reported entry", - "type": "none" - } - ], - "packageName": "@itwin/perf-tools" -} \ No newline at end of file diff --git a/common/changes/@itwin/physical-material-backend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/physical-material-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/physical-material-backend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/physical-material-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-backend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/presentation-backend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/presentation-backend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/presentation-backend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-backend/native-3.1.1_2022-01-14-07-08.json b/common/changes/@itwin/presentation-backend/presentation-docs-learning-snippets-cleanup_2022-03-22-13-41.json similarity index 100% rename from common/changes/@itwin/presentation-backend/native-3.1.1_2022-01-14-07-08.json rename to common/changes/@itwin/presentation-backend/presentation-docs-learning-snippets-cleanup_2022-03-22-13-41.json diff --git a/common/changes/@itwin/presentation-backend/webpack5-support_2022-03-11-21-28.json b/common/changes/@itwin/presentation-backend/webpack5-support_2022-03-11-21-28.json new file mode 100644 index 000000000000..8cf278a0fc94 --- /dev/null +++ b/common/changes/@itwin/presentation-backend/webpack5-support_2022-03-11-21-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-backend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/presentation-backend" +} \ No newline at end of file diff --git a/common/changes/@itwin/presentation-common/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/presentation-common/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/presentation-common/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/presentation-common/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-common/presentation-docs-content-customization-rules_2022-01-21-14-16.json b/common/changes/@itwin/presentation-common/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/presentation-common/presentation-docs-content-customization-rules_2022-01-21-14-16.json rename to common/changes/@itwin/presentation-common/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/presentation-common/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json b/common/changes/@itwin/presentation-common/presentation-common-rule-docs_2022-03-03-11-17.json similarity index 56% rename from common/changes/@itwin/presentation-common/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json rename to common/changes/@itwin/presentation-common/presentation-common-rule-docs_2022-03-03-11-17.json index 9348725e6175..832da0bf5908 100644 --- a/common/changes/@itwin/presentation-common/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json +++ b/common/changes/@itwin/presentation-common/presentation-common-rule-docs_2022-03-03-11-17.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/presentation-common", - "comment": "Deprecate `PropertyGroupingValue`, `PropertyGroup.groupingValue` and `PropertyGroup.sortingValue`.", + "comment": "", "type": "none" } ], diff --git a/common/changes/@itwin/presentation-common/presentation-customization_docs_improvement_2022-03-09-08-13.json b/common/changes/@itwin/presentation-common/presentation-customization_docs_improvement_2022-03-09-08-13.json new file mode 100644 index 000000000000..2e7aedc8a640 --- /dev/null +++ b/common/changes/@itwin/presentation-common/presentation-customization_docs_improvement_2022-03-09-08-13.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-common", + "comment": "Deprecated StyleOverrideRule, ImageIdOverrideRule, CheckboxRule and LabelOverrideRule", + "type": "none" + } + ], + "packageName": "@itwin/presentation-common" +} \ No newline at end of file diff --git a/common/changes/@itwin/presentation-common/webpack5-support_2022-03-11-21-28.json b/common/changes/@itwin/presentation-common/webpack5-support_2022-03-11-21-28.json new file mode 100644 index 000000000000..832da0bf5908 --- /dev/null +++ b/common/changes/@itwin/presentation-common/webpack5-support_2022-03-11-21-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-common", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/presentation-common" +} \ No newline at end of file diff --git a/common/changes/@itwin/presentation-components/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/presentation-components/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/presentation-components/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/presentation-components/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-components/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json b/common/changes/@itwin/presentation-components/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/presentation-components/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json rename to common/changes/@itwin/presentation-components/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/presentation-components/presentation-customization_docs_improvement_2022-03-09-08-13.json b/common/changes/@itwin/presentation-components/presentation-customization_docs_improvement_2022-03-09-08-13.json new file mode 100644 index 000000000000..010c4cdffdb0 --- /dev/null +++ b/common/changes/@itwin/presentation-components/presentation-customization_docs_improvement_2022-03-09-08-13.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-components", + "comment": "Added ability to customize TreeNodeItems produced by PresentationTreeDataProvider", + "type": "none" + } + ], + "packageName": "@itwin/presentation-components" +} \ No newline at end of file diff --git a/common/changes/@itwin/presentation-frontend/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/presentation-frontend/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/presentation-frontend/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/presentation-frontend/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-frontend/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json b/common/changes/@itwin/presentation-frontend/kill-old-ext-api_2022-03-14-19-00.json similarity index 100% rename from common/changes/@itwin/presentation-frontend/presentation-docs-hierarchy-specifications_2022-01-24-06-40.json rename to common/changes/@itwin/presentation-frontend/kill-old-ext-api_2022-03-14-19-00.json diff --git a/common/changes/@itwin/presentation-frontend/presentation-fix_paged_request_response_2022-03-10-14-40.json b/common/changes/@itwin/presentation-frontend/presentation-fix_paged_request_response_2022-03-10-14-40.json new file mode 100644 index 000000000000..be02401a44f7 --- /dev/null +++ b/common/changes/@itwin/presentation-frontend/presentation-fix_paged_request_response_2022-03-10-14-40.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-frontend", + "comment": "Fix paged requests result accumulation resulting in infinite loop.", + "type": "none" + } + ], + "packageName": "@itwin/presentation-frontend" +} \ No newline at end of file diff --git a/common/changes/@itwin/presentation-testing/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/presentation-testing/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/presentation-testing/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/presentation-testing/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/presentation-testing/presentation-docs-learning-snippets-cleanup_2022-03-23-08-19.json b/common/changes/@itwin/presentation-testing/presentation-docs-learning-snippets-cleanup_2022-03-23-08-19.json new file mode 100644 index 000000000000..714fea3f8982 --- /dev/null +++ b/common/changes/@itwin/presentation-testing/presentation-docs-learning-snippets-cleanup_2022-03-23-08-19.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/presentation-testing", + "comment": "Add a way to reduce raw numeric values' decimal precision to overcome rounding differences across platforms", + "type": "none" + } + ], + "packageName": "@itwin/presentation-testing" +} \ No newline at end of file diff --git a/common/changes/@itwin/rpcinterface-full-stack-tests/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/rpcinterface-full-stack-tests/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/rpcinterface-full-stack-tests/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/rpcinterface-full-stack-tests/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/rpcinterface-full-stack-tests/deprecate-get-view-thumbnail_2022-02-02-18-19.json b/common/changes/@itwin/rpcinterface-full-stack-tests/deprecate-get-view-thumbnail_2022-02-02-18-19.json deleted file mode 100644 index 43c386112e51..000000000000 --- a/common/changes/@itwin/rpcinterface-full-stack-tests/deprecate-get-view-thumbnail_2022-02-02-18-19.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/rpcinterface-full-stack-tests", - "comment": "Deprecate IModelReadRpcInterface.getViewThumbnail", - "type": "none" - } - ], - "packageName": "@itwin/rpcinterface-full-stack-tests" -} \ No newline at end of file diff --git a/common/changes/@itwin/rpcinterface-full-stack-tests/update-deps_2022-01-25-17-24.json b/common/changes/@itwin/rpcinterface-full-stack-tests/reimplement-get-view-thumbnail_2022-03-07-17-37.json similarity index 100% rename from common/changes/@itwin/rpcinterface-full-stack-tests/update-deps_2022-01-25-17-24.json rename to common/changes/@itwin/rpcinterface-full-stack-tests/reimplement-get-view-thumbnail_2022-03-07-17-37.json diff --git a/common/changes/@itwin/rpcinterface-full-stack-tests/update-imodels-client_2022-01-18-15-46.json b/common/changes/@itwin/rpcinterface-full-stack-tests/update-imodels-client_2022-01-18-15-46.json deleted file mode 100644 index f4ac0f33aed4..000000000000 --- a/common/changes/@itwin/rpcinterface-full-stack-tests/update-imodels-client_2022-01-18-15-46.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@itwin/rpcinterface-full-stack-tests", - "comment": "", - "type": "none" - } - ], - "packageName": "@itwin/rpcinterface-full-stack-tests" -} \ No newline at end of file diff --git a/common/changes/@itwin/webgl-compatibility/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/webgl-compatibility/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/webgl-compatibility/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/webgl-compatibility/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/changes/@itwin/webgl-compatibility/workaround-mali-gp7-mp20-bug_2022-02-18-11-45.json b/common/changes/@itwin/webgl-compatibility/kill-old-ext-api_2022-03-14-19-00.json similarity index 54% rename from common/changes/@itwin/webgl-compatibility/workaround-mali-gp7-mp20-bug_2022-02-18-11-45.json rename to common/changes/@itwin/webgl-compatibility/kill-old-ext-api_2022-03-14-19-00.json index a726a7e69195..02a2bb6bf631 100644 --- a/common/changes/@itwin/webgl-compatibility/workaround-mali-gp7-mp20-bug_2022-02-18-11-45.json +++ b/common/changes/@itwin/webgl-compatibility/kill-old-ext-api_2022-03-14-19-00.json @@ -2,9 +2,9 @@ "changes": [ { "packageName": "@itwin/webgl-compatibility", - "comment": "Apply workaround for failure to render shadows and transparency on Mali-G71 MP20 (Samsung Galaxy Note 8).", + "comment": "", "type": "none" } ], "packageName": "@itwin/webgl-compatibility" -} +} \ No newline at end of file diff --git a/common/changes/@itwin/webgl-compatibility/report-integrated-graphics_2022-03-14-12-41.json b/common/changes/@itwin/webgl-compatibility/report-integrated-graphics_2022-03-14-12-41.json new file mode 100644 index 000000000000..357155130697 --- /dev/null +++ b/common/changes/@itwin/webgl-compatibility/report-integrated-graphics_2022-03-14-12-41.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/webgl-compatibility", + "comment": "A `usingIntegratedGraphics` property has been added to WebGLRenderCompatibilityInfo. If true, there is a likelihood that integrated graphics are being used.", + "type": "none" + } + ], + "packageName": "@itwin/webgl-compatibility" +} \ No newline at end of file diff --git a/common/changes/@itwin/workspace-editor/3.0.0-changelogs_2022-02-09-21-42.json b/common/changes/@itwin/workspace-editor/3.0.2-changelogs_2022-03-10-21-24.json similarity index 100% rename from common/changes/@itwin/workspace-editor/3.0.0-changelogs_2022-02-09-21-42.json rename to common/changes/@itwin/workspace-editor/3.0.2-changelogs_2022-03-10-21-24.json diff --git a/common/config/rush/.pnpmfile.cjs b/common/config/rush/.pnpmfile.cjs index 8bcf37263a9b..228b9991b7da 100644 --- a/common/config/rush/.pnpmfile.cjs +++ b/common/config/rush/.pnpmfile.cjs @@ -1,11 +1,19 @@ function readPackage(pkg) { - if ((pkg.name == "typedoc" || pkg.name == "@microsoft/api-extractor") && pkg.dependencies && pkg.dependencies["typescript"]) + if ( + (pkg.name == "typedoc" || pkg.name == "@microsoft/api-extractor") && + pkg.dependencies && + pkg.dependencies["typescript"] + ) { pkg.dependencies["typescript"] = "~4.4.0"; + } + // Hacky mess: For external packages to this monorepo that have peer dependencies on packages // in this repo, we need to do some magic in order to get the peerDeps to point to a correct // version of the packages. Update the pkg.json real dependency list to // Note that these dependencies are only ever allowed for testing purposes and should not be the // dependency of any published packages. + + // https://github.com/iTwin/imodels-clients else if (pkg.name == "@itwin/imodels-access-backend") { pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; pkg.dependencies["@itwin/core-backend"] = "workspace:*"; @@ -14,16 +22,29 @@ function readPackage(pkg) { pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; pkg.dependencies["@itwin/core-frontend"] = "workspace:*"; pkg.dependencies["@itwin/core-common"] = "workspace:*"; - } else if (pkg.name == "@itwin/oidc-signin-tool") { + } + + // https://github.com/iTwin/auth-clients + else if (pkg.name == "@itwin/browser-authorization") { pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; } else if (pkg.name == "@itwin/electron-authorization") { pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; + } else if (pkg.name == "@itwin/oidc-signin-tool") { + pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; } + + // https://github.com/iTwin/reality-data-client + else if (pkg.name == "@itwin/reality-data-client") { + pkg.dependencies["@itwin/core-bentley"] = "workspace:*"; + pkg.dependencies["@itwin/core-common"] = "workspace:*"; + pkg.dependencies["@itwin/core-geometry"] = "workspace:*"; + } + return pkg; } module.exports = { hooks: { - readPackage - } -} + readPackage, + }, +}; diff --git a/common/config/rush/browser-approved-packages.json b/common/config/rush/browser-approved-packages.json index 1747819f5280..88714bdba02f 100644 --- a/common/config/rush/browser-approved-packages.json +++ b/common/config/rush/browser-approved-packages.json @@ -82,6 +82,10 @@ "name": "@itwin/core-electron", "allowedCategories": [ "internal" ] }, + { + "name": "@itwin/core-extension", + "allowedCategories": [ "internal" ] + }, { "name": "@itwin/core-frontend", "allowedCategories": [ "backend", "common", "edit", "extensions", "frontend", "integration-testing", "internal", "tools" ] @@ -198,6 +202,10 @@ "name": "@itwin/itwinui-css", "allowedCategories": [ "extensions", "frontend", "internal" ] }, + { + "name": "@itwin/itwinui-icons-react", + "allowedCategories": [ "internal" ] + }, { "name": "@itwin/itwinui-react", "allowedCategories": [ "extensions", "frontend", "internal" ] @@ -284,7 +292,7 @@ }, { "name": "@testing-library/react", - "allowedCategories": [ "extensions", "frontend" ] + "allowedCategories": [ "extensions", "frontend", "internal" ] }, { "name": "@testing-library/react-hooks", @@ -306,10 +314,6 @@ "name": "@typescript-eslint/typescript-estree", "allowedCategories": [ "tools" ] }, - { - "name": "@ungap/url-search-params", - "allowedCategories": [ "common" ] - }, { "name": "@wojtekmaj/enzyme-adapter-react-17", "allowedCategories": [ "extensions", "frontend" ] @@ -342,6 +346,10 @@ "name": "body-parser", "allowedCategories": [ "internal" ] }, + { + "name": "buffer", + "allowedCategories": [ "common", "internal" ] + }, { "name": "cache-require-paths", "allowedCategories": [ "internal" ] @@ -458,6 +466,10 @@ "name": "enzyme-to-json", "allowedCategories": [ "extensions", "frontend" ] }, + { + "name": "esbuild", + "allowedCategories": [ "internal" ] + }, { "name": "eslint", "allowedCategories": [ "backend", "common", "edit", "extensions", "frontend", "integration-testing", "internal", "tools" ] @@ -780,7 +792,7 @@ }, { "name": "react-resize-detector", - "allowedCategories": [ "extensions", "internal" ] + "allowedCategories": [ "internal" ] }, { "name": "react-select", @@ -862,6 +874,10 @@ "name": "spdy", "allowedCategories": [ "internal" ] }, + { + "name": "string_decoder", + "allowedCategories": [ "common" ] + }, { "name": "superagent", "allowedCategories": [ "backend", "common", "frontend" ] @@ -906,6 +922,10 @@ "name": "typescript-json-schema", "allowedCategories": [ "common" ] }, + { + "name": "url", + "allowedCategories": [ "internal" ] + }, { "name": "username", "allowedCategories": [ "backend" ] diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 1f7903efca73..78aa885f82c8 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -46,7 +46,7 @@ importers: superagent: ^7.0.1 typescript: ~4.4.0 dependencies: - agentkeepalive: 4.2.0 + agentkeepalive: 4.2.1 deep-assign: 2.0.0 fs-write-stream-atomic: 1.0.10 got: 11.8.3 @@ -68,7 +68,7 @@ importers: '@types/deep-assign': 0.1.1 '@types/fs-extra': 4.0.12 '@types/jsonwebtoken': 8.5.8 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 '@types/proper-lockfile': 4.1.2 @@ -89,7 +89,7 @@ importers: ../../core/backend: specifiers: '@azure/storage-blob': ^12.7.0 - '@bentley/imodeljs-native': 3.1.6 + '@bentley/imodeljs-native': 3.2.1 '@itwin/build-tools': workspace:* '@itwin/core-bentley': workspace:* '@itwin/core-common': workspace:* @@ -126,13 +126,13 @@ importers: typescript: ~4.4.0 ws: ^7.5.3 dependencies: - '@azure/storage-blob': 12.8.0 - '@bentley/imodeljs-native': 3.1.6 + '@azure/storage-blob': 12.9.0 + '@bentley/imodeljs-native': 3.2.1 '@itwin/core-telemetry': link:../telemetry form-data: 2.5.1 fs-extra: 8.1.0 js-base64: 3.7.2 - json5: 2.2.0 + json5: 2.2.1 multiparty: 4.2.3 semver: 5.7.1 ws: 7.5.7 @@ -206,7 +206,7 @@ importers: '@types/mocha': ^8.2.2 '@types/node': 14.14.31 '@types/semver': ^5.5.0 - '@ungap/url-search-params': ^0.1.2 + buffer: ^6.0.3 chai: ^4.1.2 eslint: ^7.11.0 flatbuffers: ~1.12.0 @@ -215,12 +215,14 @@ importers: nyc: ^15.1.0 rimraf: ^3.0.2 semver: ^5.5.0 + string_decoder: ^1.3.0 typescript: ~4.4.0 dependencies: - '@ungap/url-search-params': 0.1.4 + buffer: 6.0.3 flatbuffers: 1.12.0 js-base64: 3.7.2 semver: 5.7.1 + string_decoder: 1.3.0 devDependencies: '@itwin/build-tools': link:../../tools/build '@itwin/core-bentley': link:../bentley @@ -466,7 +468,7 @@ importers: '@itwin/eslint-plugin': link:../../tools/eslint-plugin '@itwin/presentation-common': link:../../presentation/common '@types/node': 14.14.31 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 rimraf: 3.0.2 typescript: 4.4.4 @@ -510,7 +512,7 @@ importers: '@types/mocha': 8.2.3 '@types/node': 14.14.31 '@types/sinon': 9.0.11 - '@types/supertest': 2.0.11 + '@types/supertest': 2.0.12 chai: 4.3.6 eslint: 7.32.0 mocha: 8.4.0 @@ -520,6 +522,23 @@ importers: supertest: 3.4.2 typescript: 4.4.4 + ../../core/extension: + specifiers: + '@itwin/build-tools': workspace:* + '@itwin/core-common': workspace:* + '@itwin/core-frontend': workspace:* + '@itwin/eslint-plugin': workspace:* + eslint: ^7.11.0 + rimraf: ^3.0.2 + dependencies: + '@itwin/core-common': link:../common + '@itwin/core-frontend': link:../frontend + devDependencies: + '@itwin/build-tools': link:../../tools/build + '@itwin/eslint-plugin': link:../../tools/eslint-plugin + eslint: 7.32.0 + rimraf: 3.0.2 + ../../core/frontend: specifiers: '@itwin/appui-abstract': workspace:* @@ -593,7 +612,7 @@ importers: '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 '@types/deep-assign': 0.1.1 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 '@types/qs': 6.9.7 @@ -745,9 +764,9 @@ importers: rimraf: ^3.0.2 typescript: ~4.4.0 dependencies: - i18next: 21.6.11 + i18next: 21.6.14 i18next-browser-languagedetector: 6.1.3 - i18next-http-backend: 1.3.2 + i18next-http-backend: 1.4.0 i18next-xhr-backend: 3.2.2 devDependencies: '@itwin/build-tools': link:../../tools/build @@ -858,7 +877,7 @@ importers: '@types/chai': 4.3.0 '@types/deep-assign': 0.1.1 '@types/fs-extra': 4.0.12 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 '@types/qs': 6.9.7 @@ -1327,11 +1346,11 @@ importers: '@itwin/core-electron': link:../../core/electron '@itwin/core-frontend': link:../../core/frontend '@itwin/core-geometry': link:../../core/geometry - electron: 14.2.6 + electron: 14.2.7 devDependencies: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@itwin/oidc-signin-tool': 3.2.2_electron@14.2.6 + '@itwin/oidc-signin-tool': 3.3.0_electron@14.2.7 '@types/chai': 4.3.0 '@types/mocha': 8.2.3 '@types/node': 14.14.31 @@ -1376,12 +1395,12 @@ importers: '@itwin/core-geometry': link:../../core/geometry '@itwin/core-transformer': link:../../core/transformer '@itwin/projects-client': 0.6.0 - '@itwin/service-authorization': 0.6.1 + '@itwin/service-authorization': 0.6.2 fs-extra: 8.1.0 devDependencies: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@itwin/oidc-signin-tool': 3.2.2 + '@itwin/oidc-signin-tool': 3.3.0 '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 '@types/fs-extra': 4.0.12 @@ -1437,8 +1456,8 @@ importers: '@itwin/core-react': workspace:* '@itwin/eslint-plugin': workspace:* '@itwin/imodel-components-react': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@itwin/presentation-common': workspace:* '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 @@ -1466,7 +1485,6 @@ importers: nyc: ^15.1.0 react: ^17.0.0 react-beautiful-dnd: ^13.0.0 - react-resize-detector: ^6.7.6 rimraf: ^3.0.2 sinon: ^9.0.2 sinon-chai: ^3.2.0 @@ -1475,7 +1493,6 @@ importers: dependencies: classnames: 2.3.1 react-beautiful-dnd: 13.1.0_react@17.0.2 - react-resize-detector: 6.7.8_react@17.0.2 devDependencies: '@itwin/appui-abstract': link:../../ui/appui-abstract '@itwin/appui-layout-react': link:../../ui/appui-layout-react @@ -1490,16 +1507,16 @@ importers: '@itwin/core-react': link:../../ui/core-react '@itwin/eslint-plugin': link:../../tools/eslint-plugin '@itwin/imodel-components-react': link:../../ui/imodel-components-react - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react@17.0.2 '@itwin/presentation-common': link:../../presentation/common - '@testing-library/react': 12.1.3_react@17.0.2 + '@testing-library/react': 12.1.4_react@17.0.2 '@testing-library/react-hooks': 7.0.2_react@17.0.2 '@types/chai': 4.3.0 '@types/enzyme': 3.9.3 '@types/mocha': 8.2.3 '@types/node': 14.14.31 - '@types/react': 17.0.39 + '@types/react': 17.0.41 '@types/react-beautiful-dnd': 12.1.5 '@types/sinon': 9.0.11 '@types/sinon-chai': 3.2.8 @@ -1523,10 +1540,33 @@ importers: typemoq: 2.1.0 typescript: 4.4.4 + ../../extensions/test-extension: + specifiers: + '@itwin/build-tools': workspace:* + '@itwin/core-extension': workspace:* + '@itwin/eslint-plugin': workspace:* + buffer: ^6.0.3 + esbuild: ^0.13.8 + eslint: ^7.11.0 + rimraf: ^3.0.2 + typescript: ~4.4.0 + url: ^0.11.0 + dependencies: + '@itwin/core-extension': link:../../core/extension + buffer: 6.0.3 + url: 0.11.0 + devDependencies: + '@itwin/build-tools': link:../../tools/build + '@itwin/eslint-plugin': link:../../tools/eslint-plugin + esbuild: 0.13.15 + eslint: 7.32.0 + rimraf: 3.0.2 + typescript: 4.4.4 + ../../full-stack-tests/backend: specifiers: '@azure/storage-blob': ^12.7.0 - '@bentley/imodeljs-native': 3.1.6 + '@bentley/imodeljs-native': 3.2.1 '@itwin/build-tools': workspace:* '@itwin/core-backend': workspace:* '@itwin/core-bentley': workspace:* @@ -1559,8 +1599,8 @@ importers: rimraf: ^3.0.2 typescript: ~4.4.0 dependencies: - '@azure/storage-blob': 12.8.0 - '@bentley/imodeljs-native': 3.1.6 + '@azure/storage-blob': 12.9.0 + '@bentley/imodeljs-native': 3.2.1 '@itwin/core-backend': link:../../core/backend '@itwin/core-bentley': link:../../core/bentley '@itwin/core-common': link:../../core/common @@ -1568,10 +1608,10 @@ importers: '@itwin/ecschema-metadata': link:../../core/ecschema-metadata '@itwin/imodels-access-backend': 1.0.1 '@itwin/imodels-client-authoring': 1.0.1 - '@itwin/oidc-signin-tool': 3.2.2 + '@itwin/oidc-signin-tool': 3.3.0 '@itwin/perf-tools': link:../../tools/perf-tools '@itwin/projects-client': 0.6.0 - azurite: 3.15.0 + azurite: 3.16.0 chai: 4.3.6 chai-as-promised: 7.1.1_chai@4.3.6 cpx2: 3.0.2 @@ -1623,7 +1663,7 @@ importers: '@itwin/imodels-client-management': ^1.0.1 '@itwin/oidc-signin-tool': ^3.2.2 '@itwin/projects-client': ^0.6.0 - '@itwin/reality-data-client': ^0.7.0 + '@itwin/reality-data-client': 0.7.0 '@types/chai': ^4.1.4 '@types/chai-as-promised': ^7 '@types/fs-extra': ^4.0.7 @@ -1674,13 +1714,13 @@ importers: '@itwin/reality-data-client': 0.7.0 chai: 4.3.6 chai-as-promised: 7.1.1_chai@4.3.6 - electron: 14.2.6 + electron: 14.2.7 fs-extra: 8.1.0 devDependencies: '@itwin/build-tools': link:../../tools/build '@itwin/certa': link:../../tools/certa '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@itwin/oidc-signin-tool': 3.2.2_electron@14.2.6 + '@itwin/oidc-signin-tool': 3.3.0_electron@14.2.7 '@itwin/projects-client': 0.6.0 '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 @@ -1759,7 +1799,7 @@ importers: '@itwin/imodels-access-backend': 1.0.1 '@itwin/imodels-access-frontend': 1.0.1 '@itwin/imodels-client-management': 1.0.1 - '@itwin/oidc-signin-tool': 3.2.2 + '@itwin/oidc-signin-tool': 3.3.0 '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-frontend': link:../../presentation/frontend chai: 4.3.6 @@ -1810,6 +1850,7 @@ importers: '@itwin/presentation-components': workspace:* '@itwin/presentation-frontend': workspace:* '@itwin/presentation-testing': workspace:* + '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 '@types/chai': ^4.1.4 '@types/chai-as-promised': ^7 @@ -1863,12 +1904,13 @@ importers: '@itwin/core-i18n': link:../../core/i18n '@itwin/core-quantity': link:../../core/quantity '@itwin/core-react': link:../../ui/core-react - '@itwin/oidc-signin-tool': 3.2.2 + '@itwin/oidc-signin-tool': 3.3.0 '@itwin/presentation-backend': link:../../presentation/backend '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-components': link:../../presentation/components '@itwin/presentation-frontend': link:../../presentation/frontend '@itwin/presentation-testing': link:../../presentation/testing + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 @@ -1889,7 +1931,7 @@ importers: cpx2: 3.0.2 deep-equal: 1.1.1 faker: 4.1.0 - fast-sort: 3.1.1 + fast-sort: 3.1.3 immer: 9.0.6 mocha: 8.4.0 react: 17.0.2 @@ -1902,8 +1944,8 @@ importers: devDependencies: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 cache-require-paths: 0.3.0 cross-env: 5.2.1 dotenv: 10.0.0 @@ -1954,7 +1996,7 @@ importers: '@itwin/core-frontend': link:../../core/frontend '@itwin/core-mobile': link:../../core/mobile '@itwin/express-server': link:../../core/express-server - electron: 14.2.6 + electron: 14.2.7 express: 4.17.3 semver: 5.7.1 spdy: 4.0.2 @@ -2035,10 +2077,10 @@ importers: '@itwin/imodels-access-frontend': 1.0.1 '@itwin/imodels-client-authoring': 1.0.1 '@itwin/imodels-client-management': 1.0.1 - '@itwin/oidc-signin-tool': 3.2.2 + '@itwin/oidc-signin-tool': 3.3.0 '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-frontend': link:../../presentation/frontend - '@itwin/service-authorization': 0.6.1 + '@itwin/service-authorization': 0.6.2 chai: 4.3.6 chai-as-promised: 7.1.1_chai@4.3.6 dotenv: 10.0.0 @@ -2279,7 +2321,7 @@ importers: xmlhttprequest: ^1.8.0 dependencies: fast-deep-equal: 3.1.3 - fast-sort: 3.1.1 + fast-sort: 3.1.3 micro-memoize: 4.0.9 rxjs: 6.6.7 devDependencies: @@ -2295,7 +2337,7 @@ importers: '@itwin/imodel-components-react': link:../../ui/imodel-components-react '@itwin/presentation-common': link:../common '@itwin/presentation-frontend': link:../frontend - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 @@ -2304,8 +2346,8 @@ importers: '@types/enzyme': 3.9.3 '@types/faker': 4.1.12 '@types/mocha': 8.2.3 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/sinon': 9.0.11 '@types/sinon-chai': 3.2.8 '@wojtekmaj/enzyme-adapter-react-17': 0.6.6_fae758709a8810ba97b4c03852dde4d0 @@ -2509,13 +2551,13 @@ importers: '@itwin/imodels-access-frontend': ^1.0.1 '@itwin/imodels-client-authoring': ^1.0.1 '@itwin/perf-tools': workspace:* - '@itwin/reality-data-client': ^0.7.0 + '@itwin/reality-data-client': 0.7.0 '@types/body-parser': ^1.17.0 '@types/express': ^4.16.1 '@types/node': 14.14.31 body-parser: ^1.18.2 child_process: ^1.0.2 - chrome-launcher: ^0.10.5 + chrome-launcher: ^0.15.0 cpx2: ^3.0.0 cross-env: ^5.1.4 dotenv: ^10.0.0 @@ -2556,12 +2598,12 @@ importers: '@types/express': 4.17.13 '@types/node': 14.14.31 child_process: 1.0.2 - chrome-launcher: 0.10.7 + chrome-launcher: 0.15.0 cpx2: 3.0.2 cross-env: 5.2.1 dotenv: 10.0.0 dotenv-expand: 5.1.0 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 express: 4.17.3 internal-tools: link:../../tools/internal @@ -2601,7 +2643,7 @@ importers: '@itwin/imodels-access-backend': ^1.0.1 '@itwin/imodels-access-frontend': ^1.0.1 '@itwin/imodels-client-authoring': ^1.0.1 - '@itwin/reality-data-client': ^0.7.0 + '@itwin/reality-data-client': 0.7.0 '@itwin/webgl-compatibility': workspace:* '@types/express': ^4.16.1 '@types/express-ws': ^3.0.1 @@ -2665,7 +2707,7 @@ importers: cross-env: 5.2.1 dotenv: 10.0.0 dotenv-expand: 5.1.0 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 express: 4.17.3 express-ws: 5.0.2_express@4.17.3 @@ -2772,7 +2814,7 @@ importers: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin '@types/fs-extra': 4.0.12 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/node': 14.14.31 '@types/yargs': 12.0.20 eslint: 7.32.0 @@ -2840,7 +2882,7 @@ importers: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin '@types/fs-extra': 4.0.12 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/node': 14.14.31 '@types/yargs': 12.0.20 eslint: 7.32.0 @@ -2901,7 +2943,7 @@ importers: '@types/node': 14.14.31 '@types/yargs': 12.0.20 cross-env: 5.2.1 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 internal-tools: link:../../tools/internal mocha: 8.4.0 @@ -2927,8 +2969,8 @@ importers: '@itwin/eslint-plugin': workspace:* '@itwin/express-server': workspace:* '@itwin/imodel-components-react': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@itwin/presentation-backend': workspace:* '@itwin/presentation-common': workspace:* '@itwin/presentation-components': workspace:* @@ -2971,8 +3013,8 @@ importers: '@itwin/electron-authorization': 0.8.3 '@itwin/express-server': link:../../core/express-server '@itwin/imodel-components-react': link:../../ui/imodel-components-react - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 '@itwin/presentation-backend': link:../../presentation/backend '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-components': link:../../presentation/components @@ -2987,15 +3029,15 @@ importers: '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin '@types/bunyan': 1.8.8 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/react-select': 3.0.26 autoprefixer: 8.6.5 cpx2: 3.0.2 cross-env: 5.2.1 dotenv: 10.0.0 dotenv-expand: 5.1.0 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 internal-tools: link:../../tools/internal npm-run-all: 4.1.5 @@ -3020,8 +3062,8 @@ importers: '@itwin/core-quantity': workspace:* '@itwin/core-react': workspace:* '@itwin/eslint-plugin': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@itwin/presentation-common': workspace:* '@itwin/presentation-components': workspace:* '@itwin/presentation-frontend': workspace:* @@ -3048,12 +3090,12 @@ importers: '@itwin/core-geometry': link:../../core/geometry '@itwin/core-quantity': link:../../core/quantity '@itwin/core-react': link:../../ui/core-react - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-components': link:../../presentation/components '@itwin/presentation-frontend': link:../../presentation/frontend - '@reduxjs/toolkit': 1.7.2_react-redux@7.2.6+react@17.0.2 + '@reduxjs/toolkit': 1.8.0_react-redux@7.2.6+react@17.0.2 classnames: 2.3.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -3063,7 +3105,7 @@ importers: '@bentley/react-scripts': 4.0.3_react@17.0.2+typescript@4.4.4 '@itwin/build-tools': link:../../tools/build '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@types/react': 17.0.39 + '@types/react': 17.0.41 '@types/react-select': 3.0.26 cpx2: 3.0.2 eslint: 7.32.0 @@ -3109,15 +3151,16 @@ importers: '@itwin/imodels-access-frontend': ^1.0.1 '@itwin/imodels-client-authoring': ^1.0.1 '@itwin/imodels-client-management': ^1.0.1 - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-icons-react': ^1.8.0 + '@itwin/itwinui-react': ^1.32.0 '@itwin/map-layers': workspace:* '@itwin/presentation-backend': workspace:* '@itwin/presentation-common': workspace:* '@itwin/presentation-components': workspace:* '@itwin/presentation-frontend': workspace:* '@itwin/projects-client': ^0.6.0 - '@itwin/reality-data-client': ^0.7.0 + '@itwin/reality-data-client': 0.7.0 '@itwin/ui-items-providers-test': workspace:* '@types/lorem-ipsum': ^1.0.2 '@types/node': 14.14.31 @@ -3184,8 +3227,9 @@ importers: '@itwin/imodels-access-frontend': 1.0.1 '@itwin/imodels-client-authoring': 1.0.1 '@itwin/imodels-client-management': 1.0.1 - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-icons-react': 1.8.0_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 '@itwin/map-layers': link:../../extensions/map-layers '@itwin/presentation-backend': link:../../presentation/backend '@itwin/presentation-common': link:../../presentation/common @@ -3213,17 +3257,17 @@ importers: '@itwin/projects-client': 0.6.0 '@types/lorem-ipsum': 1.0.2 '@types/node': 14.14.31 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 - '@types/react-redux': 7.1.22 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 + '@types/react-redux': 7.1.23 '@types/react-select': 3.0.26 - '@types/react-table': 7.7.9 + '@types/react-table': 7.7.10 '@types/semver': 5.5.0 cpx2: 3.0.2 cross-env: 5.2.1 dotenv: 10.0.0 dotenv-expand: 5.1.0 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 fs-extra: 8.1.0 internal-tools: link:../../tools/internal @@ -3299,8 +3343,8 @@ importers: recursive-readdir: 2.2.2 rimraf: 3.0.2 tree-kill: 1.2.2 - typedoc: 0.22.11_typescript@4.4.4 - typedoc-plugin-merge-modules: 3.1.0_typedoc@0.22.11 + typedoc: 0.22.13_typescript@4.4.4 + typedoc-plugin-merge-modules: 3.1.0_typedoc@0.22.13 typescript: 4.4.4 wtfnode: 0.9.1 yargs: 16.2.0 @@ -3352,13 +3396,13 @@ importers: '@types/chai': 4.3.0 '@types/detect-port': 1.1.0 '@types/express': 4.17.13 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 '@types/puppeteer': 2.0.1 '@types/uuid': 7.0.5 '@types/yargs': 12.0.20 - electron: 14.2.6 + electron: 14.2.7 eslint: 7.32.0 nyc: 15.1.0 rimraf: 3.0.2 @@ -3634,8 +3678,8 @@ importers: '@itwin/core-bentley': workspace:* '@itwin/core-react': workspace:* '@itwin/eslint-plugin': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 '@types/chai': ^4.1.4 @@ -3674,8 +3718,8 @@ importers: typescript: ~4.4.0 uuid: ^7.0.3 dependencies: - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 classnames: 2.3.1 immer: 9.0.6 uuid: 7.0.3 @@ -3685,7 +3729,7 @@ importers: '@itwin/core-bentley': link:../../core/bentley '@itwin/core-react': link:../core-react '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_react-dom@17.0.2+react@17.0.2 '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 @@ -3693,8 +3737,8 @@ importers: '@types/chai-spies': 1.0.3 '@types/enzyme': 3.9.3 '@types/mocha': 8.2.3 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/sinon': 9.0.11 '@types/uuid': 7.0.5 '@wojtekmaj/enzyme-adapter-react-17': 0.6.6_fae758709a8810ba97b4c03852dde4d0 @@ -3738,8 +3782,8 @@ importers: '@itwin/core-telemetry': workspace:* '@itwin/eslint-plugin': workspace:* '@itwin/imodel-components-react': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@itwin/presentation-common': workspace:* '@itwin/presentation-components': workspace:* '@itwin/presentation-frontend': workspace:* @@ -3800,8 +3844,8 @@ importers: '@bentley/icons-generic': 1.0.34 '@bentley/icons-generic-webfont': 1.0.34 '@itwin/core-telemetry': link:../../core/telemetry - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 '@itwin/presentation-components': link:../../presentation/components classnames: 2.3.1 immer: 9.0.6 @@ -3826,7 +3870,7 @@ importers: '@itwin/presentation-common': link:../../presentation/common '@itwin/presentation-frontend': link:../../presentation/frontend '@itwin/presentation-testing': link:../../presentation/testing - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d '@types/chai': 4.3.0 '@types/chai-as-promised': 7.1.5 @@ -3834,12 +3878,12 @@ importers: '@types/chai-spies': 1.0.3 '@types/enzyme': 3.9.3 '@types/faker': 4.1.12 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 - '@types/react-redux': 7.1.22 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 + '@types/react-redux': 7.1.23 '@types/rimraf': 2.0.5 '@types/sinon': 9.0.11 '@types/sinon-chai': 3.2.8 @@ -3883,8 +3927,8 @@ importers: '@itwin/core-i18n': workspace:* '@itwin/core-react': workspace:* '@itwin/eslint-plugin': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 '@testing-library/user-event': ^13.2.1 @@ -3954,8 +3998,8 @@ importers: xmlhttprequest: ^1.8.0 dependencies: '@bentley/icons-generic-webfont': 1.0.34 - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 '@types/shortid': 0.0.29 callable-instance2: 1.0.0 classnames: 2.3.1 @@ -3973,7 +4017,7 @@ importers: react-window: 1.8.6_react-dom@17.0.2+react@17.0.2 rxjs: 6.6.7 shortid: 2.2.16 - ts-key-enum: 2.0.10 + ts-key-enum: 2.0.11 devDependencies: '@itwin/appui-abstract': link:../appui-abstract '@itwin/build-tools': link:../../tools/build @@ -3982,7 +4026,7 @@ importers: '@itwin/core-i18n': link:../../core/i18n '@itwin/core-react': link:../core-react '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_react-dom@17.0.2+react@17.0.2 '@testing-library/user-event': 13.5.0 '@types/chai': 4.3.0 @@ -3993,11 +4037,11 @@ importers: '@types/enzyme': 3.9.3 '@types/faker': 4.1.12 '@types/linkify-it': 2.1.0 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 - '@types/react': 17.0.39 + '@types/react': 17.0.41 '@types/react-data-grid': 4.0.2 - '@types/react-dom': 17.0.11 + '@types/react-dom': 17.0.14 '@types/react-highlight-words': 0.16.4 '@types/react-select': 3.0.26 '@types/react-window': 1.8.5 @@ -4041,8 +4085,8 @@ importers: '@itwin/core-common': workspace:* '@itwin/core-i18n': workspace:* '@itwin/eslint-plugin': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 '@testing-library/user-event': ^13.2.1 @@ -4095,8 +4139,8 @@ importers: xmlhttprequest: ^1.8.0 dependencies: '@bentley/icons-generic-webfont': 1.0.34 - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 classnames: 2.3.1 dompurify: 2.3.6 lodash: 4.17.21 @@ -4110,7 +4154,7 @@ importers: '@itwin/core-common': link:../../core/common '@itwin/core-i18n': link:../../core/i18n '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d '@testing-library/user-event': 13.5.0 '@types/chai': 4.3.0 @@ -4119,12 +4163,12 @@ importers: '@types/chai-spies': 1.0.3 '@types/dompurify': 2.3.3 '@types/enzyme': 3.9.3 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 '@types/node': 14.14.31 - '@types/react': 17.0.39 + '@types/react': 17.0.41 '@types/react-autosuggest': 10.1.2 - '@types/react-dom': 17.0.11 + '@types/react-dom': 17.0.14 '@types/react-select': 3.0.26 '@types/sinon': 9.0.11 '@types/sinon-chai': 3.2.8 @@ -4168,8 +4212,8 @@ importers: '@itwin/core-quantity': workspace:* '@itwin/core-react': workspace:* '@itwin/eslint-plugin': workspace:* - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3 + '@itwin/itwinui-css': 0.x + '@itwin/itwinui-react': ^1.32.0 '@testing-library/react': ^12.0.0 '@testing-library/react-hooks': ^7.0.2 '@testing-library/user-event': ^13.2.1 @@ -4221,14 +4265,14 @@ importers: xmlhttprequest: ^1.8.0 dependencies: '@bentley/icons-generic-webfont': 1.0.34 - '@itwin/itwinui-css': 0.44.1 - '@itwin/itwinui-react': 1.29.3_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-css': 0.52.0 + '@itwin/itwinui-react': 1.34.0_react-dom@17.0.2+react@17.0.2 callable-instance2: 1.0.0 classnames: 2.3.1 eventemitter2: 5.0.1 immer: 9.0.6 immutable: 3.8.2 - ts-key-enum: 2.0.10 + ts-key-enum: 2.0.11 devDependencies: '@itwin/appui-abstract': link:../appui-abstract '@itwin/build-tools': link:../../tools/build @@ -4240,7 +4284,7 @@ importers: '@itwin/core-quantity': link:../../core/quantity '@itwin/core-react': link:../core-react '@itwin/eslint-plugin': link:../../tools/eslint-plugin - '@testing-library/react': 12.1.3_react-dom@17.0.2+react@17.0.2 + '@testing-library/react': 12.1.4_react-dom@17.0.2+react@17.0.2 '@testing-library/react-hooks': 7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d '@testing-library/user-event': 13.5.0 '@types/chai': 4.3.0 @@ -4250,10 +4294,10 @@ importers: '@types/chai-string': 1.4.2 '@types/enzyme': 3.9.3 '@types/faker': 4.1.12 - '@types/lodash': 4.14.178 + '@types/lodash': 4.14.180 '@types/mocha': 8.2.3 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/sinon': 9.0.11 '@types/sinon-chai': 3.2.8 '@wojtekmaj/enzyme-adapter-react-17': 0.6.6_fae758709a8810ba97b4c03852dde4d0 @@ -4361,7 +4405,7 @@ packages: '@azure/abort-controller': 1.0.4 '@azure/core-asynciterator-polyfill': 1.0.2 '@azure/core-auth': 1.3.2 - '@azure/core-rest-pipeline': 1.5.0 + '@azure/core-rest-pipeline': 1.7.0 '@azure/core-tracing': 1.0.0-preview.13 '@azure/logger': 1.0.3 tslib: 2.3.1 @@ -4392,8 +4436,8 @@ packages: - encoding dev: false - /@azure/core-lro/2.2.3: - resolution: {integrity: sha512-UMdlR9NsqDCLTba3EUbRjfMF4gDmWvld196JmUjbz9WWhJ2XT00OR5MXeWiR+vmGT+ETiO4hHFCi2/eGO5YVtg==} + /@azure/core-lro/2.2.4: + resolution: {integrity: sha512-e1I2v2CZM0mQo8+RSix0x091Av493e4bnT22ds2fcQGslTHzM2oTbswkB65nP4iEpCxBrFxOSDPKExmTmjCVtQ==} engines: {node: '>=12.0.0'} dependencies: '@azure/abort-controller': 1.0.4 @@ -4410,8 +4454,8 @@ packages: tslib: 2.3.1 dev: false - /@azure/core-rest-pipeline/1.5.0: - resolution: {integrity: sha512-Lofjl3mu1TULhjxoPKY4IqXt6mC8Q+r3xMF1dOz0D/aElKfrbqtO2fts36PCClAq+DJzQM/kbnrNTf3X601I5w==} + /@azure/core-rest-pipeline/1.7.0: + resolution: {integrity: sha512-e2awPzwMKHrmvYgZ0qIKNkqnCM1QoDs7A0rOiS3OSAlOQOz/kL7PPKHXwFMuBeaRvS8i7fgobJn79q2Cji5f+Q==} engines: {node: '>=12.0.0'} dependencies: '@azure/abort-controller': 1.0.4 @@ -4431,7 +4475,7 @@ packages: resolution: {integrity: sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ==} engines: {node: '>=12.0.0'} dependencies: - '@opentelemetry/api': 1.0.4 + '@opentelemetry/api': 1.1.0 tslib: 2.3.1 dev: false @@ -4442,20 +4486,20 @@ packages: tslib: 2.3.1 dev: false - /@azure/identity/2.0.3: - resolution: {integrity: sha512-MFW2QS5dWm2U8MDTSm0sHo7pcAQtQtJhKVVcN5wA2ownHzmHluXTGFK4WdFiXzUInhZtqYA5CH+OGHTGs6DTBA==} + /@azure/identity/2.0.4: + resolution: {integrity: sha512-ZgFubAsmo7dji63NLPaot6O7pmDfceAUPY57uphSCr0hmRj+Cakqb4SUz5SohCHFtscrhcmejRU903Fowz6iXg==} engines: {node: '>=12.0.0'} dependencies: '@azure/abort-controller': 1.0.4 '@azure/core-auth': 1.3.2 '@azure/core-client': 1.5.0 - '@azure/core-rest-pipeline': 1.5.0 + '@azure/core-rest-pipeline': 1.7.0 '@azure/core-tracing': 1.0.0-preview.13 '@azure/core-util': 1.0.0-beta.1 '@azure/logger': 1.0.3 - '@azure/msal-browser': 2.22.0 + '@azure/msal-browser': 2.22.1 '@azure/msal-common': 4.5.1 - '@azure/msal-node': 1.6.0 + '@azure/msal-node': 1.7.0 events: 3.3.0 jws: 4.0.0 open: 8.4.0 @@ -4473,7 +4517,7 @@ packages: dependencies: '@azure/abort-controller': 1.0.4 '@azure/core-http': 2.2.4 - '@azure/core-lro': 2.2.3 + '@azure/core-lro': 2.2.4 '@azure/core-paging': 1.2.1 '@azure/core-tracing': 1.0.0-preview.13 '@azure/logger': 1.0.3 @@ -4504,8 +4548,8 @@ packages: - debug dev: false - /@azure/msal-browser/2.22.0: - resolution: {integrity: sha512-ZpnbnzjYGRGHjWDPOLjSp47CQvhK927+W9avtLoNNCMudqs2dBfwj76lnJwObDE7TAKmCUueTiieglBiPb1mgQ==} + /@azure/msal-browser/2.22.1: + resolution: {integrity: sha512-VYvdSHnOen1CDok01OhfQ2qNxsrY10WAKe6c2reIuwqqDDOkWwq1IDkieGHpDRjj4kGdPZ/dle4d7SlvNi9EJQ==} engines: {node: '>=0.8.0'} dependencies: '@azure/msal-common': 6.1.0 @@ -4517,7 +4561,7 @@ packages: resolution: {integrity: sha512-/i5dXM+QAtO+6atYd5oHGBAx48EGSISkXNXViheliOQe+SIFMDo3gSq3lL54W0suOSAsVPws3XnTaIHlla0PIQ==} engines: {node: '>=0.8.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: false @@ -4526,13 +4570,13 @@ packages: resolution: {integrity: sha512-IGjAHttOgKDPQr0Qxx1NjABR635ZNuN7LHjxI0Y7SEA2thcaRGTccy+oaXTFabM/rZLt4F2VrPKUX4BnR9hW9g==} engines: {node: '>=0.8.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color dev: false - /@azure/msal-node/1.6.0: - resolution: {integrity: sha512-RCPXVWsjqYZh7NB1pAJLn4ypHlLBulOjw5nKPLsJiaJJIXnN8kc6SMkK3S9/80DZCEBstvoRMz6zF50QZJUeOQ==} + /@azure/msal-node/1.7.0: + resolution: {integrity: sha512-qDkW+Z4b0SGkkYrM1x+0s5WJ3z96vgiNZ20iwpmtCUHVfSrDiGFB8s8REKVaz7JZJi2L1s0vQRbUahly8EoGnw==} engines: {node: 10 || 12 || 14 || 16} dependencies: '@azure/msal-common': 6.1.0 @@ -4551,7 +4595,7 @@ packages: dependencies: '@azure/abort-controller': 1.0.4 '@azure/core-http': 2.2.4 - '@azure/core-lro': 2.2.3 + '@azure/core-lro': 2.2.4 '@azure/core-paging': 1.2.1 '@azure/core-tracing': 1.0.0-preview.13 '@azure/logger': 1.0.3 @@ -4561,13 +4605,13 @@ packages: - encoding dev: false - /@azure/storage-blob/12.8.0: - resolution: {integrity: sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A==} + /@azure/storage-blob/12.9.0: + resolution: {integrity: sha512-ank38FdCLfJ+EoeMzCz3hkYJuZAd63ARvDKkxZYRDb+beBYf+/+gx8jNTqkq/hfyUl4dJQ/a7tECU0Y0F98CHg==} engines: {node: '>=12.0.0'} dependencies: '@azure/abort-controller': 1.0.4 '@azure/core-http': 2.2.4 - '@azure/core-lro': 2.2.3 + '@azure/core-lro': 2.2.4 '@azure/core-paging': 1.2.1 '@azure/core-tracing': 1.0.0-preview.13 '@azure/logger': 1.0.3 @@ -4594,8 +4638,8 @@ packages: dependencies: '@babel/highlight': 7.16.10 - /@babel/compat-data/7.17.0: - resolution: {integrity: sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==} + /@babel/compat-data/7.17.7: + resolution: {integrity: sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==} engines: {node: '>=6.9.0'} /@babel/core/7.12.3: @@ -4603,17 +4647,17 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/generator': 7.17.3 - '@babel/helper-module-transforms': 7.16.7 - '@babel/helpers': 7.17.2 - '@babel/parser': 7.17.3 + '@babel/generator': 7.17.7 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helpers': 7.17.8 + '@babel/parser': 7.17.8 '@babel/template': 7.16.7 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 convert-source-map: 1.8.0 - debug: 4.3.3 + debug: 4.3.4 gensync: 1.0.0-beta.2 - json5: 2.2.0 + json5: 2.2.1 lodash: 4.17.21 resolve: 1.19.0 semver: 5.7.1 @@ -4622,30 +4666,30 @@ packages: - supports-color dev: true - /@babel/core/7.17.5: - resolution: {integrity: sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==} + /@babel/core/7.17.8: + resolution: {integrity: sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==} engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.1.2 '@babel/code-frame': 7.16.7 - '@babel/generator': 7.17.3 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.5 - '@babel/helper-module-transforms': 7.16.7 - '@babel/helpers': 7.17.2 - '@babel/parser': 7.17.3 + '@babel/generator': 7.17.7 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 + '@babel/helper-module-transforms': 7.17.7 + '@babel/helpers': 7.17.8 + '@babel/parser': 7.17.8 '@babel/template': 7.16.7 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 convert-source-map: 1.8.0 - debug: 4.3.3 + debug: 4.3.4 gensync: 1.0.0-beta.2 - json5: 2.2.0 + json5: 2.2.1 semver: 6.3.0 transitivePeerDependencies: - supports-color - /@babel/generator/7.17.3: - resolution: {integrity: sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==} + /@babel/generator/7.17.7: + resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.17.0 @@ -4667,33 +4711,33 @@ packages: '@babel/types': 7.17.0 dev: true - /@babel/helper-compilation-targets/7.16.7_@babel+core@7.12.3: - resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.12.3: + resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.17.0 + '@babel/compat-data': 7.17.7 '@babel/core': 7.12.3 '@babel/helper-validator-option': 7.16.7 - browserslist: 4.19.2 + browserslist: 4.20.2 semver: 6.3.0 dev: true - /@babel/helper-compilation-targets/7.16.7_@babel+core@7.17.5: - resolution: {integrity: sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==} + /@babel/helper-compilation-targets/7.17.7_@babel+core@7.17.8: + resolution: {integrity: sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.17.0 - '@babel/core': 7.17.5 + '@babel/compat-data': 7.17.7 + '@babel/core': 7.17.8 '@babel/helper-validator-option': 7.16.7 - browserslist: 4.19.2 + browserslist: 4.20.2 semver: 6.3.0 - /@babel/helper-create-class-features-plugin/7.17.1_@babel+core@7.12.3: - resolution: {integrity: sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==} + /@babel/helper-create-class-features-plugin/7.17.6_@babel+core@7.12.3: + resolution: {integrity: sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -4702,7 +4746,7 @@ packages: '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-function-name': 7.16.7 - '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.17.7 '@babel/helper-optimise-call-expression': 7.16.7 '@babel/helper-replace-supers': 7.16.7 '@babel/helper-split-export-declaration': 7.16.7 @@ -4710,17 +4754,17 @@ packages: - supports-color dev: true - /@babel/helper-create-class-features-plugin/7.17.1_@babel+core@7.17.5: - resolution: {integrity: sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==} + /@babel/helper-create-class-features-plugin/7.17.6_@babel+core@7.17.8: + resolution: {integrity: sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-function-name': 7.16.7 - '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.17.7 '@babel/helper-optimise-call-expression': 7.16.7 '@babel/helper-replace-supers': 7.16.7 '@babel/helper-split-export-declaration': 7.16.7 @@ -4739,13 +4783,13 @@ packages: regexpu-core: 5.0.1 dev: true - /@babel/helper-create-regexp-features-plugin/7.17.0_@babel+core@7.17.5: + /@babel/helper-create-regexp-features-plugin/7.17.0_@babel+core@7.17.8: resolution: {integrity: sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 regexpu-core: 5.0.1 dev: true @@ -4756,11 +4800,11 @@ packages: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.12.3 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.12.3 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/traverse': 7.17.3 - debug: 4.3.3 + debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.19.0 semver: 6.3.0 @@ -4768,17 +4812,17 @@ packages: - supports-color dev: true - /@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.17.5: + /@babel/helper-define-polyfill-provider/0.3.1_@babel+core@7.17.8: resolution: {integrity: sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==} peerDependencies: '@babel/core': ^7.4.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/traverse': 7.17.3 - debug: 4.3.3 + debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.19.0 semver: 6.3.0 @@ -4819,8 +4863,8 @@ packages: dependencies: '@babel/types': 7.17.0 - /@babel/helper-member-expression-to-functions/7.16.7: - resolution: {integrity: sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==} + /@babel/helper-member-expression-to-functions/7.17.7: + resolution: {integrity: sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.17.0 @@ -4832,13 +4876,13 @@ packages: dependencies: '@babel/types': 7.17.0 - /@babel/helper-module-transforms/7.16.7: - resolution: {integrity: sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==} + /@babel/helper-module-transforms/7.17.7: + resolution: {integrity: sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-simple-access': 7.16.7 + '@babel/helper-simple-access': 7.17.7 '@babel/helper-split-export-declaration': 7.16.7 '@babel/helper-validator-identifier': 7.16.7 '@babel/template': 7.16.7 @@ -4875,7 +4919,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.16.7 - '@babel/helper-member-expression-to-functions': 7.16.7 + '@babel/helper-member-expression-to-functions': 7.17.7 '@babel/helper-optimise-call-expression': 7.16.7 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 @@ -4883,8 +4927,8 @@ packages: - supports-color dev: true - /@babel/helper-simple-access/7.16.7: - resolution: {integrity: sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==} + /@babel/helper-simple-access/7.17.7: + resolution: {integrity: sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.17.0 @@ -4922,8 +4966,8 @@ packages: - supports-color dev: true - /@babel/helpers/7.17.2: - resolution: {integrity: sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==} + /@babel/helpers/7.17.8: + resolution: {integrity: sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.16.7 @@ -4940,8 +4984,8 @@ packages: chalk: 2.4.2 js-tokens: 4.0.0 - /@babel/parser/7.17.3: - resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==} + /@babel/parser/7.17.8: + resolution: {integrity: sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -4955,13 +4999,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.5: + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -4977,16 +5021,16 @@ packages: '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.12.3 dev: true - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.17.5: + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-async-generator-functions/7.16.8_@babel+core@7.12.3: @@ -5003,16 +5047,16 @@ packages: - supports-color dev: true - /@babel/plugin-proposal-async-generator-functions/7.16.8_@babel+core@7.17.5: + /@babel/plugin-proposal-async-generator-functions/7.16.8_@babel+core@7.17.8: resolution: {integrity: sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-remap-async-to-generator': 7.16.8 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.5 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true @@ -5024,64 +5068,64 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.12.3 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-class-properties/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.12.3: - resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} + /@babel/plugin-proposal-class-static-block/7.17.6_@babel+core@7.12.3: + resolution: {integrity: sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.12.3 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.12.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-class-static-block/7.16.7_@babel+core@7.17.5: - resolution: {integrity: sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==} + /@babel/plugin-proposal-class-static-block/7.17.6_@babel+core@7.17.8: + resolution: {integrity: sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.5 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-decorators/7.17.2_@babel+core@7.17.5: - resolution: {integrity: sha512-WH8Z95CwTq/W8rFbMqb9p3hicpt4RX4f0K659ax2VHxgOyT6qQmUaEVEjIh4WR9Eh9NymkVn5vwsrE68fAQNUw==} + /@babel/plugin-proposal-decorators/7.17.8_@babel+core@7.17.8: + resolution: {integrity: sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-replace-supers': 7.16.7 - '@babel/plugin-syntax-decorators': 7.17.0_@babel+core@7.17.5 + '@babel/plugin-syntax-decorators': 7.17.0_@babel+core@7.17.8 charcodes: 0.2.0 transitivePeerDependencies: - supports-color @@ -5098,15 +5142,15 @@ packages: '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-dynamic-import/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.12.3: @@ -5120,15 +5164,15 @@ packages: '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-export-namespace-from/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.12.3: @@ -5142,15 +5186,15 @@ packages: '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-json-strings/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.12.3: @@ -5164,15 +5208,15 @@ packages: '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-logical-assignment-operators/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.5 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.12.3: @@ -5186,15 +5230,15 @@ packages: '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-nullish-coalescing-operator/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.12.3: @@ -5208,15 +5252,15 @@ packages: '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-numeric-separator/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-object-rest-spread/7.17.3_@babel+core@7.12.3: @@ -5225,26 +5269,26 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 + '@babel/compat-data': 7.17.7 '@babel/core': 7.12.3 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.12.3 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.12.3 '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-object-rest-spread/7.17.3_@babel+core@7.17.5: + /@babel/plugin-proposal-object-rest-spread/7.17.3_@babel+core@7.17.8: resolution: {integrity: sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 - '@babel/core': 7.17.5 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.5 + '@babel/compat-data': 7.17.7 + '@babel/core': 7.17.8 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.12.3: @@ -5258,15 +5302,15 @@ packages: '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-optional-catch-binding/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.12.3: @@ -5281,16 +5325,16 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.12.3 dev: true - /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-optional-chaining/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.8 dev: true /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.12.3: @@ -5300,20 +5344,20 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.12.3 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.17.5: + /@babel/plugin-proposal-private-methods/7.16.11_@babel+core@7.17.8: resolution: {integrity: sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color @@ -5327,24 +5371,24 @@ packages: dependencies: '@babel/core': 7.12.3 '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.12.3 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.12.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-private-property-in-object/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true @@ -5360,14 +5404,14 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.17.5: + /@babel/plugin-proposal-unicode-property-regex/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==} engines: {node: '>=4'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5380,12 +5424,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.17.5: + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.17.8: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5398,12 +5442,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5416,12 +5460,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.17.5: + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.17.8: resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5435,23 +5479,23 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.17.5: + /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.17.8: resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-decorators/7.17.0_@babel+core@7.17.5: + /@babel/plugin-syntax-decorators/7.17.0_@babel+core@7.17.8: resolution: {integrity: sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5464,12 +5508,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5482,22 +5526,22 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.17.5: + /@babel/plugin-syntax-flow/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5510,12 +5554,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.5: + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.17.8: resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5528,12 +5572,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5547,13 +5591,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.5: + /@babel/plugin-syntax-jsx/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5566,12 +5610,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.17.5: + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.17.8: resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5584,12 +5628,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5602,12 +5646,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.17.5: + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.17.8: resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5620,12 +5664,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5638,12 +5682,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5656,12 +5700,12 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.17.5: + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.17.8: resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5675,13 +5719,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.17.5: + /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.17.8: resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5695,23 +5739,23 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.17.5: + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.17.8: resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.17.5: + /@babel/plugin-syntax-typescript/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5725,13 +5769,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-arrow-functions/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-arrow-functions/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5749,13 +5793,13 @@ packages: - supports-color dev: true - /@babel/plugin-transform-async-to-generator/7.16.8_@babel+core@7.17.5: + /@babel/plugin-transform-async-to-generator/7.16.8_@babel+core@7.17.8: resolution: {integrity: sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-remap-async-to-generator': 7.16.8 @@ -5773,13 +5817,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-block-scoped-functions/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5793,13 +5837,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-block-scoping/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5822,13 +5866,13 @@ packages: - supports-color dev: true - /@babel/plugin-transform-classes/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-classes/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-function-name': 7.16.7 @@ -5851,18 +5895,18 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-computed-properties/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-destructuring/7.17.3_@babel+core@7.12.3: - resolution: {integrity: sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==} + /@babel/plugin-transform-destructuring/7.17.7_@babel+core@7.12.3: + resolution: {integrity: sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -5871,13 +5915,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-destructuring/7.17.3_@babel+core@7.17.5: - resolution: {integrity: sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==} + /@babel/plugin-transform-destructuring/7.17.7_@babel+core@7.17.8: + resolution: {integrity: sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5892,14 +5936,14 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-dotall-regex/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5913,13 +5957,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-duplicate-keys/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5934,26 +5978,26 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-exponentiation-operator/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-builder-binary-assignment-operator-visitor': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-flow-strip-types/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-flow': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-syntax-flow': 7.16.7_@babel+core@7.17.8 dev: true /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.12.3: @@ -5966,13 +6010,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-for-of/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -5983,19 +6027,19 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.12.3 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.12.3 '@babel/helper-function-name': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-function-name/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 '@babel/helper-function-name': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6010,13 +6054,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-literals/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-literals/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6030,13 +6074,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-member-expression-literals/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6047,66 +6091,66 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-modules-amd/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-module-transforms': 7.16.7 + '@babel/core': 7.17.8 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.16.8_@babel+core@7.12.3: - resolution: {integrity: sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==} + /@babel/plugin-transform-modules-commonjs/7.17.7_@babel+core@7.12.3: + resolution: {integrity: sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-simple-access': 7.16.7 + '@babel/helper-simple-access': 7.17.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-commonjs/7.16.8_@babel+core@7.17.5: - resolution: {integrity: sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==} + /@babel/plugin-transform-modules-commonjs/7.17.7_@babel+core@7.17.8: + resolution: {integrity: sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-module-transforms': 7.16.7 + '@babel/core': 7.17.8 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/helper-simple-access': 7.16.7 + '@babel/helper-simple-access': 7.17.7 babel-plugin-dynamic-import-node: 2.3.3 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.12.3: - resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} + /@babel/plugin-transform-modules-systemjs/7.17.8_@babel+core@7.12.3: + resolution: {integrity: sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 '@babel/helper-hoist-variables': 7.16.7 - '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-identifier': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 @@ -6114,15 +6158,15 @@ packages: - supports-color dev: true - /@babel/plugin-transform-modules-systemjs/7.16.7_@babel+core@7.17.5: - resolution: {integrity: sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==} + /@babel/plugin-transform-modules-systemjs/7.17.8_@babel+core@7.17.8: + resolution: {integrity: sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-hoist-variables': 7.16.7 - '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-identifier': 7.16.7 babel-plugin-dynamic-import-node: 2.3.3 @@ -6137,20 +6181,20 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-module-transforms': 7.16.7 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color dev: true - /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-modules-umd/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-module-transforms': 7.16.7 + '@babel/core': 7.17.8 + '@babel/helper-module-transforms': 7.17.7 '@babel/helper-plugin-utils': 7.16.7 transitivePeerDependencies: - supports-color @@ -6166,14 +6210,14 @@ packages: '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.12.3 dev: true - /@babel/plugin-transform-named-capturing-groups-regex/7.16.8_@babel+core@7.17.5: + /@babel/plugin-transform-named-capturing-groups-regex/7.16.8_@babel+core@7.17.8: resolution: {integrity: sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.8 dev: true /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.12.3: @@ -6186,13 +6230,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-new-target/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6209,13 +6253,13 @@ packages: - supports-color dev: true - /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-object-super/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-replace-supers': 7.16.7 transitivePeerDependencies: @@ -6232,13 +6276,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-parameters/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6252,18 +6296,18 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-property-literals/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-react-constant-elements/7.16.7_@babel+core@7.12.3: - resolution: {integrity: sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ==} + /@babel/plugin-transform-react-constant-elements/7.17.6_@babel+core@7.12.3: + resolution: {integrity: sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -6282,13 +6326,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-react-display-name/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-react-display-name/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6302,14 +6346,14 @@ packages: '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.12.3 dev: true - /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-react-jsx-development/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.8 dev: true /@babel/plugin-transform-react-jsx/7.17.3_@babel+core@7.12.3: @@ -6326,17 +6370,17 @@ packages: '@babel/types': 7.17.0 dev: true - /@babel/plugin-transform-react-jsx/7.17.3_@babel+core@7.17.5: + /@babel/plugin-transform-react-jsx/7.17.3_@babel+core@7.17.8: resolution: {integrity: sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-syntax-jsx': 7.16.7_@babel+core@7.17.8 '@babel/types': 7.17.0 dev: true @@ -6351,13 +6395,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-react-pure-annotations/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6372,13 +6416,13 @@ packages: regenerator-transform: 0.14.5 dev: true - /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-regenerator/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 regenerator-transform: 0.14.5 dev: true @@ -6392,28 +6436,28 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-reserved-words/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-runtime/7.17.0_@babel+core@7.17.5: + /@babel/plugin-transform-runtime/7.17.0_@babel+core@7.17.8: resolution: {integrity: sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-module-imports': 7.16.7 '@babel/helper-plugin-utils': 7.16.7 - babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.17.5 - babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.17.5 - babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.17.5 + babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.17.8 + babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.17.8 + babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.17.8 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -6429,13 +6473,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-shorthand-properties/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6450,13 +6494,13 @@ packages: '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 dev: true - /@babel/plugin-transform-spread/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-spread/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-skip-transparent-expression-wrappers': 7.16.0 dev: true @@ -6471,13 +6515,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-sticky-regex/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6491,13 +6535,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-template-literals/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6511,26 +6555,26 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-typeof-symbol/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.17.5: + /@babel/plugin-transform-typescript/7.16.8_@babel+core@7.17.8: resolution: {integrity: sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-class-features-plugin': 7.17.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-class-features-plugin': 7.17.6_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-syntax-typescript': 7.16.7_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true @@ -6545,13 +6589,13 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-unicode-escapes/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6566,14 +6610,14 @@ packages: '@babel/helper-plugin-utils': 7.16.7 dev: true - /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.17.5: + /@babel/plugin-transform-unicode-regex/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-create-regexp-features-plugin': 7.17.0_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 dev: true @@ -6583,16 +6627,16 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 + '@babel/compat-data': 7.17.7 '@babel/core': 7.12.3 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.12.3 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.12.3 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-option': 7.16.7 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.12.3 '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.12.3 '@babel/plugin-proposal-async-generator-functions': 7.16.8_@babel+core@7.12.3 '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.12.3 - '@babel/plugin-proposal-class-static-block': 7.16.7_@babel+core@7.12.3 + '@babel/plugin-proposal-class-static-block': 7.17.6_@babel+core@7.12.3 '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.12.3 '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.12.3 '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.12.3 @@ -6625,7 +6669,7 @@ packages: '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.12.3 - '@babel/plugin-transform-destructuring': 7.17.3_@babel+core@7.12.3 + '@babel/plugin-transform-destructuring': 7.17.7_@babel+core@7.12.3 '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.12.3 @@ -6634,8 +6678,8 @@ packages: '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.12.3 - '@babel/plugin-transform-modules-commonjs': 7.16.8_@babel+core@7.12.3 - '@babel/plugin-transform-modules-systemjs': 7.16.7_@babel+core@7.12.3 + '@babel/plugin-transform-modules-commonjs': 7.17.7_@babel+core@7.12.3 + '@babel/plugin-transform-modules-systemjs': 7.17.8_@babel+core@7.12.3 '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.12.3 '@babel/plugin-transform-named-capturing-groups-regex': 7.16.8_@babel+core@7.12.3 '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.12.3 @@ -6662,85 +6706,85 @@ packages: - supports-color dev: true - /@babel/preset-env/7.16.11_@babel+core@7.17.5: + /@babel/preset-env/7.16.11_@babel+core@7.17.8: resolution: {integrity: sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 - '@babel/core': 7.17.5 - '@babel/helper-compilation-targets': 7.16.7_@babel+core@7.17.5 + '@babel/compat-data': 7.17.7 + '@babel/core': 7.17.8 + '@babel/helper-compilation-targets': 7.17.7_@babel+core@7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-async-generator-functions': 7.16.8_@babel+core@7.17.5 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-class-static-block': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-object-rest-spread': 7.17.3_@babel+core@7.17.5 - '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.17.5 - '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.5 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.5 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.5 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.5 - '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-async-to-generator': 7.16.8_@babel+core@7.17.5 - '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-destructuring': 7.17.3_@babel+core@7.17.5 - '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-modules-commonjs': 7.16.8_@babel+core@7.17.5 - '@babel/plugin-transform-modules-systemjs': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-named-capturing-groups-regex': 7.16.8_@babel+core@7.17.5 - '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-regenerator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-reserved-words': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-typeof-symbol': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.17.5 - '@babel/preset-modules': 0.1.5_@babel+core@7.17.5 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-async-generator-functions': 7.16.8_@babel+core@7.17.8 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-class-static-block': 7.17.6_@babel+core@7.17.8 + '@babel/plugin-proposal-dynamic-import': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-export-namespace-from': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-json-strings': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-logical-assignment-operators': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-object-rest-spread': 7.17.3_@babel+core@7.17.8 + '@babel/plugin-proposal-optional-catch-binding': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.17.8 + '@babel/plugin-proposal-private-property-in-object': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.8 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.8 + '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.17.8 + '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.17.8 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.8 + '@babel/plugin-transform-arrow-functions': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-async-to-generator': 7.16.8_@babel+core@7.17.8 + '@babel/plugin-transform-block-scoped-functions': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-block-scoping': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-classes': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-computed-properties': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-destructuring': 7.17.7_@babel+core@7.17.8 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-duplicate-keys': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-exponentiation-operator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-for-of': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-function-name': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-literals': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-member-expression-literals': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-modules-amd': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-modules-commonjs': 7.17.7_@babel+core@7.17.8 + '@babel/plugin-transform-modules-systemjs': 7.17.8_@babel+core@7.17.8 + '@babel/plugin-transform-modules-umd': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-named-capturing-groups-regex': 7.16.8_@babel+core@7.17.8 + '@babel/plugin-transform-new-target': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-object-super': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-parameters': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-property-literals': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-regenerator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-reserved-words': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-shorthand-properties': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-spread': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-sticky-regex': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-template-literals': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-typeof-symbol': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-unicode-escapes': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-unicode-regex': 7.16.7_@babel+core@7.17.8 + '@babel/preset-modules': 0.1.5_@babel+core@7.17.8 '@babel/types': 7.17.0 - babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.17.5 - babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.17.5 - babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.17.5 + babel-plugin-polyfill-corejs2: 0.3.1_@babel+core@7.17.8 + babel-plugin-polyfill-corejs3: 0.5.2_@babel+core@7.17.8 + babel-plugin-polyfill-regenerator: 0.3.1_@babel+core@7.17.8 core-js-compat: 3.21.1 semver: 6.3.0 transitivePeerDependencies: @@ -6760,15 +6804,15 @@ packages: esutils: 2.0.3 dev: true - /@babel/preset-modules/0.1.5_@babel+core@7.17.5: + /@babel/preset-modules/0.1.5_@babel+core@7.17.8: resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 - '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-proposal-unicode-property-regex': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-dotall-regex': 7.16.7_@babel+core@7.17.8 '@babel/types': 7.17.0 esutils: 2.0.3 dev: true @@ -6788,44 +6832,44 @@ packages: '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.12.3 dev: true - /@babel/preset-react/7.16.7_@babel+core@7.17.5: + /@babel/preset-react/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.5 - '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.17.5 + '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-react-jsx': 7.17.3_@babel+core@7.17.8 + '@babel/plugin-transform-react-jsx-development': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-react-pure-annotations': 7.16.7_@babel+core@7.17.8 dev: true - /@babel/preset-typescript/7.16.7_@babel+core@7.17.5: + /@babel/preset-typescript/7.16.7_@babel+core@7.17.8: resolution: {integrity: sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-plugin-utils': 7.16.7 '@babel/helper-validator-option': 7.16.7 - '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.17.5 + '@babel/plugin-transform-typescript': 7.16.8_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true - /@babel/runtime-corejs3/7.17.2: - resolution: {integrity: sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==} + /@babel/runtime-corejs3/7.17.8: + resolution: {integrity: sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==} engines: {node: '>=6.9.0'} dependencies: core-js-pure: 3.21.1 regenerator-runtime: 0.13.9 - /@babel/runtime/7.17.2: - resolution: {integrity: sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==} + /@babel/runtime/7.17.8: + resolution: {integrity: sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.9 @@ -6835,7 +6879,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 /@babel/traverse/7.17.3: @@ -6843,14 +6887,14 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/generator': 7.17.3 + '@babel/generator': 7.17.7 '@babel/helper-environment-visitor': 7.16.7 '@babel/helper-function-name': 7.16.7 '@babel/helper-hoist-variables': 7.16.7 '@babel/helper-split-export-declaration': 7.16.7 - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 - debug: 4.3.3 + debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6874,8 +6918,8 @@ packages: resolution: {integrity: sha512-IIs1wDcY2oZ8tJ3EZRw0U51M+0ZL3MvwoDYYmhUXaa9/UZqpFoOyLBGaxjirQteWXqTIMm3mFvmC+Nbn1ok4Iw==} dev: false - /@bentley/imodeljs-native/3.1.6: - resolution: {integrity: sha512-e4FfMt7h/YrsvMag+1hYpvdSy9ooFEsGHwpmJkjiscx16PThfK5cbqgwEV/SY79q4zJKeragPVjWbO9BJo5hTg==} + /@bentley/imodeljs-native/3.2.1: + resolution: {integrity: sha512-oIe9mhdpI0iMVBXnBJRDxIKM7Bh+BkpdV9ve32FV0k1f5eYnBLnEzRXDGPQrUYrJh1HDHlGmnQdxNL9rWLNtvQ==} requiresBuild: true dev: false @@ -6894,8 +6938,8 @@ packages: '@bentley/webpack-tools-core': 2.19.28_webpack@4.44.2 '@pmmmwh/react-refresh-webpack-plugin': 0.4.3_9f0995138d24e525eb86c097d82409c0 '@svgr/webpack': 5.5.0 - '@typescript-eslint/eslint-plugin': 4.31.2_8f0416aa8ec58a469909c5c0f73069bc - '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.4 + '@typescript-eslint/eslint-plugin': 4.26.0_254a60bd907cee05fd203cdf9e9086f0 + '@typescript-eslint/parser': 4.26.0_eslint@7.32.0+typescript@4.4.4 babel-eslint: 10.1.0_eslint@7.32.0 babel-jest: 26.6.3_@babel+core@7.12.3 babel-loader: 8.1.0_427212bc1158d185e577033f19ca0757 @@ -6910,16 +6954,16 @@ packages: dotenv: 8.2.0 dotenv-expand: 5.1.0 eslint: 7.32.0 - eslint-config-react-app: 6.0.0_1aeedec7f5157d0e02e45ad499760247 + eslint-config-react-app: 6.0.0_587eb56c66291e3ab94b46708696c3be eslint-plugin-flowtype: 5.10.0_eslint@7.32.0 eslint-plugin-import: 2.23.4_eslint@7.32.0 - eslint-plugin-jest: 24.7.0_1597ebf22056641fa858351a9409f475 + eslint-plugin-jest: 24.7.0_537c812b64b0470fabb72cea3d22f29e eslint-plugin-jsx-a11y: 6.4.1_eslint@7.32.0 eslint-plugin-react: 7.24.0_eslint@7.32.0 eslint-plugin-react-hooks: 4.2.0_eslint@7.32.0 eslint-plugin-testing-library: 3.10.2_eslint@7.32.0+typescript@4.4.4 eslint-webpack-plugin: 2.6.0_eslint@7.32.0+webpack@4.44.2 - fast-sass-loader: 2.0.1_sass@1.49.8+webpack@4.44.2 + fast-sass-loader: 2.0.1_sass@1.49.9+webpack@4.44.2 file-loader: 6.1.1_webpack@4.44.2 fs-extra: 9.1.0 html-webpack-plugin: 4.5.0_webpack@4.44.2 @@ -6942,9 +6986,9 @@ packages: react-dev-utils: 11.0.4 react-refresh: 0.8.3 resolve: 1.18.1 - resolve-url-loader: 3.1.4 - sass: 1.49.8 - sass-loader: 10.2.1_sass@1.49.8+webpack@4.44.2 + resolve-url-loader: 3.1.2 + sass: 1.49.9 + sass-loader: 10.2.1_sass@1.49.9+webpack@4.44.2 semver: 7.3.2 source-map-loader: 1.1.3_webpack@4.44.2 speed-measure-webpack-plugin: 1.5.0_webpack@4.44.2 @@ -6964,7 +7008,6 @@ packages: fsevents: 2.3.2 transitivePeerDependencies: - '@types/webpack' - - acorn - bufferutil - canvas - fibers @@ -6995,8 +7038,8 @@ packages: '@bentley/webpack-tools-core': 2.19.28_webpack@4.44.2 '@pmmmwh/react-refresh-webpack-plugin': 0.4.3_9f0995138d24e525eb86c097d82409c0 '@svgr/webpack': 5.5.0 - '@typescript-eslint/eslint-plugin': 4.31.2_8f0416aa8ec58a469909c5c0f73069bc - '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.4 + '@typescript-eslint/eslint-plugin': 4.26.0_254a60bd907cee05fd203cdf9e9086f0 + '@typescript-eslint/parser': 4.26.0_eslint@7.32.0+typescript@4.4.4 babel-eslint: 10.1.0_eslint@7.32.0 babel-jest: 26.6.3_@babel+core@7.12.3 babel-loader: 8.1.0_427212bc1158d185e577033f19ca0757 @@ -7011,16 +7054,16 @@ packages: dotenv: 8.2.0 dotenv-expand: 5.1.0 eslint: 7.32.0 - eslint-config-react-app: 6.0.0_1aeedec7f5157d0e02e45ad499760247 + eslint-config-react-app: 6.0.0_587eb56c66291e3ab94b46708696c3be eslint-plugin-flowtype: 5.10.0_eslint@7.32.0 eslint-plugin-import: 2.23.4_eslint@7.32.0 - eslint-plugin-jest: 24.7.0_1597ebf22056641fa858351a9409f475 + eslint-plugin-jest: 24.7.0_537c812b64b0470fabb72cea3d22f29e eslint-plugin-jsx-a11y: 6.4.1_eslint@7.32.0 eslint-plugin-react: 7.24.0_eslint@7.32.0 eslint-plugin-react-hooks: 4.2.0_eslint@7.32.0 eslint-plugin-testing-library: 3.10.2_eslint@7.32.0+typescript@4.4.4 eslint-webpack-plugin: 2.6.0_eslint@7.32.0+webpack@4.44.2 - fast-sass-loader: 2.0.1_sass@1.49.8+webpack@4.44.2 + fast-sass-loader: 2.0.1_sass@1.49.9+webpack@4.44.2 file-loader: 6.1.1_webpack@4.44.2 fs-extra: 9.1.0 html-webpack-plugin: 4.5.0_webpack@4.44.2 @@ -7042,9 +7085,9 @@ packages: react-dev-utils: 11.0.4 react-refresh: 0.8.3 resolve: 1.18.1 - resolve-url-loader: 3.1.4 - sass: 1.49.8 - sass-loader: 10.2.1_sass@1.49.8+webpack@4.44.2 + resolve-url-loader: 3.1.2 + sass: 1.49.9 + sass-loader: 10.2.1_sass@1.49.9+webpack@4.44.2 semver: 7.3.2 source-map-loader: 1.1.3_webpack@4.44.2 speed-measure-webpack-plugin: 1.5.0_webpack@4.44.2 @@ -7064,7 +7107,6 @@ packages: fsevents: 2.3.2 transitivePeerDependencies: - '@types/webpack' - - acorn - bufferutil - canvas - fibers @@ -7109,7 +7151,7 @@ packages: hasBin: true dependencies: exec-sh: 0.3.6 - minimist: 1.2.5 + minimist: 1.2.6 dev: true /@colors/colors/1.5.0: @@ -7134,11 +7176,11 @@ packages: kuler: 2.0.0 dev: false - /@electron/get/1.13.1: - resolution: {integrity: sha512-U5vkXDZ9DwXtkPqlB45tfYnnYBN8PePp1z/XDCupnSpdrxT8/ThCv9WCwPLf9oqiSGZTkH6dx2jDUPuoXpjkcA==} + /@electron/get/1.14.1: + resolution: {integrity: sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==} engines: {node: '>=8.6'} dependencies: - debug: 4.3.3 + debug: 4.3.4 env-paths: 2.2.1 fs-extra: 8.1.0 got: 9.6.0 @@ -7165,7 +7207,7 @@ packages: peerDependencies: react: '>=16.3.0' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@emotion/cache': 10.0.29 '@emotion/css': 10.0.27 '@emotion/serialize': 0.11.16 @@ -7197,7 +7239,7 @@ packages: '@emotion/memoize': 0.7.4 '@emotion/unitless': 0.7.5 '@emotion/utils': 0.11.3 - csstype: 2.6.19 + csstype: 2.6.20 dev: false /@emotion/sheet/0.9.4: @@ -7234,9 +7276,9 @@ packages: engines: {node: ^10.12.0 || >=12.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.3 + debug: 4.3.4 espree: 7.3.1 - globals: 13.12.1 + globals: 13.13.0 ignore: 4.0.6 import-fresh: 3.3.0 js-yaml: 3.14.1 @@ -7285,7 +7327,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.3 + debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -7309,14 +7351,13 @@ packages: /@itwin/browser-authorization/0.5.1: resolution: {integrity: sha512-TI7nd4I5Lc9MrJnf40kk+u4bTCym1xH9IBJNkvVt+7unjUSbRuUaPS6wC6WTu2DoYbIocEIEBWTqNOR67lAHGA==} - peerDependencies: - '@itwin/core-bentley': ^3.0.0 dependencies: + '@itwin/core-bentley': link:../../core/bentley oidc-client: 1.11.5 dev: false - /@itwin/certa/3.0.0: - resolution: {integrity: sha512-nCRUIsCEOyIwbbUeN3tX/at7g7ezhn38xaUa5Y9wmrxIB1goBmkk1p1FpKdJJlxmUinQsyKR65lGuS9WseUF6w==} + /@itwin/certa/3.0.2: + resolution: {integrity: sha512-EnXUGKMwgjGjOg9+DKc/R7P2LjRvU0Yy4fEwJfTXadxmV3kWxIGrxnKT43Bz4r3i8Jk/n7TssdZh/3EbdjBGQQ==} hasBin: true peerDependencies: electron: ^14.0.0 @@ -7338,8 +7379,8 @@ packages: - supports-color - utf-8-validate - /@itwin/certa/3.0.0_electron@14.2.6: - resolution: {integrity: sha512-nCRUIsCEOyIwbbUeN3tX/at7g7ezhn38xaUa5Y9wmrxIB1goBmkk1p1FpKdJJlxmUinQsyKR65lGuS9WseUF6w==} + /@itwin/certa/3.0.2_electron@14.2.7: + resolution: {integrity: sha512-EnXUGKMwgjGjOg9+DKc/R7P2LjRvU0Yy4fEwJfTXadxmV3kWxIGrxnKT43Bz4r3i8Jk/n7TssdZh/3EbdjBGQQ==} hasBin: true peerDependencies: electron: ^14.0.0 @@ -7348,7 +7389,7 @@ packages: optional: true dependencies: detect-port: 1.3.0 - electron: 14.2.6 + electron: 14.2.7 express: 4.17.3 jsonc-parser: 2.0.3 lodash: 4.17.21 @@ -7363,17 +7404,6 @@ packages: - utf-8-validate dev: true - /@itwin/core-bentley/3.0.0: - resolution: {integrity: sha512-tfFM6lKVtjUMrQM/amHrEgJRtIhpqI5bGMtX8MwM9bBeH3hLGY8eTA8A7ReflWmUky+gHhpvN3TGsC7VLqqrIw==} - dev: false - - /@itwin/core-geometry/3.0.0: - resolution: {integrity: sha512-00KlHwya2ZhYF4XmrbRJ6RyxaROJJ3j9rTiGKdT8oYvuf+dm5fRA1a+V8HPPKonSiTwpmQYOr0Ro3X6v+CjpDQ==} - dependencies: - '@itwin/core-bentley': 3.0.0 - flatbuffers: 1.12.0 - dev: false - /@itwin/electron-authorization/0.8.3: resolution: {integrity: sha512-gKsQewSx4e/a74WJvROzq+dmUb05zE2evMLLywKP+CQULwq2uX0IeI0MRGI/FeVS9T9xBSv90sSzxmrugBtPrQ==} dependencies: @@ -7427,8 +7457,8 @@ packages: - debug dev: false - /@itwin/itwinui-css/0.44.1: - resolution: {integrity: sha512-J0zSBKLPoEAMPGV/Sw2+VkrQH432HejACXvymUbSGaqBYodIcCm6JPAlMbjeJlNZgU2auQbyPr4tbe1U6AwIWw==} + /@itwin/itwinui-css/0.52.0: + resolution: {integrity: sha512-OTrCEuBR3221I9RuamlE9R19m58uHWR0rKP0lQEgnWlurGI5etgTvoA3r5PIWbT7SM5PJ64toV0NH0pXY9x+Uw==} /@itwin/itwinui-icons-react/1.8.0_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-/16NPEPGvqOAwcJ/uBCvmIyl0c0vaprfsjl/mdecYLf301dKvlKmIH+Eq6a2YUXZHO/B6KaZtM78UCuxXGMQBA==} @@ -7449,8 +7479,8 @@ packages: react: 17.0.2 dev: true - /@itwin/itwinui-illustrations-react/1.2.0_react-dom@17.0.2+react@17.0.2: - resolution: {integrity: sha512-uGX7PVyGuMexLFlVxU/qi1Bzv14RJcv0MwHB43harqUjWOOSvy7l7eXIwEmjuwlfmXDnUULJ88gmgvcnEJGXCA==} + /@itwin/itwinui-illustrations-react/1.3.0_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-80H4sS1PRCs8U5VgzO6F8sWvhkxPS5K3Bu5o99A+M3/aBjuk3zhLn+fN49lBkmFJ+sHWA6xE7+T3cF7xPkz8qA==} peerDependencies: react: ^16.8.6 || ^17.0.0 react-dom: ^16.8.6 || ^17.0.0 @@ -7459,8 +7489,8 @@ packages: react-dom: 17.0.2_react@17.0.2 dev: false - /@itwin/itwinui-illustrations-react/1.2.0_react@17.0.2: - resolution: {integrity: sha512-uGX7PVyGuMexLFlVxU/qi1Bzv14RJcv0MwHB43harqUjWOOSvy7l7eXIwEmjuwlfmXDnUULJ88gmgvcnEJGXCA==} + /@itwin/itwinui-illustrations-react/1.3.0_react@17.0.2: + resolution: {integrity: sha512-80H4sS1PRCs8U5VgzO6F8sWvhkxPS5K3Bu5o99A+M3/aBjuk3zhLn+fN49lBkmFJ+sHWA6xE7+T3cF7xPkz8qA==} peerDependencies: react: ^16.8.6 || ^17.0.0 react-dom: ^16.8.6 || ^17.0.0 @@ -7468,17 +7498,17 @@ packages: react: 17.0.2 dev: true - /@itwin/itwinui-react/1.29.3_react-dom@17.0.2+react@17.0.2: - resolution: {integrity: sha512-c3W2DaGofVaZCe0Z6ldChFBy+GBqBXrMz0Ap6awBLX6FwHcFzwcOxBo0BaCWLoIFl8BFv94mbrRh9zkk1m7ZbA==} + /@itwin/itwinui-react/1.34.0_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-QSpd7TQFNEH9Y/yOGNxlhMDEJtpNxX/pBQWKCWpos4PnqOqpQaKnmeQuZgXxdJ8jytzyDxUVpNQsLxDOkyCJLQ==} peerDependencies: react: ^16.8.6 || ^17.0.0 react-dom: ^16.8.6 || ^17.0.0 dependencies: - '@itwin/itwinui-css': 0.44.1 + '@itwin/itwinui-css': 0.52.0 '@itwin/itwinui-icons-react': 1.8.0_react-dom@17.0.2+react@17.0.2 - '@itwin/itwinui-illustrations-react': 1.2.0_react-dom@17.0.2+react@17.0.2 + '@itwin/itwinui-illustrations-react': 1.3.0_react-dom@17.0.2+react@17.0.2 '@tippyjs/react': 4.2.6_react-dom@17.0.2+react@17.0.2 - '@types/react-table': 7.7.9 + '@types/react-table': 7.7.10 classnames: 2.3.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -7486,27 +7516,27 @@ packages: react-transition-group: 4.4.2_react-dom@17.0.2+react@17.0.2 dev: false - /@itwin/itwinui-react/1.29.3_react@17.0.2: - resolution: {integrity: sha512-c3W2DaGofVaZCe0Z6ldChFBy+GBqBXrMz0Ap6awBLX6FwHcFzwcOxBo0BaCWLoIFl8BFv94mbrRh9zkk1m7ZbA==} + /@itwin/itwinui-react/1.34.0_react@17.0.2: + resolution: {integrity: sha512-QSpd7TQFNEH9Y/yOGNxlhMDEJtpNxX/pBQWKCWpos4PnqOqpQaKnmeQuZgXxdJ8jytzyDxUVpNQsLxDOkyCJLQ==} peerDependencies: react: ^16.8.6 || ^17.0.0 react-dom: ^16.8.6 || ^17.0.0 dependencies: - '@itwin/itwinui-css': 0.44.1 + '@itwin/itwinui-css': 0.52.0 '@itwin/itwinui-icons-react': 1.8.0_react@17.0.2 - '@itwin/itwinui-illustrations-react': 1.2.0_react@17.0.2 + '@itwin/itwinui-illustrations-react': 1.3.0_react@17.0.2 '@tippyjs/react': 4.2.6_react@17.0.2 - '@types/react-table': 7.7.9 + '@types/react-table': 7.7.10 classnames: 2.3.1 react: 17.0.2 react-table: 7.7.0_react@17.0.2 react-transition-group: 4.4.2_react@17.0.2 dev: true - /@itwin/oidc-signin-tool/3.2.2: - resolution: {integrity: sha512-2tBDo+J4ORxTdHJf76zmpoGOq/l3RzlY3ofoxEQo4d+8b454gcHkxFQA9r/7xOF8qN+dOBaG/P60ZWsB3D/qug==} + /@itwin/oidc-signin-tool/3.3.0: + resolution: {integrity: sha512-mXY45oqbCD8WVaTw6Gae+ffS6Q5ULlGMelJu5jAspDPmZVfEeC98L51vsAYD+Vt3QNeV6hhQu3/Imm/uofpVVA==} dependencies: - '@itwin/certa': 3.0.0 + '@itwin/certa': 3.0.2 '@itwin/core-bentley': link:../../core/bentley dotenv: 10.0.0 dotenv-expand: 5.1.0 @@ -7518,10 +7548,10 @@ packages: - supports-color - utf-8-validate - /@itwin/oidc-signin-tool/3.2.2_electron@14.2.6: - resolution: {integrity: sha512-2tBDo+J4ORxTdHJf76zmpoGOq/l3RzlY3ofoxEQo4d+8b454gcHkxFQA9r/7xOF8qN+dOBaG/P60ZWsB3D/qug==} + /@itwin/oidc-signin-tool/3.3.0_electron@14.2.7: + resolution: {integrity: sha512-mXY45oqbCD8WVaTw6Gae+ffS6Q5ULlGMelJu5jAspDPmZVfEeC98L51vsAYD+Vt3QNeV6hhQu3/Imm/uofpVVA==} dependencies: - '@itwin/certa': 3.0.0_electron@14.2.6 + '@itwin/certa': 3.0.2_electron@14.2.7 '@itwin/core-bentley': link:../../core/bentley dotenv: 10.0.0 dotenv-expand: 5.1.0 @@ -7543,17 +7573,17 @@ packages: /@itwin/reality-data-client/0.7.0: resolution: {integrity: sha512-fUbS3953g3zXNagcgwmJ7n2DHvL15KlBQZ5NlpWpGdotRgtOKAxeJqybPJBnoM10dErmJVC+Cbv3JVc2Nar/Mw==} - peerDependencies: - '@itwin/core-common': ^3.0.0 dependencies: - '@itwin/core-geometry': 3.0.0 + '@itwin/core-bentley': link:../../core/bentley + '@itwin/core-common': link:../../core/common + '@itwin/core-geometry': link:../../core/geometry axios: 0.25.0 transitivePeerDependencies: - debug dev: false - /@itwin/service-authorization/0.6.1: - resolution: {integrity: sha512-vg/ajMS9YmBu7DFivpQBbBGFCb512UeiMw78nqMTkVj/T9CDeSEk0BurwZdAQUnosRRYm72BU0b5kYe7Sa6nSw==} + /@itwin/service-authorization/0.6.2: + resolution: {integrity: sha512-4zFhPwskE7rd6mlNPvzDLyfRR2EE2+dzknD7IAXSF+we+l5clLyGmsCV0Z5moFgPE0wa1TCXpkxKklQmhrzuCA==} peerDependencies: '@itwin/core-bentley': ^3.0.0 dependencies: @@ -7721,7 +7751,7 @@ packages: resolution: {integrity: sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@jest/types': 26.6.2 babel-plugin-istanbul: 6.1.1 chalk: 4.1.2 @@ -7771,7 +7801,7 @@ packages: /@loaders.gl/core/3.1.8: resolution: {integrity: sha512-y+dMqkWjnC7WnrSEMBMe5vVN6N6m+eQXaEdsE8QhuFZo/np9/HkSF3Fod1pYcmlATthp5dB1djYjzQeYR/njxw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@loaders.gl/loader-utils': 3.1.8 '@loaders.gl/worker-utils': 3.1.8 '@probe.gl/log': 3.5.0 @@ -7781,7 +7811,7 @@ packages: /@loaders.gl/draco/3.1.8: resolution: {integrity: sha512-urZAlh1qxu8p7hyRnsz9Z3oyXhRFWM5MZs87uolyFIhwpb8dPOKUr85jeL97EVsQW4bmhP7Y6SxYc7x5YnOgRw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@loaders.gl/loader-utils': 3.1.8 '@loaders.gl/schema': 3.1.8 '@loaders.gl/worker-utils': 3.1.8 @@ -7791,7 +7821,7 @@ packages: /@loaders.gl/loader-utils/3.1.8: resolution: {integrity: sha512-Lgyk6RZv9ekE0MUMAmEqiEr+p3G/1XPNmMs2boyiZNy/xjq6lyBIEIqh5vALqkUWgm6519fhHjeNNwYLWY3n+Q==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@loaders.gl/worker-utils': 3.1.8 '@probe.gl/stats': 3.5.0 dev: false @@ -7805,7 +7835,7 @@ packages: /@loaders.gl/worker-utils/3.1.8: resolution: {integrity: sha512-w2OK4EmKqQMKezgYBXii4sXczxrHf6sksYEoJUveJsZoCjN/8gGeV6X2G4Ll4TAGwOjBluSdqRNtWlU7xpV/Mw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false /@microsoft/api-extractor-model/7.7.2: @@ -7889,17 +7919,17 @@ packages: resolution: {integrity: sha512-e54kpi219wES2ijPzeHe1kMnT8VKH8YeTd1GAn9BzVBmutz3tBgcG1y8a4pziNr4vNjFnuD4W446Ua7ELnNDiA==} dependencies: '@types/base64-js': 1.3.0 - '@types/jquery': 3.5.13 + '@types/jquery': 3.5.14 base64-js: 1.5.1 - follow-redirects: 1.14.9_debug@4.3.3 + follow-redirects: 1.14.9_debug@4.3.4 form-data: 4.0.0 opener: 1.5.2 transitivePeerDependencies: - debug dev: false - /@opentelemetry/api/1.0.4: - resolution: {integrity: sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==} + /@opentelemetry/api/1.1.0: + resolution: {integrity: sha512-hf+3bwuBwtXsugA2ULBc95qxrOqP2pOekLz34BJhcAKawt94vfeNyUKpYc0lZQ/3sCP6LqRa7UAdHA7i5UODzQ==} engines: {node: '>=8.0.0'} dev: false @@ -7944,26 +7974,26 @@ packages: webpack-dev-server: 3.11.1_webpack@4.44.2 dev: true - /@popperjs/core/2.11.2: - resolution: {integrity: sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==} + /@popperjs/core/2.11.4: + resolution: {integrity: sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==} /@probe.gl/env/3.5.0: resolution: {integrity: sha512-YdlpZZshhyYxvWDBmZ5RIW2pTR14Pw4p9czMlt/v7F6HbFzWfAdmH7q6xVwFRYxUpQLwhWensWyv4aFysiWl4g==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false /@probe.gl/log/3.5.0: resolution: {integrity: sha512-nW/qz2X1xY08WU/TsmJP6/6IPNcaY5fS/vLjpC4ahJuE2Mezga4hGM/R2X5JWE/nkPc+BsC5GnAnD13rwAxS7g==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@probe.gl/env': 3.5.0 dev: false /@probe.gl/stats/3.5.0: resolution: {integrity: sha512-IH2M+F3c8HR1DTroBARePUFG7wIewumtKA0UFqx51Z7S4hKrD60wFbpMmg0AcF4FvHAXMBoC+kYi1UKW9XbAOw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false /@react-dnd/asap/4.0.0: @@ -7976,8 +8006,8 @@ packages: resolution: {integrity: sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==} dev: false - /@reduxjs/toolkit/1.7.2_react-redux@7.2.6+react@17.0.2: - resolution: {integrity: sha512-wwr3//Ar8ZhM9bS58O+HCIaMlR4Y6SNHfuszz9hKnQuFIKvwaL3Kmjo6fpDKUOjo4Lv54Yi299ed8rofCJ/Vjw==} + /@reduxjs/toolkit/1.8.0_react-redux@7.2.6+react@17.0.2: + resolution: {integrity: sha512-cdfHWfcvLyhBUDicoFwG1u32JqvwKDxLxDd7zSmSoFw/RhYLOygIRtmaMjPRUUHmVmmAGAvquLLsKKU/677kSQ==} peerDependencies: react: ^16.9.0 || ^17.0.0 || 18.0.0-beta react-redux: ^7.2.1 || ^8.0.0-beta @@ -8015,7 +8045,7 @@ packages: rollup: ^1.20.0 || ^2.0.0 dependencies: '@rollup/pluginutils': 3.1.0_rollup@1.32.1 - magic-string: 0.25.7 + magic-string: 0.25.9 rollup: 1.32.1 dev: true @@ -8035,8 +8065,8 @@ packages: resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==} engines: {node: '>=6'} - /@sindresorhus/is/4.4.0: - resolution: {integrity: sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==} + /@sindresorhus/is/4.6.0: + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} /@sinonjs/commons/1.8.3: @@ -8063,7 +8093,7 @@ packages: resolution: {integrity: sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==} dependencies: ejs: 2.7.4 - magic-string: 0.25.7 + magic-string: 0.25.9 dev: true /@svgdotjs/svg.js/3.0.13: @@ -8146,7 +8176,7 @@ packages: resolution: {integrity: sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==} engines: {node: '>=10'} dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@svgr/babel-preset': 5.5.0 '@svgr/hast-util-to-babel-ast': 5.5.0 svg-parser: 2.0.4 @@ -8168,7 +8198,7 @@ packages: engines: {node: '>=10'} dependencies: '@babel/core': 7.12.3 - '@babel/plugin-transform-react-constant-elements': 7.16.7_@babel+core@7.12.3 + '@babel/plugin-transform-react-constant-elements': 7.17.6_@babel+core@7.12.3 '@babel/preset-env': 7.16.11_@babel+core@7.12.3 '@babel/preset-react': 7.16.7_@babel+core@7.12.3 '@svgr/core': 5.5.0 @@ -8196,14 +8226,13 @@ packages: engines: {node: '>=12'} dependencies: '@babel/code-frame': 7.16.7 - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@types/aria-query': 4.2.2 aria-query: 5.0.0 chalk: 4.1.2 - dom-accessibility-api: 0.5.11 + dom-accessibility-api: 0.5.13 lz-string: 1.4.4 pretty-format: 27.5.1 - dev: true /@testing-library/react-hooks/7.0.2_fc2bb8a5b006d3f25c5f84ea777e678d: resolution: {integrity: sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==} @@ -8218,9 +8247,9 @@ packages: react-test-renderer: optional: true dependencies: - '@babel/runtime': 7.17.2 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@babel/runtime': 7.17.8 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/react-test-renderer': 17.0.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -8240,9 +8269,9 @@ packages: react-test-renderer: optional: true dependencies: - '@babel/runtime': 7.17.2 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@babel/runtime': 7.17.8 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/react-test-renderer': 17.0.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -8262,38 +8291,37 @@ packages: react-test-renderer: optional: true dependencies: - '@babel/runtime': 7.17.2 - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@babel/runtime': 7.17.8 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/react-test-renderer': 17.0.1 react: 17.0.2 react-error-boundary: 3.1.4_react@17.0.2 dev: true - /@testing-library/react/12.1.3_react-dom@17.0.2+react@17.0.2: - resolution: {integrity: sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg==} + /@testing-library/react/12.1.4_react-dom@17.0.2+react@17.0.2: + resolution: {integrity: sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA==} engines: {node: '>=12'} peerDependencies: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@testing-library/dom': 8.11.3 - '@types/react-dom': 17.0.11 + '@types/react-dom': 17.0.14 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 - dev: true - /@testing-library/react/12.1.3_react@17.0.2: - resolution: {integrity: sha512-oCULRXWRrBtC9m6G/WohPo1GLcLesH7T4fuKzRAKn1CWVu9BzXtqLXDDTA6KhFNNtRwLtfSMr20HFl+Qrdrvmg==} + /@testing-library/react/12.1.4_react@17.0.2: + resolution: {integrity: sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA==} engines: {node: '>=12'} peerDependencies: react: '*' react-dom: '*' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@testing-library/dom': 8.11.3 - '@types/react-dom': 17.0.11 + '@types/react-dom': 17.0.14 react: 17.0.2 dev: true @@ -8303,7 +8331,7 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: true /@tippyjs/react/4.2.6_react-dom@17.0.2+react@17.0.2: @@ -8341,12 +8369,11 @@ packages: /@types/aria-query/4.2.2: resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} - dev: true - /@types/babel__core/7.1.18: - resolution: {integrity: sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==} + /@types/babel__core/7.1.19: + resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} dependencies: - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 @@ -8362,7 +8389,7 @@ packages: /@types/babel__template/7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.8 '@babel/types': 7.17.0 dev: true @@ -8396,7 +8423,7 @@ packages: resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==} dependencies: '@types/http-cache-semantics': 4.0.1 - '@types/keyv': 3.1.3 + '@types/keyv': 3.1.4 '@types/node': 14.14.31 '@types/responselike': 1.0.0 @@ -8479,21 +8506,21 @@ packages: resolution: {integrity: sha512-jDKoZiiMA3lGO3skSO7dfqEHNvmiTLLV+PHD9EBQVlJANJvpY6qq1zzjRI24ZOtG7F+CS7BVWDXKewRmN8PjHQ==} dependencies: '@types/cheerio': 0.22.31 - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true /@types/eslint/7.2.14: resolution: {integrity: sha512-pESyhSbUOskqrGcaN+bCXIQDyT5zTaRWfj5ZjjSlMatgGjIn3QQPfocAu4WSabUR7CGyLZ2CQaZyISOEX7/saw==} dependencies: '@types/estree': 0.0.51 - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 dev: true /@types/eslint/7.29.0: resolution: {integrity: sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==} dependencies: '@types/estree': 0.0.51 - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 dev: true /@types/estree/0.0.39: @@ -8583,7 +8610,7 @@ packages: /@types/hoist-non-react-statics/3.3.1: resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 hoist-non-react-statics: 3.3.2 /@types/html-minifier-terser/5.1.2: @@ -8617,8 +8644,8 @@ packages: '@types/istanbul-lib-report': 3.0.0 dev: true - /@types/jquery/3.5.13: - resolution: {integrity: sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg==} + /@types/jquery/3.5.14: + resolution: {integrity: sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==} dependencies: '@types/sizzle': 2.3.3 dev: false @@ -8631,8 +8658,8 @@ packages: parse5: 4.0.0 dev: false - /@types/json-schema/7.0.9: - resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} + /@types/json-schema/7.0.10: + resolution: {integrity: sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A==} /@types/json5/0.0.29: resolution: {integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4=} @@ -8643,8 +8670,8 @@ packages: '@types/node': 14.14.31 dev: true - /@types/keyv/3.1.3: - resolution: {integrity: sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==} + /@types/keyv/3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: '@types/node': 14.14.31 @@ -8652,8 +8679,8 @@ packages: resolution: {integrity: sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw==} dev: true - /@types/lodash/4.14.178: - resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==} + /@types/lodash/4.14.180: + resolution: {integrity: sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==} dev: true /@types/lolex/2.1.3: @@ -8740,76 +8767,76 @@ packages: /@types/react-autosuggest/10.1.2: resolution: {integrity: sha512-K23lmXhC3Bbd8y/jm5+wYrw/NAeN4U/wlHTgAEBIwLOyQKFCFYA3ONKte9P21L+RGIXRP8UlzHOSRtmIZw5Nqw==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true /@types/react-beautiful-dnd/12.1.5: resolution: {integrity: sha512-UHSjLoRsPBRX81FMRmNwIFT0hSjPW0BayEFCcMhz1f3WsXEiYytR09WAzkBqvytJHzSL25ooCBA2DSjK6m1Qow==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true /@types/react-data-grid/4.0.2: resolution: {integrity: sha512-no7HnLfm5CSLicuLixZjgsfq0myt6+aBxyVCIo9XiJdNLiZUC0uogMa2f4wq+xdTaslYHeyzwsVL6KF0B765Yg==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true - /@types/react-dom/17.0.11: - resolution: {integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==} + /@types/react-dom/17.0.14: + resolution: {integrity: sha512-H03xwEP1oXmSfl3iobtmQ/2dHF5aBHr8aUMwyGZya6OW45G+xtdzmq6HkncefiBt5JU8DVyaWl/nWZbjZCnzAQ==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 /@types/react-highlight-words/0.16.4: resolution: {integrity: sha512-KITBX3xzheQLu2s3bUgLmRE7ekmhc52zRjRTwkKayQARh30L4fjEGzGm7ULK9TuX2LgxWWavZqyQGDGjAHbL3w==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true - /@types/react-redux/7.1.22: - resolution: {integrity: sha512-GxIA1kM7ClU73I6wg9IRTVwSO9GS+SAKZKe0Enj+82HMU6aoESFU2HNAdNi3+J53IaOHPiUfT3kSG4L828joDQ==} + /@types/react-redux/7.1.23: + resolution: {integrity: sha512-D02o3FPfqQlfu2WeEYwh3x2otYd2Dk1o8wAfsA0B1C2AJEFxE663Ozu7JzuWbznGgW248NaOF6wsqCGNq9d3qw==} dependencies: '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 17.0.39 + '@types/react': 17.0.41 hoist-non-react-statics: 3.3.2 redux: 4.1.2 /@types/react-select/3.0.26: resolution: {integrity: sha512-rAaiD0SFkBi3PUwp1DrJV04CobPl2LuZXF+kv6MKw8kaeGo82xTOZzjM8DDi4lrdkqGbInZiE2QO9nIJm3bqgw==} dependencies: - '@types/react': 17.0.39 - '@types/react-dom': 17.0.11 + '@types/react': 17.0.41 + '@types/react-dom': 17.0.14 '@types/react-transition-group': 4.4.4 dev: true - /@types/react-table/7.7.9: - resolution: {integrity: sha512-ejP/J20Zlj9VmuLh73YgYkW2xOSFTW39G43rPH93M4mYWdMmqv66lCCr+axZpkdtlNLGjvMG2CwzT4S6abaeGQ==} + /@types/react-table/7.7.10: + resolution: {integrity: sha512-yt7FHv/2cFsucStSWLBOB3OmsRZF08DvVHzz8Zg41B4tzRL6pQ+5VYvmhaR1dKS//tDG4UOJ1RQJPEINHYoRtg==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 /@types/react-test-renderer/17.0.1: resolution: {integrity: sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 /@types/react-transition-group/4.4.4: resolution: {integrity: sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true /@types/react-window/1.8.5: resolution: {integrity: sha512-V9q3CvhC9Jk9bWBOysPGaWy/Z0lxYcTXLtLipkt2cnRj1JOSFNF7wqGpkScSXMgBwC+fnVRg/7shwgddBG5ICw==} dependencies: - '@types/react': 17.0.39 + '@types/react': 17.0.41 dev: true - /@types/react/17.0.39: - resolution: {integrity: sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==} + /@types/react/17.0.41: + resolution: {integrity: sha512-chYZ9ogWUodyC7VUTRBfblysKLjnohhFY9bGLwvnUFFy48+vB9DikmB3lW0qTFmBcKSzmdglcvkHK71IioOlDA==} dependencies: '@types/prop-types': 15.7.4 '@types/scheduler': 0.16.2 - csstype: 3.0.10 + csstype: 3.0.11 /@types/resize-observer-browser/0.1.7: resolution: {integrity: sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg==} @@ -8904,8 +8931,8 @@ packages: '@types/node': 14.14.31 dev: true - /@types/supertest/2.0.11: - resolution: {integrity: sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==} + /@types/supertest/2.0.12: + resolution: {integrity: sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==} dependencies: '@types/superagent': 4.1.15 dev: true @@ -8938,6 +8965,10 @@ packages: resolution: {integrity: sha512-hKB88y3YHL8oPOs/CNlaXtjWn93+Bs48sDQR37ZUqG2tLeCS7EA1cmnkKsuQsub9OKEB/y/Rw9zqJqqNSbqVlQ==} dev: true + /@types/validator/13.7.1: + resolution: {integrity: sha512-I6OUIZ5cYRk5lp14xSOAiXjWrfVoMZVjDuevBYgQDYzZIjsf2CAISpEcXOkFAtpAHbmWIDLcZObejqny/9xq5Q==} + dev: false + /@types/webpack-sources/0.1.9: resolution: {integrity: sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new==} dependencies: @@ -8963,8 +8994,8 @@ packages: '@types/node': 14.14.31 dev: true - /@types/yargs-parser/20.2.1: - resolution: {integrity: sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==} + /@types/yargs-parser/21.0.0: + resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: true /@types/yargs/12.0.20: @@ -8974,7 +9005,7 @@ packages: /@types/yargs/15.0.14: resolution: {integrity: sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==} dependencies: - '@types/yargs-parser': 20.2.1 + '@types/yargs-parser': 21.0.0 dev: true /@types/yauzl/2.9.2: @@ -8984,6 +9015,32 @@ packages: '@types/node': 14.14.31 optional: true + /@typescript-eslint/eslint-plugin/4.26.0_254a60bd907cee05fd203cdf9e9086f0: + resolution: {integrity: sha512-yA7IWp+5Qqf+TLbd8b35ySFOFzUfL7i+4If50EqvjT6w35X8Lv0eBHb6rATeWmucks37w+zV+tWnOXI9JlG6Eg==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + '@typescript-eslint/parser': ^4.0.0 + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/experimental-utils': 4.26.0_eslint@7.32.0+typescript@4.4.4 + '@typescript-eslint/parser': 4.26.0_eslint@7.32.0+typescript@4.4.4 + '@typescript-eslint/scope-manager': 4.26.0 + debug: 4.3.4 + eslint: 7.32.0 + functional-red-black-tree: 1.0.1 + lodash: 4.17.21 + regexpp: 3.2.0 + semver: 7.3.5 + tsutils: 3.21.0_typescript@4.4.4 + typescript: 4.4.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/eslint-plugin/4.31.2_8f0416aa8ec58a469909c5c0f73069bc: resolution: {integrity: sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==} engines: {node: ^10.12.0 || >=12.0.0} @@ -8998,7 +9055,7 @@ packages: '@typescript-eslint/experimental-utils': 4.31.2_eslint@7.32.0+typescript@4.4.4 '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.4 '@typescript-eslint/scope-manager': 4.31.2 - debug: 4.3.3 + debug: 4.3.4 eslint: 7.32.0 functional-red-black-tree: 1.0.1 regexpp: 3.2.0 @@ -9007,6 +9064,7 @@ packages: typescript: 4.4.4 transitivePeerDependencies: - supports-color + dev: false /@typescript-eslint/experimental-utils/3.10.1_eslint@7.32.0+typescript@4.4.4: resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==} @@ -9014,7 +9072,7 @@ packages: peerDependencies: eslint: '*' dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 '@typescript-eslint/types': 3.10.1 '@typescript-eslint/typescript-estree': 3.10.1_typescript@4.4.4 eslint: 7.32.0 @@ -9024,13 +9082,31 @@ packages: - supports-color - typescript + /@typescript-eslint/experimental-utils/4.26.0_eslint@7.32.0+typescript@4.4.4: + resolution: {integrity: sha512-TH2FO2rdDm7AWfAVRB5RSlbUhWxGVuxPNzGT7W65zVfl8H/WeXTk1e69IrcEVsBslrQSTDKQSaJD89hwKrhdkw==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: '*' + dependencies: + '@types/json-schema': 7.0.10 + '@typescript-eslint/scope-manager': 4.26.0 + '@typescript-eslint/types': 4.26.0 + '@typescript-eslint/typescript-estree': 4.26.0_typescript@4.4.4 + eslint: 7.32.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0_eslint@7.32.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/experimental-utils/4.31.2_eslint@7.32.0+typescript@4.4.4: resolution: {integrity: sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: eslint: '*' dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 '@typescript-eslint/scope-manager': 4.31.2 '@typescript-eslint/types': 4.31.2 '@typescript-eslint/typescript-estree': 4.31.2_typescript@4.4.4 @@ -9040,6 +9116,7 @@ packages: transitivePeerDependencies: - supports-color - typescript + dev: false /@typescript-eslint/experimental-utils/4.33.0_eslint@7.32.0+typescript@4.4.4: resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==} @@ -9047,7 +9124,7 @@ packages: peerDependencies: eslint: '*' dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 '@typescript-eslint/scope-manager': 4.33.0 '@typescript-eslint/types': 4.33.0 '@typescript-eslint/typescript-estree': 4.33.0_typescript@4.4.4 @@ -9059,6 +9136,26 @@ packages: - typescript dev: true + /@typescript-eslint/parser/4.26.0_eslint@7.32.0+typescript@4.4.4: + resolution: {integrity: sha512-b4jekVJG9FfmjUfmM4VoOItQhPlnt6MPOBUL0AQbiTmm+SSpSdhHYlwayOm4IW9KLI/4/cRKtQCmDl1oE2OlPg==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 4.26.0 + '@typescript-eslint/types': 4.26.0 + '@typescript-eslint/typescript-estree': 4.26.0_typescript@4.4.4 + debug: 4.3.4 + eslint: 7.32.0 + typescript: 4.4.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser/4.31.2_eslint@7.32.0+typescript@4.4.4: resolution: {integrity: sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw==} engines: {node: ^10.12.0 || >=12.0.0} @@ -9072,11 +9169,20 @@ packages: '@typescript-eslint/scope-manager': 4.31.2 '@typescript-eslint/types': 4.31.2 '@typescript-eslint/typescript-estree': 4.31.2_typescript@4.4.4 - debug: 4.3.3 + debug: 4.3.4 eslint: 7.32.0 typescript: 4.4.4 transitivePeerDependencies: - supports-color + dev: false + + /@typescript-eslint/scope-manager/4.26.0: + resolution: {integrity: sha512-G6xB6mMo4xVxwMt5lEsNTz3x4qGDt0NSGmTBNBPJxNsrTXJSm21c6raeYroS2OwQsOyIXqKZv266L/Gln1BWqg==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dependencies: + '@typescript-eslint/types': 4.26.0 + '@typescript-eslint/visitor-keys': 4.26.0 + dev: true /@typescript-eslint/scope-manager/4.31.2: resolution: {integrity: sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==} @@ -9084,6 +9190,7 @@ packages: dependencies: '@typescript-eslint/types': 4.31.2 '@typescript-eslint/visitor-keys': 4.31.2 + dev: false /@typescript-eslint/scope-manager/4.33.0: resolution: {integrity: sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==} @@ -9097,6 +9204,11 @@ packages: resolution: {integrity: sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + /@typescript-eslint/types/4.26.0: + resolution: {integrity: sha512-rADNgXl1kS/EKnDr3G+m7fB9yeJNnR9kF7xMiXL6mSIWpr3Wg5MhxyfEXy/IlYthsqwBqHOr22boFbf/u6O88A==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dev: true + /@typescript-eslint/types/4.31.2: resolution: {integrity: sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} @@ -9117,7 +9229,7 @@ packages: dependencies: '@typescript-eslint/types': 3.10.1 '@typescript-eslint/visitor-keys': 3.10.1 - debug: 4.3.3 + debug: 4.3.4 glob: 7.2.0 is-glob: 4.0.3 lodash: 4.17.21 @@ -9127,6 +9239,27 @@ packages: transitivePeerDependencies: - supports-color + /@typescript-eslint/typescript-estree/4.26.0_typescript@4.4.4: + resolution: {integrity: sha512-GHUgahPcm9GfBuy3TzdsizCcPjKOAauG9xkz9TR8kOdssz2Iz9jRCSQm6+aVFa23d5NcSpo1GdHGSQKe0tlcbg==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 4.26.0 + '@typescript-eslint/visitor-keys': 4.26.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.3.5 + tsutils: 3.21.0_typescript@4.4.4 + typescript: 4.4.4 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/typescript-estree/4.31.2_typescript@4.4.4: resolution: {integrity: sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==} engines: {node: ^10.12.0 || >=12.0.0} @@ -9138,7 +9271,7 @@ packages: dependencies: '@typescript-eslint/types': 4.31.2 '@typescript-eslint/visitor-keys': 4.31.2 - debug: 4.3.3 + debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.5 @@ -9158,7 +9291,7 @@ packages: dependencies: '@typescript-eslint/types': 4.33.0 '@typescript-eslint/visitor-keys': 4.33.0 - debug: 4.3.3 + debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.5 @@ -9174,6 +9307,14 @@ packages: dependencies: eslint-visitor-keys: 1.3.0 + /@typescript-eslint/visitor-keys/4.26.0: + resolution: {integrity: sha512-cw4j8lH38V1ycGBbF+aFiLUls9Z0Bw8QschP3mkth50BbWzgFS33ISIgBzUMuQ2IdahoEv/rXstr8Zhlz4B1Zg==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + dependencies: + '@typescript-eslint/types': 4.26.0 + eslint-visitor-keys: 2.1.0 + dev: true + /@typescript-eslint/visitor-keys/4.31.2: resolution: {integrity: sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==} engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} @@ -9192,10 +9333,6 @@ packages: /@ungap/promise-all-settled/1.1.2: resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} - /@ungap/url-search-params/0.1.4: - resolution: {integrity: sha512-RLwrxCTDNiNev9hpr9rDq8NyeQ8Nn0X1we4Wu7Tlf368I8r+7hBj3uObhifhuLk74egaYaSX5nUsBlWz6kjj+A==} - dev: false - /@webassemblyjs/ast/1.8.5: resolution: {integrity: sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==} dependencies: @@ -9501,7 +9638,7 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} dependencies: - mime-types: 2.1.34 + mime-types: 2.1.35 negotiator: 0.6.3 /acorn-globals/6.0.0: @@ -9559,15 +9696,15 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color - /agentkeepalive/4.2.0: - resolution: {integrity: sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==} + /agentkeepalive/4.2.1: + resolution: {integrity: sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==} engines: {node: '>= 8.0.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 depd: 1.1.2 humanize-ms: 1.2.1 transitivePeerDependencies: @@ -9612,8 +9749,8 @@ packages: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - /ajv/8.10.0: - resolution: {integrity: sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==} + /ajv/8.11.0: + resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -9669,8 +9806,8 @@ packages: resolution: {integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=} engines: {node: '>=4'} - /ansi-regex/4.1.0: - resolution: {integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==} + /ansi-regex/4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} engines: {node: '>=6'} dev: true @@ -9697,7 +9834,6 @@ packages: /ansi-styles/5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - dev: true /anymatch/2.0.0: resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} @@ -9753,13 +9889,12 @@ packages: resolution: {integrity: sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==} engines: {node: '>=6.0'} dependencies: - '@babel/runtime': 7.17.2 - '@babel/runtime-corejs3': 7.17.2 + '@babel/runtime': 7.17.8 + '@babel/runtime-corejs3': 7.17.8 /aria-query/5.0.0: resolution: {integrity: sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==} engines: {node: '>=6.0'} - dev: true /arity-n/1.0.4: resolution: {integrity: sha1-2edrEXM+CFacCEeuezmyhgswt0U=} @@ -9917,7 +10052,7 @@ packages: hasBin: true dependencies: browserslist: 3.2.8 - caniuse-lite: 1.0.30001312 + caniuse-lite: 1.0.30001319 normalize-range: 0.1.2 num2fraction: 1.2.2 postcss: 6.0.23 @@ -9928,8 +10063,8 @@ packages: resolution: {integrity: sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==} hasBin: true dependencies: - browserslist: 4.19.2 - caniuse-lite: 1.0.30001312 + browserslist: 4.20.2 + caniuse-lite: 1.0.30001319 normalize-range: 0.1.2 num2fraction: 1.2.2 picocolors: 0.2.1 @@ -9954,41 +10089,42 @@ packages: - debug dev: false - /axios/0.24.0: - resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} + /axios/0.25.0: + resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: - follow-redirects: 1.14.9_debug@4.3.3 + follow-redirects: 1.14.9_debug@4.3.4 transitivePeerDependencies: - debug - dev: false - /axios/0.25.0: - resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} + /axios/0.26.1: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} dependencies: - follow-redirects: 1.14.9_debug@4.3.3 + follow-redirects: 1.14.9_debug@4.3.4 transitivePeerDependencies: - debug + dev: false /axobject-query/2.2.0: resolution: {integrity: sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==} - /azurite/3.15.0: - resolution: {integrity: sha512-NkzcJnUXV/k8xqlDWEsN+1BamH3ksy7oQjr+ItUjehk1TqxwHzl5VnDhefVtZY1ccuPRdbZPkqL4uzQTwcluKA==} + /azurite/3.16.0: + resolution: {integrity: sha512-E/l9W6bEk8oMoOhhqUVjcVU1HnoL+03XMWlKM0ogDBwLgHAVF0S5JEQP8Mhez8kHC/SYSyWaNEjVVFtMztE0cA==} engines: {node: '>=10.0.0', vscode: ^1.39.0} hasBin: true dependencies: '@azure/ms-rest-js': 1.11.2 args: 5.0.1 - axios: 0.24.0 + axios: 0.26.1 etag: 1.8.1 express: 4.17.3 + fs-extra: 8.1.0 jsonwebtoken: 8.5.1 lokijs: 1.5.12 morgan: 1.10.0 multistream: 2.1.1 mysql2: 2.3.3 rimraf: 3.0.2 - sequelize: 6.16.2_mysql2@2.3.3+tedious@14.3.0 + sequelize: 6.17.0_mysql2@2.3.3+tedious@14.3.0 tedious: 14.3.0 to-readable-stream: 2.1.0 tslib: 2.3.1 @@ -10024,7 +10160,7 @@ packages: eslint: '>= 4.12.1' dependencies: '@babel/code-frame': 7.16.7 - '@babel/parser': 7.17.3 + '@babel/parser': 7.17.8 '@babel/traverse': 7.17.3 '@babel/types': 7.17.0 eslint: 7.32.0 @@ -10063,7 +10199,7 @@ packages: '@babel/core': 7.12.3 '@jest/transform': 26.6.2 '@jest/types': 26.6.2 - '@types/babel__core': 7.1.18 + '@types/babel__core': 7.1.19 babel-plugin-istanbul: 6.1.1 babel-preset-jest: 26.6.2_@babel+core@7.12.3 chalk: 4.1.2 @@ -10073,18 +10209,18 @@ packages: - supports-color dev: true - /babel-jest/26.6.3_@babel+core@7.17.5: + /babel-jest/26.6.3_@babel+core@7.17.8: resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==} engines: {node: '>= 10.14.2'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@jest/transform': 26.6.2 '@jest/types': 26.6.2 - '@types/babel__core': 7.1.18 + '@types/babel__core': 7.1.19 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 26.6.2_@babel+core@7.17.5 + babel-preset-jest: 26.6.2_@babel+core@7.17.8 chalk: 4.1.2 graceful-fs: 4.2.9 slash: 3.0.0 @@ -10102,7 +10238,7 @@ packages: '@babel/core': 7.12.3 find-cache-dir: 2.1.0 loader-utils: 1.4.0 - mkdirp: 0.5.5 + mkdirp: 0.5.6 pify: 4.0.1 schema-utils: 2.7.1 webpack: 4.44.2 @@ -10158,14 +10294,14 @@ packages: dependencies: '@babel/template': 7.16.7 '@babel/types': 7.17.0 - '@types/babel__core': 7.1.18 + '@types/babel__core': 7.1.19 '@types/babel__traverse': 7.14.2 dev: true /babel-plugin-macros/2.8.0: resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 cosmiconfig: 6.0.0 resolve: 1.19.0 dev: false @@ -10174,7 +10310,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 cosmiconfig: 7.0.1 resolve: 1.19.0 dev: true @@ -10192,7 +10328,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 + '@babel/compat-data': 7.17.7 '@babel/core': 7.12.3 '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.12.3 semver: 6.3.0 @@ -10200,14 +10336,14 @@ packages: - supports-color dev: true - /babel-plugin-polyfill-corejs2/0.3.1_@babel+core@7.17.5: + /babel-plugin-polyfill-corejs2/0.3.1_@babel+core@7.17.8: resolution: {integrity: sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.17.0 - '@babel/core': 7.17.5 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.5 + '@babel/compat-data': 7.17.7 + '@babel/core': 7.17.8 + '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.8 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -10225,13 +10361,13 @@ packages: - supports-color dev: true - /babel-plugin-polyfill-corejs3/0.5.2_@babel+core@7.17.5: + /babel-plugin-polyfill-corejs3/0.5.2_@babel+core@7.17.8: resolution: {integrity: sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.8 core-js-compat: 3.21.1 transitivePeerDependencies: - supports-color @@ -10248,13 +10384,13 @@ packages: - supports-color dev: true - /babel-plugin-polyfill-regenerator/0.3.1_@babel+core@7.17.5: + /babel-plugin-polyfill-regenerator/0.3.1_@babel+core@7.17.8: resolution: {integrity: sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.17.5 - '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/helper-define-polyfill-provider': 0.3.1_@babel+core@7.17.8 transitivePeerDependencies: - supports-color dev: true @@ -10302,24 +10438,24 @@ packages: '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.12.3 dev: true - /babel-preset-current-node-syntax/1.0.1_@babel+core@7.17.5: + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.17.8: resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.5 - '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.5 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.17.5 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.5 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.5 + '@babel/core': 7.17.8 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.17.8 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.17.8 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.17.8 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.17.8 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.17.8 dev: true /babel-preset-jest/26.6.2_@babel+core@7.12.3: @@ -10333,34 +10469,34 @@ packages: babel-preset-current-node-syntax: 1.0.1_@babel+core@7.12.3 dev: true - /babel-preset-jest/26.6.2_@babel+core@7.17.5: + /babel-preset-jest/26.6.2_@babel+core@7.17.8: resolution: {integrity: sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==} engines: {node: '>= 10.14.2'} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 babel-plugin-jest-hoist: 26.6.2 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.17.5 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.17.8 dev: true /babel-preset-react-app/10.0.1: resolution: {integrity: sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==} dependencies: - '@babel/core': 7.17.5 - '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-decorators': 7.17.2_@babel+core@7.17.5 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.17.5 - '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.17.5 - '@babel/plugin-transform-runtime': 7.17.0_@babel+core@7.17.5 - '@babel/preset-env': 7.16.11_@babel+core@7.17.5 - '@babel/preset-react': 7.16.7_@babel+core@7.17.5 - '@babel/preset-typescript': 7.16.7_@babel+core@7.17.5 - '@babel/runtime': 7.17.2 + '@babel/core': 7.17.8 + '@babel/plugin-proposal-class-properties': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-decorators': 7.17.8_@babel+core@7.17.8 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-numeric-separator': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-optional-chaining': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-proposal-private-methods': 7.16.11_@babel+core@7.17.8 + '@babel/plugin-transform-flow-strip-types': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-react-display-name': 7.16.7_@babel+core@7.17.8 + '@babel/plugin-transform-runtime': 7.17.0_@babel+core@7.17.8 + '@babel/preset-env': 7.16.11_@babel+core@7.17.8 + '@babel/preset-react': 7.16.7_@babel+core@7.17.8 + '@babel/preset-typescript': 7.16.7_@babel+core@7.17.8 + '@babel/runtime': 7.17.8 babel-plugin-macros: 3.1.0 babel-plugin-transform-react-remove-prop-types: 0.4.24 transitivePeerDependencies: @@ -10565,6 +10701,12 @@ packages: balanced-match: 1.0.2 concat-map: 0.0.1 + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + /braces/2.3.2: resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} engines: {node: '>=0.10.0'} @@ -10649,8 +10791,8 @@ packages: resolution: {integrity: sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==} hasBin: true dependencies: - caniuse-lite: 1.0.30001312 - electron-to-chromium: 1.4.71 + caniuse-lite: 1.0.30001319 + electron-to-chromium: 1.4.89 dev: true /browserslist/4.14.2: @@ -10658,19 +10800,19 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001312 - electron-to-chromium: 1.4.71 + caniuse-lite: 1.0.30001319 + electron-to-chromium: 1.4.89 escalade: 3.1.1 node-releases: 1.1.77 dev: true - /browserslist/4.19.2: - resolution: {integrity: sha512-97XU1CTZ5TwU9Qy/Taj+RtiI6SQM1WIhZ9osT7EY0oO2aWXGABZT2OZeRL+6PfaQsiiMIjjwIoYFPq4APgspgQ==} + /browserslist/4.20.2: + resolution: {integrity: sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001312 - electron-to-chromium: 1.4.71 + caniuse-lite: 1.0.30001319 + electron-to-chromium: 1.4.89 escalade: 3.1.1 node-releases: 2.0.2 picocolors: 1.0.0 @@ -10753,7 +10895,7 @@ packages: infer-owner: 1.0.4 lru-cache: 5.1.1 mississippi: 3.0.0 - mkdirp: 0.5.5 + mkdirp: 0.5.6 move-concurrently: 1.0.1 promise-inflight: 1.0.1 rimraf: 2.7.1 @@ -10906,14 +11048,14 @@ packages: /caniuse-api/3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: - browserslist: 4.19.2 - caniuse-lite: 1.0.30001312 + browserslist: 4.20.2 + caniuse-lite: 1.0.30001319 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: true - /caniuse-lite/1.0.30001312: - resolution: {integrity: sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==} + /caniuse-lite/1.0.30001319: + resolution: {integrity: sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==} /capture-exit/2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} @@ -11040,7 +11182,7 @@ packages: css-select: 4.2.1 css-what: 5.1.0 domelementtype: 2.2.0 - domhandler: 4.3.0 + domhandler: 4.3.1 domutils: 2.8.0 dev: true @@ -11050,7 +11192,7 @@ packages: dependencies: cheerio-select: 1.5.0 dom-serializer: 1.3.2 - domhandler: 4.3.0 + domhandler: 4.3.1 htmlparser2: 6.1.0 parse5: 6.0.1 parse5-htmlparser2-tree-adapter: 6.0.1 @@ -11114,14 +11256,15 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - /chrome-launcher/0.10.7: - resolution: {integrity: sha512-IoQLp64s2n8OQuvKZwt77CscVj3UlV2Dj7yZtd1EBMld9mSdGcsGy9fN5hd/r4vJuWZR09it78n1+A17gB+AIQ==} + /chrome-launcher/0.15.0: + resolution: {integrity: sha512-ZQqX5kb9H0+jy1OqLnWampfocrtSZaGl7Ny3F9GRha85o4odbL8x55paUzh51UC7cEmZ5obp3H2Mm70uC2PpRA==} + engines: {node: '>=12.13.0'} + hasBin: true dependencies: '@types/node': 14.14.31 - is-wsl: 1.1.0 + escape-string-regexp: 4.0.0 + is-wsl: 2.2.0 lighthouse-logger: 1.3.0 - mkdirp: 0.5.1 - rimraf: 2.7.1 dev: true /chrome-trace-event/1.0.3: @@ -11342,7 +11485,7 @@ packages: resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} engines: {node: '>= 0.6'} dependencies: - mime-db: 1.51.0 + mime-db: 1.52.0 dev: true /compression/1.7.4: @@ -11465,7 +11608,7 @@ packages: aproba: 1.2.0 fs-write-stream-atomic: 1.0.10 iferr: 0.1.5 - mkdirp: 0.5.5 + mkdirp: 0.5.6 rimraf: 2.7.1 run-queue: 1.0.3 @@ -11516,7 +11659,7 @@ packages: /core-js-compat/3.21.1: resolution: {integrity: sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 semver: 7.0.0 dev: true @@ -11576,9 +11719,9 @@ packages: dependencies: co: 4.6.0 debounce: 1.2.1 - debug: 4.3.3 + debug: 4.3.4 duplexer: 0.1.2 - fs-extra: 10.0.0 + fs-extra: 10.0.1 glob: 7.2.0 glob2base: 0.0.12 minimatch: 3.1.2 @@ -11732,7 +11875,7 @@ packages: postcss-modules-values: 3.0.0 postcss-value-parser: 4.2.0 schema-utils: 2.7.1 - semver: 7.3.2 + semver: 7.3.5 webpack: 4.44.2 dev: true @@ -11762,7 +11905,7 @@ packages: dependencies: boolbase: 1.0.0 css-what: 5.1.0 - domhandler: 4.3.0 + domhandler: 4.3.1 domutils: 2.8.0 nth-check: 2.0.1 dev: true @@ -11912,12 +12055,12 @@ packages: cssom: 0.3.8 dev: true - /csstype/2.6.19: - resolution: {integrity: sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==} + /csstype/2.6.20: + resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==} dev: false - /csstype/3.0.10: - resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} + /csstype/3.0.11: + resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} /cyclist/1.0.1: resolution: {integrity: sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=} @@ -11925,7 +12068,7 @@ packages: /d/1.0.1: resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} dependencies: - es5-ext: 0.10.53 + es5-ext: 0.10.59 type: 1.2.0 dev: true @@ -11979,8 +12122,8 @@ packages: ms: 2.1.2 supports-color: 8.1.1 - /debug/4.3.3: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -11990,8 +12133,8 @@ packages: dependencies: ms: 2.1.2 - /debug/4.3.3_supports-color@6.1.0: - resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} + /debug/4.3.4_supports-color@6.1.0: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -12293,9 +12436,8 @@ packages: dependencies: esutils: 2.0.3 - /dom-accessibility-api/0.5.11: - resolution: {integrity: sha512-7X6GvzjYf4yTdRKuCVScV+aA9Fvh5r8WzWrXBH9w82ZWB/eYDMGCnazoC/YAqAzUJWHzLOnZqr46K3iEyUhUvw==} - dev: true + /dom-accessibility-api/0.5.13: + resolution: {integrity: sha512-R305kwb5CcMDIpSHUnLyIAp7SrSPBx6F0VfQFB3M75xVMHhXJJIdePYgbPPh1o57vCHNu5QztokWUPsLjWzFqw==} /dom-converter/0.2.0: resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} @@ -12306,8 +12448,8 @@ packages: /dom-helpers/5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.17.2 - csstype: 3.0.10 + '@babel/runtime': 7.17.8 + csstype: 3.0.11 /dom-serializer/0.2.2: resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} @@ -12320,7 +12462,7 @@ packages: resolution: {integrity: sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==} dependencies: domelementtype: 2.2.0 - domhandler: 4.3.0 + domhandler: 4.3.1 entities: 2.2.0 dev: true @@ -12349,8 +12491,8 @@ packages: domelementtype: 1.3.1 dev: true - /domhandler/4.3.0: - resolution: {integrity: sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==} + /domhandler/4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} dependencies: domelementtype: 2.2.0 @@ -12376,7 +12518,7 @@ packages: dependencies: dom-serializer: 1.3.2 domelementtype: 2.2.0 - domhandler: 4.3.0 + domhandler: 4.3.1 dev: true /dot-case/3.0.4: @@ -12446,16 +12588,16 @@ packages: requiresBuild: true dev: true - /electron-to-chromium/1.4.71: - resolution: {integrity: sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==} + /electron-to-chromium/1.4.89: + resolution: {integrity: sha512-z1Axg0Fu54fse8wN4fd+GAINdU5mJmLtcl6bqIcYyzNVGONcfHAeeJi88KYMQVKalhXlYuVPzKkFIU5VD0raUw==} - /electron/14.2.6: - resolution: {integrity: sha512-yTPmuBO6/7baUUjhQ1E2URsNjEPsj+DMcleLf3VexVPU1Py0mXc5OpwI6LCq/jvuwyGiXOLK2Vx6h4bel6DoEw==} + /electron/14.2.7: + resolution: {integrity: sha512-JYK2DviM9l0UDR6PgIKg9w/r7klty2u1+a3hqWIyXi0f3BSFpcswcSpY6kThrsFdSxeeXO9m4sXjWExDl/YquQ==} engines: {node: '>= 8.6'} hasBin: true requiresBuild: true dependencies: - '@electron/get': 1.13.1 + '@electron/get': 1.14.1 '@types/node': 14.14.31 extract-zip: 1.7.0 transitivePeerDependencies: @@ -12608,7 +12750,7 @@ packages: get-intrinsic: 1.1.1 get-symbol-description: 1.0.0 has: 1.0.3 - has-symbols: 1.0.2 + has-symbols: 1.0.3 internal-slot: 1.0.3 is-callable: 1.2.4 is-negative-zero: 2.0.2 @@ -12635,12 +12777,14 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 - /es5-ext/0.10.53: - resolution: {integrity: sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==} + /es5-ext/0.10.59: + resolution: {integrity: sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==} + engines: {node: '>=0.10'} + requiresBuild: true dependencies: es6-iterator: 2.0.3 es6-symbol: 3.1.3 - next-tick: 1.0.0 + next-tick: 1.1.0 dev: true /es6-error/4.1.1: @@ -12650,7 +12794,7 @@ packages: resolution: {integrity: sha1-p96IkUGgWpSwhUQDstCg+/qY87c=} dependencies: d: 1.0.1 - es5-ext: 0.10.53 + es5-ext: 0.10.59 es6-symbol: 3.1.3 dev: true @@ -12665,6 +12809,166 @@ packages: ext: 1.6.0 dev: true + /esbuild-android-arm64/0.13.15: + resolution: {integrity: sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-64/0.13.15: + resolution: {integrity: sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-arm64/0.13.15: + resolution: {integrity: sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-64/0.13.15: + resolution: {integrity: sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-arm64/0.13.15: + resolution: {integrity: sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-32/0.13.15: + resolution: {integrity: sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-64/0.13.15: + resolution: {integrity: sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm/0.13.15: + resolution: {integrity: sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm64/0.13.15: + resolution: {integrity: sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-mips64le/0.13.15: + resolution: {integrity: sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-ppc64le/0.13.15: + resolution: {integrity: sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-netbsd-64/0.13.15: + resolution: {integrity: sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-openbsd-64/0.13.15: + resolution: {integrity: sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-sunos-64/0.13.15: + resolution: {integrity: sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-32/0.13.15: + resolution: {integrity: sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-64/0.13.15: + resolution: {integrity: sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-arm64/0.13.15: + resolution: {integrity: sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild/0.13.15: + resolution: {integrity: sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==} + hasBin: true + requiresBuild: true + optionalDependencies: + esbuild-android-arm64: 0.13.15 + esbuild-darwin-64: 0.13.15 + esbuild-darwin-arm64: 0.13.15 + esbuild-freebsd-64: 0.13.15 + esbuild-freebsd-arm64: 0.13.15 + esbuild-linux-32: 0.13.15 + esbuild-linux-64: 0.13.15 + esbuild-linux-arm: 0.13.15 + esbuild-linux-arm64: 0.13.15 + esbuild-linux-mips64le: 0.13.15 + esbuild-linux-ppc64le: 0.13.15 + esbuild-netbsd-64: 0.13.15 + esbuild-openbsd-64: 0.13.15 + esbuild-sunos-64: 0.13.15 + esbuild-windows-32: 0.13.15 + esbuild-windows-64: 0.13.15 + esbuild-windows-arm64: 0.13.15 + dev: true + /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -12716,7 +13020,7 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-react-app/6.0.0_1aeedec7f5157d0e02e45ad499760247: + /eslint-config-react-app/6.0.0_587eb56c66291e3ab94b46708696c3be: resolution: {integrity: sha512-bpoAAC+YRfzq0dsTk+6v9aHm/uqnDwayNAXleMypGl6CpxI9oXXscVHo4fk3eJPIn+rsbtNetB4r/ZIidFIE8A==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -12737,14 +13041,14 @@ packages: eslint-plugin-testing-library: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 4.31.2_8f0416aa8ec58a469909c5c0f73069bc - '@typescript-eslint/parser': 4.31.2_eslint@7.32.0+typescript@4.4.4 + '@typescript-eslint/eslint-plugin': 4.26.0_254a60bd907cee05fd203cdf9e9086f0 + '@typescript-eslint/parser': 4.26.0_eslint@7.32.0+typescript@4.4.4 babel-eslint: 10.1.0_eslint@7.32.0 confusing-browser-globals: 1.0.11 eslint: 7.32.0 eslint-plugin-flowtype: 5.10.0_eslint@7.32.0 eslint-plugin-import: 2.23.4_eslint@7.32.0 - eslint-plugin-jest: 24.7.0_1597ebf22056641fa858351a9409f475 + eslint-plugin-jest: 24.7.0_537c812b64b0470fabb72cea3d22f29e eslint-plugin-jsx-a11y: 6.4.1_eslint@7.32.0 eslint-plugin-react: 7.24.0_eslint@7.32.0 eslint-plugin-react-hooks: 4.2.0_eslint@7.32.0 @@ -12764,13 +13068,13 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.3 + debug: 4.3.4 eslint: 7.32.0 eslint-plugin-import: 2.23.4_eslint@7.32.0 glob: 7.2.0 is-glob: 4.0.3 resolve: 1.19.0 - tsconfig-paths: 3.12.0 + tsconfig-paths: 3.14.1 transitivePeerDependencies: - supports-color dev: false @@ -12829,7 +13133,7 @@ packages: pkg-up: 2.0.0 read-pkg-up: 3.0.0 resolve: 1.22.0 - tsconfig-paths: 3.12.0 + tsconfig-paths: 3.14.1 /eslint-plugin-jam3/0.2.3: resolution: {integrity: sha512-aW1L8C96fsRji0c8ZAgqtJVIu5p2IaNbeT2kuHNS6p5tontAVK1yP1W4ECjq3BHOv/GgAWvBVIx7kQI0kG2Rew==} @@ -12840,7 +13144,7 @@ packages: requireindex: 1.1.0 dev: false - /eslint-plugin-jest/24.7.0_1597ebf22056641fa858351a9409f475: + /eslint-plugin-jest/24.7.0_537c812b64b0470fabb72cea3d22f29e: resolution: {integrity: sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==} engines: {node: '>=10'} peerDependencies: @@ -12850,7 +13154,7 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 4.31.2_8f0416aa8ec58a469909c5c0f73069bc + '@typescript-eslint/eslint-plugin': 4.26.0_254a60bd907cee05fd203cdf9e9086f0 '@typescript-eslint/experimental-utils': 4.33.0_eslint@7.32.0+typescript@4.4.4 eslint: 7.32.0 transitivePeerDependencies: @@ -12866,7 +13170,7 @@ packages: dependencies: '@es-joy/jsdoccomment': 0.8.0 comment-parser: 1.1.5 - debug: 4.3.3 + debug: 4.3.4 eslint: 7.32.0 esquery: 1.4.0 jsdoc-type-pratt-parser: 1.2.0 @@ -12884,7 +13188,7 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 aria-query: 4.2.2 array-includes: 3.1.4 ast-types-flow: 0.0.7 @@ -12931,7 +13235,7 @@ packages: object.values: 1.1.5 prop-types: 15.8.1 resolve: 2.0.0-next.3 - string.prototype.matchall: 4.0.6 + string.prototype.matchall: 4.0.7 /eslint-plugin-testing-library/3.10.2_eslint@7.32.0+typescript@4.4.4: resolution: {integrity: sha512-WAmOCt7EbF1XM8XfbCKAEzAPnShkNSwcIsAD2jHdsMUT9mZJPjLCG7pMzbcC8kK366NOuGip8HKLDC+Xk4yIdA==} @@ -13011,7 +13315,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.3 + debug: 4.3.4 doctrine: 3.0.0 enquirer: 2.3.6 escape-string-regexp: 4.0.0 @@ -13025,7 +13329,7 @@ packages: file-entry-cache: 6.0.1 functional-red-black-tree: 1.0.1 glob-parent: 5.1.2 - globals: 13.12.1 + globals: 13.13.0 ignore: 4.0.6 import-fresh: 3.3.0 imurmurhash: 0.1.4 @@ -13289,7 +13593,7 @@ packages: dependencies: concat-stream: 1.6.2 debug: 2.6.9 - mkdirp: 0.5.5 + mkdirp: 0.5.6 yauzl: 2.10.0 /extract-zip/2.0.1: @@ -13297,7 +13601,7 @@ packages: engines: {node: '>= 10.17.0'} hasBin: true dependencies: - debug: 4.3.3 + debug: 4.3.4 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -13335,7 +13639,7 @@ packages: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} dev: false - /fast-sass-loader/2.0.1_sass@1.49.8+webpack@4.44.2: + /fast-sass-loader/2.0.1_sass@1.49.9+webpack@4.44.2: resolution: {integrity: sha512-RGQNKA9d7OiF9dIa65QOabz4guGRZGg4CS2uXvLyWdmy5A6VLK8ZZEQKKlJ54ILmOpdFyaAq8u3Fj3oNkSmdug==} peerDependencies: sass: 1.x @@ -13346,12 +13650,12 @@ packages: co: 4.6.0 fs-extra: 3.0.1 loader-utils: 1.4.0 - sass: 1.49.8 + sass: 1.49.9 webpack: 4.44.2 dev: true - /fast-sort/3.1.1: - resolution: {integrity: sha512-EA3PVIYj8uyyJc2Mma7GHjMrE74N/ClKkBj5gVUmY+8JePrc/ognCk4bhszVGYazu9Qk2aUTHnBF38QDSHcjkg==} + /fast-sort/3.1.3: + resolution: {integrity: sha512-DFD9n2nZVfJljjRaEN94SnIvUoSW2wpCdS2LC95iMNnzz8sja4yAYUVOXsXqvTiKUGMXiuhGZkrmtzUx8vopTg==} dev: false /fastq/1.13.0: @@ -13579,7 +13883,7 @@ packages: optional: true dev: false - /follow-redirects/1.14.9_debug@4.3.3: + /follow-redirects/1.14.9_debug@4.3.4: resolution: {integrity: sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==} engines: {node: '>=4.0'} peerDependencies: @@ -13588,7 +13892,7 @@ packages: debug: optional: true dependencies: - debug: 4.3.3_supports-color@6.1.0 + debug: 4.3.4_supports-color@6.1.0 /for-in/1.0.2: resolution: {integrity: sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=} @@ -13620,7 +13924,7 @@ packages: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 - mime-types: 2.1.34 + mime-types: 2.1.35 /form-data/3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} @@ -13628,7 +13932,7 @@ packages: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 - mime-types: 2.1.34 + mime-types: 2.1.35 /form-data/4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} @@ -13636,7 +13940,7 @@ packages: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 - mime-types: 2.1.34 + mime-types: 2.1.35 /format-util/1.0.5: resolution: {integrity: sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==} @@ -13682,8 +13986,8 @@ packages: /fs-constants/1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - /fs-extra/10.0.0: - resolution: {integrity: sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==} + /fs-extra/10.0.1: + resolution: {integrity: sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==} engines: {node: '>=12'} dependencies: graceful-fs: 4.2.9 @@ -13823,7 +14127,7 @@ packages: dependencies: function-bind: 1.1.1 has: 1.0.3 - has-symbols: 1.0.2 + has-symbols: 1.0.3 /get-own-enumerable-property-symbols/3.0.2: resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} @@ -13980,8 +14284,8 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - /globals/13.12.1: - resolution: {integrity: sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==} + /globals/13.13.0: + resolution: {integrity: sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 @@ -14036,7 +14340,7 @@ packages: resolution: {integrity: sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==} engines: {node: '>=10.19.0'} dependencies: - '@sindresorhus/is': 4.4.0 + '@sindresorhus/is': 4.6.0 '@szmarczak/http-timer': 4.0.6 '@types/cacheable-request': 6.0.2 '@types/responselike': 1.0.0 @@ -14112,15 +14416,15 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-symbols/1.0.2: - resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} /has-tostringtag/1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} dependencies: - has-symbols: 1.0.2 + has-symbols: 1.0.3 /has-unicode/2.0.1: resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} @@ -14344,7 +14648,7 @@ packages: resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} dependencies: domelementtype: 2.2.0 - domhandler: 4.3.0 + domhandler: 4.3.1 domutils: 2.8.0 entities: 2.2.0 dev: true @@ -14375,8 +14679,8 @@ packages: statuses: 1.5.0 toidentifier: 1.0.1 - /http-parser-js/0.5.5: - resolution: {integrity: sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==} + /http-parser-js/0.5.6: + resolution: {integrity: sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==} dev: true /http-proxy-agent/4.0.1: @@ -14385,15 +14689,15 @@ packages: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color - /http-proxy-middleware/0.19.1_debug@4.3.3: + /http-proxy-middleware/0.19.1_debug@4.3.4: resolution: {integrity: sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==} engines: {node: '>=4.0.0'} dependencies: - http-proxy: 1.18.1_debug@4.3.3 + http-proxy: 1.18.1_debug@4.3.4 is-glob: 4.0.3 lodash: 4.17.21 micromatch: 3.1.10 @@ -14401,12 +14705,12 @@ packages: - debug dev: true - /http-proxy/1.18.1_debug@4.3.3: + /http-proxy/1.18.1_debug@4.3.4: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.14.9_debug@4.3.3 + follow-redirects: 1.14.9_debug@4.3.4 requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -14427,7 +14731,7 @@ packages: engines: {node: '>= 6.0.0'} dependencies: agent-base: 5.1.1 - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -14436,7 +14740,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -14454,11 +14758,11 @@ packages: /i18next-browser-languagedetector/6.1.3: resolution: {integrity: sha512-T+oGXHXtrur14CGnZZ7qQ07X38XJQEI00b/4ILrtO6xPbwTlQ1wtMZC2H+tBULixHuVUXv8LKbxfjyITJkezUg==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false - /i18next-http-backend/1.3.2: - resolution: {integrity: sha512-SfcoUmsSWnc2LYsDsCq5TCg18cxJXvXymX9N37V+qqMKQY8Gf0rWkjOnRd20sMK633Dq4NF9tvqPbOiFJ49Kbw==} + /i18next-http-backend/1.4.0: + resolution: {integrity: sha512-wsvx7E/CT1pHmBM99Vu57YLJpsrHbVjxGxf25EIJ/6oTjsvCkZZ6c3SA4TejcK5jIHfv9oLxQX8l+DFKZHZ0Gg==} dependencies: cross-fetch: 3.1.5 transitivePeerDependencies: @@ -14469,13 +14773,13 @@ packages: resolution: {integrity: sha512-OtRf2Vo3IqAxsttQbpjYnmMML12IMB5e0fc5B7qKJFLScitYaXa1OhMX0n0X/3vrfFlpHL9Ro/H+ps4Ej2j7QQ==} deprecated: replaced by i18next-http-backend dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false - /i18next/21.6.11: - resolution: {integrity: sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==} + /i18next/21.6.14: + resolution: {integrity: sha512-XL6WyD+xlwQwbieXRlXhKWoLb/rkch50/rA+vl6untHnJ+aYnkQ0YDZciTWE78PPhOpbi2gR0LTJCJpiAhA+uQ==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: false /iconv-lite/0.4.24: @@ -15017,7 +15321,7 @@ packages: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: - has-symbols: 1.0.2 + has-symbols: 1.0.3 /is-typedarray/1.0.0: resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} @@ -15107,7 +15411,7 @@ packages: resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.0 @@ -15118,8 +15422,8 @@ packages: resolution: {integrity: sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.17.5 - '@babel/parser': 7.17.3 + '@babel/core': 7.17.8 + '@babel/parser': 7.17.8 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.0 @@ -15151,7 +15455,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.3 + debug: 4.3.4 istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -15241,10 +15545,10 @@ packages: ts-node: optional: true dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@jest/test-sequencer': 26.6.3 '@jest/types': 26.6.2 - babel-jest: 26.6.3_@babel+core@7.17.5 + babel-jest: 26.6.3_@babel+core@7.17.8 chalk: 4.1.2 deepmerge: 4.2.2 glob: 7.2.0 @@ -15591,7 +15895,7 @@ packages: chalk: 2.4.2 jest-diff: 21.2.1 jest-matcher-utils: 21.2.1 - mkdirp: 0.5.5 + mkdirp: 0.5.6 natural-compare: 1.4.0 pretty-format: 21.2.1 @@ -15614,7 +15918,7 @@ packages: jest-resolve: 26.6.2 natural-compare: 1.4.0 pretty-format: 26.6.2 - semver: 7.3.2 + semver: 7.3.5 dev: true /jest-util/26.6.2: @@ -15927,10 +16231,6 @@ packages: /json-stringify-safe/5.0.1: resolution: {integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=} - /json3/3.3.3: - resolution: {integrity: sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==} - dev: true - /json5/0.5.1: resolution: {integrity: sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=} hasBin: true @@ -15940,14 +16240,12 @@ packages: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: - minimist: 1.2.5 + minimist: 1.2.6 - /json5/2.2.0: - resolution: {integrity: sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==} + /json5/2.2.1: + resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true - dependencies: - minimist: 1.2.5 /jsonc-parser/2.0.3: resolution: {integrity: sha512-WJi9y9ABL01C8CxTKxRRQkkSpY/x2bo4Gy0WuiZGrInxQqgxQpvkBCLNcDYcHOSdhx4ODgbFcgAvfL49C+PHgQ==} @@ -16033,7 +16331,7 @@ packages: engines: {node: '>=10 < 13 || >=14'} dependencies: '@types/express-jwt': 0.0.42 - debug: 4.3.3 + debug: 4.3.4 jose: 2.0.5 limiter: 1.1.5 lru-memoizer: 2.1.4 @@ -16223,7 +16521,7 @@ packages: dependencies: big.js: 5.2.2 emojis-list: 3.0.0 - json5: 2.2.0 + json5: 2.2.1 dev: true /loader-utils/2.0.2: @@ -16232,7 +16530,7 @@ packages: dependencies: big.js: 5.2.2 emojis-list: 3.0.0 - json5: 2.2.0 + json5: 2.2.1 /locate-path/2.0.0: resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=} @@ -16455,10 +16753,9 @@ packages: /lz-string/1.4.4: resolution: {integrity: sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=} hasBin: true - dev: true - /magic-string/0.25.7: - resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==} + /magic-string/0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: sourcemap-codec: 1.4.8 dev: true @@ -16679,15 +16976,15 @@ packages: bn.js: 4.12.0 brorand: 1.1.0 - /mime-db/1.51.0: - resolution: {integrity: sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==} + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - /mime-types/2.1.34: - resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==} + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: - mime-db: 1.51.0 + mime-db: 1.52.0 /mime/1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} @@ -16740,12 +17037,15 @@ packages: dependencies: brace-expansion: 1.1.11 - /minimist/0.0.8: - resolution: {integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=} - dev: true + /minimatch/5.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false - /minimist/1.2.5: - resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + /minimist/1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} /minipass-collect/1.0.2: resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} @@ -16807,19 +17107,11 @@ packages: /mkdirp-classic/0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - /mkdirp/0.5.1: - resolution: {integrity: sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=} - deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) - hasBin: true - dependencies: - minimist: 0.0.8 - dev: true - - /mkdirp/0.5.5: - resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.5 + minimist: 1.2.6 /mkdirp/1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} @@ -16833,7 +17125,7 @@ packages: dependencies: debug: 2.6.9 md5: 2.3.0 - mkdirp: 0.5.5 + mkdirp: 0.5.6 mocha: 8.4.0 strip-ansi: 4.0.0 xml: 1.0.1 @@ -16901,7 +17193,7 @@ packages: aproba: 1.2.0 copy-concurrently: 1.0.5 fs-write-stream-atomic: 1.0.10 - mkdirp: 0.5.5 + mkdirp: 0.5.6 rimraf: 2.7.1 run-queue: 1.0.3 @@ -16958,7 +17250,7 @@ packages: lru-cache: 6.0.0 named-placeholders: 1.1.2 seq-queue: 0.0.5 - sqlstring: 2.3.2 + sqlstring: 2.3.3 dev: false /named-placeholders/1.1.2: @@ -17038,8 +17330,8 @@ packages: /neo-async/2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - /next-tick/1.0.0: - resolution: {integrity: sha1-yobR/ogoFpsBICCOPchCS524NCw=} + /next-tick/1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} dev: true /nice-try/1.0.5: @@ -17071,7 +17363,7 @@ packages: resolution: {integrity: sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==} engines: {node: '>= 10.13'} dependencies: - debug: 4.3.3 + debug: 4.3.4 json-stringify-safe: 5.0.1 lodash: 4.17.21 propagate: 2.0.1 @@ -17405,7 +17697,7 @@ packages: dependencies: call-bind: 1.0.2 define-properties: 1.1.3 - has-symbols: 1.0.2 + has-symbols: 1.0.3 object-keys: 1.1.1 /object.entries/1.1.5: @@ -17574,7 +17866,7 @@ packages: /original/1.0.2: resolution: {integrity: sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==} dependencies: - url-parse: 1.5.7 + url-parse: 1.5.10 dev: true /os-browserify/0.3.0: @@ -17959,7 +18251,7 @@ packages: dependencies: async: 2.6.3 debug: 3.2.7 - mkdirp: 0.5.5 + mkdirp: 0.5.6 dev: true /posix-character-classes/0.1.1: @@ -17973,13 +18265,13 @@ packages: postcss-selector-parser: 6.0.9 dev: true - /postcss-browser-comments/3.0.0_browserslist@4.19.2: + /postcss-browser-comments/3.0.0_browserslist@4.20.2: resolution: {integrity: sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig==} engines: {node: '>=8.0.0'} peerDependencies: browserslist: ^4 dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 postcss: 7.0.39 dev: true @@ -18037,7 +18329,7 @@ packages: resolution: {integrity: sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==} engines: {node: '>=6.9.0'} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 color: 3.2.1 has: 1.0.3 postcss: 7.0.39 @@ -18235,7 +18527,7 @@ packages: resolution: {integrity: sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==} engines: {node: '>=6.9.0'} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 caniuse-api: 3.0.0 cssnano-util-same-parent: 4.0.1 postcss: 7.0.39 @@ -18266,7 +18558,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: alphanum-sort: 1.0.2 - browserslist: 4.19.2 + browserslist: 4.20.2 cssnano-util-get-arguments: 4.0.0 postcss: 7.0.39 postcss-value-parser: 3.3.1 @@ -18380,7 +18672,7 @@ packages: resolution: {integrity: sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==} engines: {node: '>=6.9.0'} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 postcss: 7.0.39 postcss-value-parser: 3.3.1 dev: true @@ -18408,9 +18700,9 @@ packages: engines: {node: '>=8.0.0'} dependencies: '@csstools/normalize.css': 10.1.0 - browserslist: 4.19.2 + browserslist: 4.20.2 postcss: 7.0.39 - postcss-browser-comments: 3.0.0_browserslist@4.19.2 + postcss-browser-comments: 3.0.0_browserslist@4.20.2 sanitize.css: 10.0.0 dev: true @@ -18444,10 +18736,10 @@ packages: postcss-values-parser: 2.0.1 dev: true - /postcss-prefix-selector/1.14.0_postcss@5.2.18: - resolution: {integrity: sha512-8d5fiBQZWMtGWH/7ewEeo6RnBNyT2kLD5wTIfV2oHYqH4hjiofg/rP5X3SUwnqOINzE4mM/K/UOAiNrIaKzd4w==} + /postcss-prefix-selector/1.15.0_postcss@5.2.18: + resolution: {integrity: sha512-9taaTPs6I4906QC03zBBt0LfTWAhrqEWlKSj0jRlxrg1yV+O91h0wcquu6krcA5L6aEv3QnCeG8B1vZ5WT4ecQ==} peerDependencies: - postcss: 7.x || 8.x + postcss: '>4 <9' dependencies: postcss: 5.2.18 dev: true @@ -18457,8 +18749,8 @@ packages: engines: {node: '>=6.0.0'} dependencies: autoprefixer: 9.8.8 - browserslist: 4.19.2 - caniuse-lite: 1.0.30001312 + browserslist: 4.20.2 + caniuse-lite: 1.0.30001319 css-blank-pseudo: 0.1.4 css-has-pseudo: 0.10.0 css-prefers-color-scheme: 3.1.1 @@ -18507,7 +18799,7 @@ packages: resolution: {integrity: sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==} engines: {node: '>=6.9.0'} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 caniuse-api: 3.0.0 has: 1.0.3 postcss: 7.0.39 @@ -18533,7 +18825,7 @@ packages: resolution: {integrity: sha512-jDUfCPJbKOABhwpUKcqCVbbXiloe/QXMcbJ6Iipf3sDIihEzTqRCeMBfRaOHxhBuTYqtASrI1KJWxzztZU4qUQ==} engines: {node: '>=10.0'} dependencies: - postcss: 8.4.6 + postcss: 8.4.12 dev: true /postcss-selector-matches/4.0.0: @@ -18630,8 +18922,8 @@ packages: supports-color: 5.5.0 dev: true - /postcss/7.0.36: - resolution: {integrity: sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==} + /postcss/7.0.21: + resolution: {integrity: sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==} engines: {node: '>=6.0.0'} dependencies: chalk: 2.4.2 @@ -18647,8 +18939,8 @@ packages: source-map: 0.6.1 dev: true - /postcss/8.4.6: - resolution: {integrity: sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==} + /postcss/8.4.12: + resolution: {integrity: sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.1 @@ -18704,7 +18996,7 @@ packages: detect-libc: 2.0.1 expand-template: 2.0.3 github-from-package: 0.0.0 - minimist: 1.2.5 + minimist: 1.2.6 mkdirp-classic: 0.5.3 napi-build-utils: 1.0.2 node-abi: 3.8.0 @@ -18769,12 +19061,11 @@ packages: ansi-regex: 5.0.1 ansi-styles: 5.2.0 react-is: 17.0.2 - dev: true /probe.gl/3.5.0: resolution: {integrity: sha512-KWj8u0PNytr/rVwcQFcN7O8SK7n/ITOsUZ91l4fSX95oHhKvVCI7eadrzFUzFRlXkFfBWpMWZXFHITsHHHUctw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@probe.gl/env': 3.5.0 '@probe.gl/log': 3.5.0 '@probe.gl/stats': 3.5.0 @@ -18914,7 +19205,7 @@ packages: deprecated: Version no longer supported. Upgrade to @latest requiresBuild: true dependencies: - debug: 4.3.3 + debug: 4.3.4 devtools-protocol: 0.0.799653 extract-zip: 2.0.1 https-proxy-agent: 4.0.0 @@ -19049,7 +19340,7 @@ packages: dependencies: deep-extend: 0.6.0 ini: 1.3.8 - minimist: 1.2.5 + minimist: 1.2.6 strip-json-comments: 2.0.1 dev: false @@ -19084,7 +19375,7 @@ packages: react: ^16.8.5 || ^17.0.0 react-dom: ^16.8.5 || ^17.0.0 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 css-box-model: 1.2.1 memoize-one: 5.2.1 raf-schd: 4.0.3 @@ -19103,7 +19394,7 @@ packages: react: ^16.8.5 || ^17.0.0 react-dom: ^16.8.5 || ^17.0.0 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 css-box-model: 1.2.1 memoize-one: 5.2.1 raf-schd: 4.0.3 @@ -19215,7 +19506,7 @@ packages: peerDependencies: react: '>=16.13.1' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 react: 17.0.2 /react-error-overlay/6.0.10: @@ -19260,8 +19551,8 @@ packages: react-native: optional: true dependencies: - '@babel/runtime': 7.17.2 - '@types/react-redux': 7.1.22 + '@babel/runtime': 7.17.8 + '@types/react-redux': 7.1.23 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -19281,8 +19572,8 @@ packages: react-native: optional: true dependencies: - '@babel/runtime': 7.17.2 - '@types/react-redux': 7.1.22 + '@babel/runtime': 7.17.8 + '@types/react-redux': 7.1.23 hoist-non-react-statics: 3.3.2 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -19308,18 +19599,6 @@ packages: resize-observer-polyfill: 1.5.1 dev: false - /react-resize-detector/6.7.8_react@17.0.2: - resolution: {integrity: sha512-0FaEcUBAbn+pq3PT5a9hHRebUfuS1SRLGLpIw8LydU7zX429I6XJgKerKAMPsJH0qWAl6o5bVKNqFJqr6tGPYw==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 - react-dom: ^16.0.0 || ^17.0.0 - dependencies: - '@types/resize-observer-browser': 0.1.7 - lodash: 4.17.21 - react: 17.0.2 - resize-observer-polyfill: 1.5.1 - dev: false - /react-select-event/5.0.0: resolution: {integrity: sha512-bESECffhi//x1nlMoRJtwI0nGl5n6OKaVYeIEcPTV8flVPycvUoBGank/1RIoxVc6WtoQ4QbPbU8xMvX0xAiOA==} dependencies: @@ -19332,7 +19611,7 @@ packages: react: ^16.8.0 || ^17.0.0 react-dom: ^16.8.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 '@emotion/cache': 10.0.29 '@emotion/core': 10.3.1_react@17.0.2 '@emotion/css': 10.0.27 @@ -19383,7 +19662,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -19397,7 +19676,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -19411,7 +19690,7 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 memoize-one: 5.2.1 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 @@ -19518,7 +19797,7 @@ packages: /redux/4.1.2: resolution: {integrity: sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 /regenerate-unicode-properties/10.0.1: resolution: {integrity: sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==} @@ -19541,7 +19820,7 @@ packages: /regenerator-transform/0.14.5: resolution: {integrity: sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==} dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 dev: true /regex-not/1.0.2: @@ -19728,8 +20007,8 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - /resolve-url-loader/3.1.4: - resolution: {integrity: sha512-D3sQ04o0eeQEySLrcz4DsX3saHfsr8/N6tfhblxgZKXxMT2Louargg12oGNfoTRLV09GXhVUe5/qgA5vdgNigg==} + /resolve-url-loader/3.1.2: + resolution: {integrity: sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==} engines: {node: '>=6.0.0'} dependencies: adjust-sourcemap-loader: 3.0.0 @@ -19738,7 +20017,7 @@ packages: convert-source-map: 1.7.0 es6-iterator: 2.0.3 loader-utils: 1.2.3 - postcss: 7.0.36 + postcss: 7.0.21 rework: 1.0.1 rework-visit: 1.0.0 source-map: 0.6.1 @@ -19861,14 +20140,14 @@ packages: sprintf-js: 1.1.2 optional: true - /rollup-plugin-babel/4.4.0_@babel+core@7.17.5+rollup@1.32.1: + /rollup-plugin-babel/4.4.0_@babel+core@7.17.8+rollup@1.32.1: resolution: {integrity: sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==} deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-babel. peerDependencies: '@babel/core': 7 || ^7.0.0-rc.2 rollup: '>=0.60.0 <3' dependencies: - '@babel/core': 7.17.5 + '@babel/core': 7.17.8 '@babel/helper-module-imports': 7.16.7 rollup: 1.32.1 rollup-pluginutils: 2.8.2 @@ -19967,7 +20246,7 @@ packages: execa: 1.0.0 fb-watchman: 2.0.1 micromatch: 3.1.10 - minimist: 1.2.5 + minimist: 1.2.6 walker: 1.0.8 dev: true @@ -19975,7 +20254,7 @@ packages: resolution: {integrity: sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==} dev: true - /sass-loader/10.2.1_sass@1.49.8+webpack@4.44.2: + /sass-loader/10.2.1_sass@1.49.9+webpack@4.44.2: resolution: {integrity: sha512-RRvWl+3K2LSMezIsd008ErK4rk6CulIMSwrcc2aZvjymUgKo/vjXGp1rSWmfTUX7bblEOz8tst4wBwWtCGBqKA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -19994,14 +20273,14 @@ packages: klona: 2.0.5 loader-utils: 2.0.2 neo-async: 2.6.2 - sass: 1.49.8 + sass: 1.49.9 schema-utils: 3.1.1 - semver: 7.3.2 + semver: 7.3.5 webpack: 4.44.2 dev: true - /sass/1.49.8: - resolution: {integrity: sha512-NoGOjvDDOU9og9oAxhRnap71QaTjjlzrvLnKecUJ3GxhaQBrV6e7gPuSPF28u1OcVAArVojPAe4ZhOXwwC4tGw==} + /sass/1.49.9: + resolution: {integrity: sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -20045,7 +20324,7 @@ packages: resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} engines: {node: '>= 8.9.0'} dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 ajv: 6.12.6 ajv-keywords: 3.5.2_ajv@6.12.6 @@ -20053,7 +20332,7 @@ packages: resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} engines: {node: '>= 10.13.0'} dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 ajv: 6.12.6 ajv-keywords: 3.5.2_ajv@6.12.6 @@ -20139,8 +20418,8 @@ packages: engines: {node: '>= 10.0.0'} dev: false - /sequelize/6.16.2_mysql2@2.3.3+tedious@14.3.0: - resolution: {integrity: sha512-0fCdO4qrkuMWizq3blDVHPC4NvrDkRnrFucoJKlaukdatrDpluBw2GXQ53rBQeizbHGefdgehhFiyFzyo0COKg==} + /sequelize/6.17.0_mysql2@2.3.3+tedious@14.3.0: + resolution: {integrity: sha512-AZus+0YZDq91Zg0hzDaO5atTzHgJruI23V8nBlAhkLuI81Z53nSRdAe/4R1A6vGOZ/RfCLP9idF4tfQnoAsM5A==} engines: {node: '>=10.0.0'} peerDependencies: ibm_db: '*' @@ -20170,7 +20449,8 @@ packages: optional: true dependencies: '@types/debug': 4.1.7 - debug: 4.3.3 + '@types/validator': 13.7.1 + debug: 4.3.4 dottie: 2.0.2 inflection: 1.13.2 lodash: 4.17.21 @@ -20216,7 +20496,7 @@ packages: debug: 2.6.9 escape-html: 1.0.3 http-errors: 1.6.3 - mime-types: 2.1.34 + mime-types: 2.1.35 parseurl: 1.3.3 dev: true @@ -20298,7 +20578,7 @@ packages: resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==} dependencies: jsonc-parser: 3.0.0 - vscode-oniguruma: 1.6.1 + vscode-oniguruma: 1.6.2 vscode-textmate: 5.2.0 dev: false @@ -20397,15 +20677,15 @@ packages: source-map-resolve: 0.5.3 use: 3.1.1 - /sockjs-client/1.5.2: - resolution: {integrity: sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==} + /sockjs-client/1.6.0: + resolution: {integrity: sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==} + engines: {node: '>=12'} dependencies: debug: 3.2.7 eventsource: 1.1.0 faye-websocket: 0.11.4 inherits: 2.0.4 - json3: 3.3.3 - url-parse: 1.5.7 + url-parse: 1.5.10 dev: true /sockjs/0.3.24: @@ -20544,7 +20824,7 @@ packages: /spdy-transport/3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} dependencies: - debug: 4.3.3 + debug: 4.3.4 detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -20557,7 +20837,7 @@ packages: /spdy-transport/3.0.0_supports-color@6.1.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} dependencies: - debug: 4.3.3_supports-color@6.1.0 + debug: 4.3.4_supports-color@6.1.0 detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -20571,7 +20851,7 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -20584,7 +20864,7 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} dependencies: - debug: 4.3.3_supports-color@6.1.0 + debug: 4.3.4_supports-color@6.1.0 handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -20615,8 +20895,8 @@ packages: /sprintf-js/1.1.2: resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} - /sqlstring/2.3.2: - resolution: {integrity: sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==} + /sqlstring/2.3.3: + resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} dev: false @@ -20746,14 +21026,14 @@ packages: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - /string.prototype.matchall/4.0.6: - resolution: {integrity: sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==} + /string.prototype.matchall/4.0.7: + resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 es-abstract: 1.19.1 get-intrinsic: 1.1.1 - has-symbols: 1.0.2 + has-symbols: 1.0.3 internal-slot: 1.0.3 regexp.prototype.flags: 1.4.1 side-channel: 1.0.4 @@ -20823,7 +21103,7 @@ packages: resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} engines: {node: '>=6'} dependencies: - ansi-regex: 4.1.0 + ansi-regex: 4.1.1 dev: true /strip-ansi/6.0.0: @@ -20888,7 +21168,7 @@ packages: resolution: {integrity: sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==} engines: {node: '>=6.9.0'} dependencies: - browserslist: 4.19.2 + browserslist: 4.20.2 postcss: 7.0.39 postcss-selector-parser: 3.1.2 dev: true @@ -20896,20 +21176,20 @@ packages: /subarg/1.0.0: resolution: {integrity: sha1-9izxdYHplrSPyWVpn1TAauJouNI=} dependencies: - minimist: 1.2.5 + minimist: 1.2.6 /sumchecker/3.0.1: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} engines: {node: '>= 8.0'} dependencies: - debug: 4.3.3 + debug: 4.3.4 transitivePeerDependencies: - supports-color /superagent/3.8.3: resolution: {integrity: sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==} engines: {node: '>= 4.0'} - deprecated: Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . Thanks to @shadowgate15, @spence-s, and @niftylettuce. Superagent is sponsored by Forward Email at . + deprecated: Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . dependencies: component-emitter: 1.3.0 cookiejar: 2.1.3 @@ -20929,7 +21209,7 @@ packages: dependencies: component-emitter: 1.3.0 cookiejar: 2.1.3 - debug: 4.3.3 + debug: 4.3.4 fast-safe-stringify: 2.1.1 form-data: 4.0.0 formidable: 2.0.1 @@ -21016,7 +21296,7 @@ packages: merge-options: 1.0.1 micromatch: 3.1.0 postcss: 5.2.18 - postcss-prefix-selector: 1.14.0_postcss@5.2.18 + postcss-prefix-selector: 1.15.0_postcss@5.2.18 posthtml-rename-id: 1.0.12 posthtml-svg-mode: 1.0.3 query-string: 4.3.4 @@ -21057,7 +21337,7 @@ packages: css-tree: 1.0.0-alpha.37 csso: 4.2.0 js-yaml: 3.14.1 - mkdirp: 0.5.5 + mkdirp: 0.5.6 object.values: 1.1.5 sax: 1.2.4 stable: 0.1.8 @@ -21083,7 +21363,7 @@ packages: resolution: {integrity: sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==} engines: {node: '>=10.0.0'} dependencies: - ajv: 8.10.0 + ajv: 8.11.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 @@ -21126,7 +21406,7 @@ packages: resolution: {integrity: sha512-ioorVbzGpGOLF9gkd47EtlHGDh0HQc9zgjlf5lon8hDCRwYZ79Uolu9cXQZ/gOPVyG63evbU7XjzEBOQOvcHeQ==} engines: {node: '>= 12'} dependencies: - '@azure/identity': 2.0.3 + '@azure/identity': 2.0.4 '@azure/keyvault-keys': 4.3.0 '@js-joda/core': 4.3.1 bl: 5.0.0 @@ -21212,11 +21492,9 @@ packages: schema-utils: 3.1.1 serialize-javascript: 5.0.1 source-map: 0.6.1 - terser: 5.10.0 + terser: 5.12.1 webpack: 4.44.2 webpack-sources: 1.4.3 - transitivePeerDependencies: - - acorn dev: true /terser/4.8.0: @@ -21228,16 +21506,12 @@ packages: source-map: 0.6.1 source-map-support: 0.5.21 - /terser/5.10.0: - resolution: {integrity: sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==} + /terser/5.12.1: + resolution: {integrity: sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==} engines: {node: '>=10'} hasBin: true - peerDependencies: - acorn: ^8.5.0 - peerDependenciesMeta: - acorn: - optional: true dependencies: + acorn: 8.7.0 commander: 2.20.3 source-map: 0.7.3 source-map-support: 0.5.21 @@ -21291,7 +21565,7 @@ packages: /tippy.js/6.3.7: resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} dependencies: - '@popperjs/core': 2.11.2 + '@popperjs/core': 2.11.4 /tmpl/1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -21434,17 +21708,17 @@ packages: fast-json-stable-stringify: 2.1.0 jest: 26.6.0 jest-util: 26.6.2 - json5: 2.2.0 + json5: 2.2.1 lodash: 4.17.21 make-error: 1.3.6 mkdirp: 1.0.4 - semver: 7.3.2 + semver: 7.3.5 typescript: 4.4.4 yargs-parser: 20.2.9 dev: true - /ts-key-enum/2.0.10: - resolution: {integrity: sha512-gqbZa/AlFKwDjS4fCVmsNsQNeVz+eUrAgn+Pk/WluAeeuDljwr6CH5zMZgB6lWoFVkA8+ie9mjEPX+ET1aLQ5g==} + /ts-key-enum/2.0.11: + resolution: {integrity: sha512-ZYcdy6/RdwryMm2hcRT3KJanGSQREd5SDkMirdFjhWINe12wht2A26tzBqi3pxPau9Pf3Bq1C7iwzFCOfdm5yQ==} dev: false /ts-node/7.0.1: @@ -21456,8 +21730,8 @@ packages: buffer-from: 1.1.2 diff: 3.5.0 make-error: 1.3.6 - minimist: 1.2.5 - mkdirp: 0.5.5 + minimist: 1.2.6 + mkdirp: 0.5.6 source-map-support: 0.5.21 yn: 2.0.0 dev: true @@ -21474,12 +21748,12 @@ packages: typescript: 4.4.4 dev: true - /tsconfig-paths/3.12.0: - resolution: {integrity: sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==} + /tsconfig-paths/3.14.1: + resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} dependencies: '@types/json5': 0.0.29 json5: 1.0.1 - minimist: 1.2.5 + minimist: 1.2.6 strip-bom: 3.0.0 /tslib/1.14.1: @@ -21569,7 +21843,7 @@ packages: engines: {node: '>= 0.6'} dependencies: media-typer: 0.3.0 - mime-types: 2.1.34 + mime-types: 2.1.35 /type/1.2.0: resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} @@ -21587,25 +21861,25 @@ packages: /typedarray/0.0.6: resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} - /typedoc-plugin-merge-modules/3.1.0_typedoc@0.22.11: + /typedoc-plugin-merge-modules/3.1.0_typedoc@0.22.13: resolution: {integrity: sha512-DAHDZD+KG3mRm+hJFAMh/pO98CQ3W/BFA81FzWpc1kos66mLRIa7QVO30yBREkZNZMsTA7fgGEjEN2GO2cgi3A==} peerDependencies: typedoc: 0.21.x || 0.22.x dependencies: - typedoc: 0.22.11_typescript@4.4.4 + typedoc: 0.22.13_typescript@4.4.4 dev: false - /typedoc/0.22.11_typescript@4.4.4: - resolution: {integrity: sha512-pVr3hh6dkS3lPPaZz1fNpvcrqLdtEvXmXayN55czlamSgvEjh+57GUqfhAI1Xsuu/hNHUT1KNSx8LH2wBP/7SA==} + /typedoc/0.22.13_typescript@4.4.4: + resolution: {integrity: sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==} engines: {node: '>= 12.10.0'} hasBin: true peerDependencies: - typescript: 4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x + typescript: 4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x dependencies: glob: 7.2.0 lunr: 2.3.9 marked: 4.0.12 - minimatch: 3.1.2 + minimatch: 5.0.1 shiki: 0.10.1 typescript: 4.4.4 dev: false @@ -21623,7 +21897,7 @@ packages: resolution: {integrity: sha512-4c9IMlIlHYJiQtzL1gh2nIPJEjBgJjDUs50gsnnc+GFyDSK1oFM3uQIBSVosiuA/4t6LSAXDS9vTdqbQC6EcgA==} hasBin: true dependencies: - '@types/json-schema': 7.0.9 + '@types/json-schema': 7.0.10 glob: 7.1.7 json-stable-stringify: 1.0.1 typescript: 4.0.8 @@ -21666,7 +21940,7 @@ packages: dependencies: function-bind: 1.1.1 has-bigints: 1.0.1 - has-symbols: 1.0.2 + has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 /unbzip2-stream/1.4.3: @@ -21828,7 +22102,7 @@ packages: dependencies: file-loader: 6.1.1_webpack@4.44.2 loader-utils: 2.0.2 - mime-types: 2.1.34 + mime-types: 2.1.35 schema-utils: 3.1.1 webpack: 4.44.2 dev: true @@ -21839,8 +22113,8 @@ packages: dependencies: prepend-http: 2.0.0 - /url-parse/1.5.7: - resolution: {integrity: sha512-HxWkieX+STA38EDk7CE9MEryFeHCKzgagxlGvsdS7WBImq9Mk+PGwiT56w82WI3aicwJA8REp42Cxo98c8FZMA==} + /url-parse/1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} dependencies: querystringify: 2.2.0 requires-port: 1.0.0 @@ -21893,7 +22167,7 @@ packages: dependencies: define-properties: 1.1.3 es-abstract: 1.19.1 - has-symbols: 1.0.2 + has-symbols: 1.0.3 object.getownpropertydescriptors: 2.1.3 dev: true @@ -21967,8 +22241,8 @@ packages: /vm-browserify/1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} - /vscode-oniguruma/1.6.1: - resolution: {integrity: sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==} + /vscode-oniguruma/1.6.2: + resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} dev: false /vscode-textmate/5.2.0: @@ -22071,7 +22345,7 @@ packages: dependencies: memory-fs: 0.4.1 mime: 2.6.0 - mkdirp: 0.5.5 + mkdirp: 0.5.6 range-parser: 1.2.1 webpack: 4.44.2 webpack-log: 2.0.0 @@ -22093,11 +22367,11 @@ packages: chokidar: 2.1.8 compression: 1.7.4 connect-history-api-fallback: 1.6.0 - debug: 4.3.3_supports-color@6.1.0 + debug: 4.3.4_supports-color@6.1.0 del: 4.1.1 express: 4.17.3 html-entities: 1.4.0 - http-proxy-middleware: 0.19.1_debug@4.3.3 + http-proxy-middleware: 0.19.1_debug@4.3.4 import-local: 2.0.0 internal-ip: 4.3.0 ip: 1.1.5 @@ -22112,7 +22386,7 @@ packages: semver: 6.3.0 serve-index: 1.9.1 sockjs: 0.3.24 - sockjs-client: 1.5.2 + sockjs-client: 1.6.0 spdy: 4.0.2_supports-color@6.1.0 strip-ansi: 3.0.1 supports-color: 6.1.0 @@ -22189,7 +22463,7 @@ packages: loader-utils: 1.4.0 memory-fs: 0.4.1 micromatch: 3.1.10 - mkdirp: 0.5.5 + mkdirp: 0.5.6 neo-async: 2.6.2 node-libs-browser: 2.2.1 schema-utils: 1.0.0 @@ -22226,7 +22500,7 @@ packages: loader-utils: 1.4.0 memory-fs: 0.4.1 micromatch: 3.1.10 - mkdirp: 0.5.5 + mkdirp: 0.5.6 neo-async: 2.6.2 node-libs-browser: 2.2.1 schema-utils: 1.0.0 @@ -22240,7 +22514,7 @@ packages: resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} engines: {node: '>=0.8.0'} dependencies: - http-parser-js: 0.5.5 + http-parser-js: 0.5.6 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 dev: true @@ -22378,7 +22652,7 @@ packages: resolution: {integrity: sha512-dGe1SQ4GySIfsmGF+yk07QRsed0DgJJkPpimbmehE9nGXLqIGhbpi6pNk71YENqupLPSqcABDrKZ1UqepOhCyA==} hasBin: true dependencies: - minimist: 1.2.5 + minimist: 1.2.6 dev: false /word-wrap/1.2.3: @@ -22401,9 +22675,9 @@ packages: resolution: {integrity: sha512-xUcZn6SYU8usjOlfLb9Y2/f86Gdo+fy1fXgH8tJHjxgpo53VVsqRX0lUDw8/JuyzNmXuo8vXX14pXX2oIm9Bow==} engines: {node: '>=8.0.0'} dependencies: - '@babel/core': 7.17.5 - '@babel/preset-env': 7.16.11_@babel+core@7.17.5 - '@babel/runtime': 7.17.2 + '@babel/core': 7.17.8 + '@babel/preset-env': 7.16.11_@babel+core@7.17.8 + '@babel/runtime': 7.17.8 '@hapi/joi': 15.1.1 '@rollup/plugin-node-resolve': 7.1.3_rollup@1.32.1 '@rollup/plugin-replace': 2.4.2_rollup@1.32.1 @@ -22415,7 +22689,7 @@ packages: lodash.template: 4.5.0 pretty-bytes: 5.6.0 rollup: 1.32.1 - rollup-plugin-babel: 4.4.0_@babel+core@7.17.5+rollup@1.32.1 + rollup-plugin-babel: 4.4.0_@babel+core@7.17.8+rollup@1.32.1 rollup-plugin-terser: 5.3.1_rollup@1.32.1 source-map: 0.7.3 source-map-url: 0.4.1 @@ -22514,7 +22788,7 @@ packages: peerDependencies: webpack: ^4.0.0 dependencies: - '@babel/runtime': 7.17.2 + '@babel/runtime': 7.17.8 fast-json-stable-stringify: 2.1.0 source-map-url: 0.4.1 upath: 1.2.0 diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index e41b670d7376..ff4b6ae41eae 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -2,7 +2,7 @@ { "policyName": "prerelease-monorepo-lockStep", "definitionName": "lockStepVersion", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "nextBump": "prerelease" } ] diff --git a/core/backend/CHANGELOG.json b/core/backend/CHANGELOG.json index e7b83850a22b..55193d9c79c0 100644 --- a/core/backend/CHANGELOG.json +++ b/core/backend/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-backend", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-backend_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-backend_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-backend_v3.0.0", diff --git a/core/backend/CHANGELOG.md b/core/backend/CHANGELOG.md index c0a33fd04422..3e215f53bf47 100644 --- a/core/backend/CHANGELOG.md +++ b/core/backend/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-backend -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/backend/package.json b/core/backend/package.json index fdcc72aed66d..5b2d11d134c3 100644 --- a/core/backend/package.json +++ b/core/backend/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/core-backend", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js backend components", "main": "lib/cjs/core-backend.js", "typings": "lib/cjs/core-backend", @@ -38,10 +38,10 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33", - "@itwin/ecschema-metadata": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21", + "@itwin/ecschema-metadata": "workspace:^3.2.0-dev.21" }, "peerDependenciesMeta": { "@itwin/ecschema-metadata": { @@ -83,7 +83,7 @@ }, "dependencies": { "@azure/storage-blob": "^12.7.0", - "@bentley/imodeljs-native": "3.1.6", + "@bentley/imodeljs-native": "3.2.1", "@itwin/core-telemetry": "workspace:*", "form-data": "^2.3.2", "fs-extra": "^8.1.0", @@ -116,4 +116,4 @@ } ] } -} \ No newline at end of file +} diff --git a/core/backend/src/IModelHost.ts b/core/backend/src/IModelHost.ts index a0e847bbff54..e2db6152dfa2 100644 --- a/core/backend/src/IModelHost.ts +++ b/core/backend/src/IModelHost.ts @@ -321,8 +321,17 @@ export class IModelHost { /** Provides access to the IModelHub for this IModelHost * @beta - */ - public static get hubAccess(): BackendHubAccess { return this._hubAccess; } + * @note If [[IModelHostConfiguration.hubAccess]] was undefined when initializing this class, accessing this property will throw an error. + */ + public static get hubAccess(): BackendHubAccess { + // Strictly speaking, _hubAccess should be marked as possibly undefined since it's not needed for Snapshot iModels. + // However, a decision was made to not provide that type annotation so callers aren't forced to constantly check for + // something that's required in all other workflows. + // This check is here to provide a better error message when hubAccess is inadvertently undefined. + if (this._hubAccess === undefined) + throw new IModelError(IModelStatus.BadRequest, "IModelHost.hubAccess is undefined. Specify an implementation in your IModelHostConfiguration"); + return this._hubAccess; + } private static _isValid = false; /** Returns true if IModelHost is started. */ diff --git a/core/backend/src/rpc-impl/IModelReadRpcImpl.ts b/core/backend/src/rpc-impl/IModelReadRpcImpl.ts index ff2ac1c6407b..04b896727d05 100644 --- a/core/backend/src/rpc-impl/IModelReadRpcImpl.ts +++ b/core/backend/src/rpc-impl/IModelReadRpcImpl.ts @@ -10,7 +10,7 @@ import { GuidString, Id64, Id64String, IModelStatus, Logger } from "@itwin/core- import { Code, CodeProps, DbBlobRequest, DbBlobResponse, DbQueryRequest, DbQueryResponse, ElementLoadOptions, ElementLoadProps, ElementProps, EntityMetaData, EntityQueryParams, FontMapProps, GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, GeometryContainmentRequestProps, - GeometryContainmentResponseProps, GeometrySummaryRequestProps, IModel, IModelConnectionProps, IModelCoordinatesRequestProps, + GeometryContainmentResponseProps, GeometrySummaryRequestProps, ImageSourceFormat, IModel, IModelConnectionProps, IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, IModelError, IModelReadRpcInterface, IModelRpcOpenProps, IModelRpcProps, MassPropertiesRequestProps, MassPropertiesResponseProps, ModelProps, NoContentError, RpcInterface, RpcManager, SnapRequestProps, SnapResponseProps, SyncMode, TextureData, TextureLoadProps, ViewStateLoadProps, ViewStateProps, @@ -200,9 +200,19 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte return (el === undefined) ? [] : el.getToolTipMessage(); } - /** @deprecated */ + /** Send a view thumbnail to the frontend. This is a binary transfer with the metadata in a 16-byte prefix header. + * @deprecated + */ public async getViewThumbnail(_tokenProps: IModelRpcProps, _viewId: string): Promise { - throw new NoContentError(); + const iModelDb = await RpcBriefcaseUtility.findOpenIModel(RpcTrace.expectCurrentActivity.accessToken, _tokenProps); + const thumbnail = iModelDb.views.getThumbnail(_viewId); + if (undefined === thumbnail || 0 === thumbnail.image.length) + throw new NoContentError(); + + const val = new Uint8Array(thumbnail.image.length + 16); // allocate a new buffer 16 bytes larger than the image size + new Uint32Array(val.buffer, 0, 4).set([thumbnail.image.length, thumbnail.format === "jpeg" ? ImageSourceFormat.Jpeg : ImageSourceFormat.Png, thumbnail.width, thumbnail.height]); // Put the metadata in the first 16 bytes. + val.set(thumbnail.image, 16); // put the image data at offset 16 after metadata + return val; } public async getDefaultViewId(tokenProps: IModelRpcProps): Promise { diff --git a/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts b/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts index 2480fe43f7aa..706ffa4e8fca 100644 --- a/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts +++ b/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts @@ -113,9 +113,7 @@ export class RpcBriefcaseUtility { * @param the IModelRpcProps to locate the opened iModel. */ public static async findOpenIModel(accessToken: AccessToken, iModel: IModelRpcProps) { - const iModelDb = IModelDb.tryFindByKey(iModel.key); - if (undefined === iModelDb) - throw new IModelError(IModelStatus.NotOpen, "iModel is not opened", () => iModel); + const iModelDb = IModelDb.findByKey(iModel.key); // call reattach, just in case this is a V2 checkpoint whose accessToken is about to expire. await iModelDb.reattachDaemon(accessToken); @@ -138,7 +136,7 @@ export class RpcBriefcaseUtility { Logger.logTrace(loggerCategory, "Open briefcase - pending", () => ({ ...tokenProps })); throw new RpcPendingResponse(); } - // note: usage is logged in BriefcaseManager.downloadNewBriefcaseAndOpen + // note: usage is logged in the function BriefcaseManager.downloadNewBriefcaseAndOpen return briefcaseDb; } diff --git a/core/backend/src/test/HubMock.ts b/core/backend/src/test/HubMock.ts index 84704355b9cb..278b2f5da9d8 100644 --- a/core/backend/src/test/HubMock.ts +++ b/core/backend/src/test/HubMock.ts @@ -80,7 +80,11 @@ export class HubMock { this.mockRoot = join(KnownTestLocations.outputDir, "HubMock", mockName); IModelJsFs.recursiveMkDirSync(this.mockRoot); IModelJsFs.purgeDirSync(this.mockRoot); - this._saveHubAccess = IModelHost.hubAccess; + try { + this._saveHubAccess = IModelHost.hubAccess; + } catch (error) { + // See note in IModelHost.hubAccess. hubAccess can in fact be undefined, but that is not annotated in type system. + } IModelHost.setHubAccess(this); HubMock._iTwinId = Guid.createValue(); // all iModels for this test get the same "iTwinId" } diff --git a/core/backend/src/test/IModelHost.test.ts b/core/backend/src/test/IModelHost.test.ts index c0d064fdd6ca..0834b1d80780 100644 --- a/core/backend/src/test/IModelHost.test.ts +++ b/core/backend/src/test/IModelHost.test.ts @@ -192,4 +192,9 @@ describe("IModelHost", () => { }); + it("should throw if hubAccess is undefined and getter is called", async () => { + await IModelHost.startup(); + expect(() => IModelHost.hubAccess).throws("IModelHost.hubAccess is undefined. Specify an implementation in your IModelHostConfiguration"); + }); + }); diff --git a/core/bentley/CHANGELOG.json b/core/bentley/CHANGELOG.json index 258adedab574..dd63db691999 100644 --- a/core/bentley/CHANGELOG.json +++ b/core/bentley/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-bentley", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-bentley_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-bentley_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-bentley_v3.0.0", diff --git a/core/bentley/CHANGELOG.md b/core/bentley/CHANGELOG.md index fad443f49d15..46c0cecb77da 100644 --- a/core/bentley/CHANGELOG.md +++ b/core/bentley/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-bentley -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/bentley/package.json b/core/bentley/package.json index 5faf4e9b6049..ba330172c88f 100644 --- a/core/bentley/package.json +++ b/core/bentley/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-bentley", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "Bentley JavaScript core components", "main": "lib/cjs/core-bentley.js", "module": "lib/esm/core-bentley.js", "typings": "lib/cjs/core-bentley", - "imodeljsSharedLibrary": true, "license": "MIT", "repository": { "type": "git", diff --git a/core/bentley/src/YieldManager.ts b/core/bentley/src/YieldManager.ts new file mode 100644 index 000000000000..0fa51479a3dc --- /dev/null +++ b/core/bentley/src/YieldManager.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ + +/** @internal options for constructing yield managers */ +export interface YieldManagerOptions { + iterationsBeforeYield?: number; +} + +/** @internal the default options when constructing yield managers */ +const defaultYieldManagerOptions: Required = { + iterationsBeforeYield: 1000, +}; + +/** + * @internal + * An object allowing code to optionally yield with some frequency. + * useful in some intense loops that make processes unresponsive. + * primarily a workaround for: https://github.com/nodejs/node-addon-api/issues/1140 + * @note see [[defaultYieldManagerOptions]], the default amount of times it must be called to cause an actual yield is 1000 + */ +export class YieldManager { + public options: Readonly>; + private _counter = 0; + + public constructor(options: YieldManagerOptions = {}) { + this.options = { ...defaultYieldManagerOptions, ...options }; + } + + public async allowYield() { + this._counter = (this._counter + 1) % this.options.iterationsBeforeYield; + if (this._counter === 0) { + await this.actualYield(); + } + } + + protected async actualYield() { + await new Promise((r) => setTimeout(r, 0)); + } +} diff --git a/core/bentley/src/core-bentley.ts b/core/bentley/src/core-bentley.ts index 120f29384ce9..eb3fd93c31bb 100644 --- a/core/bentley/src/core-bentley.ts +++ b/core/bentley/src/core-bentley.ts @@ -33,6 +33,7 @@ export * from "./StringUtils"; export * from "./Time"; export * from "./UnexpectedErrors"; export * from "./UtilityTypes"; +export * from "./YieldManager"; /** @docs-package-description * The core-bentley package contains classes to solve problems that are common for both client and server use cases. diff --git a/core/bentley/src/test/YieldManager.test.ts b/core/bentley/src/test/YieldManager.test.ts new file mode 100644 index 000000000000..e3c871133a16 --- /dev/null +++ b/core/bentley/src/test/YieldManager.test.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +import { expect } from "chai"; +import { YieldManager } from "../YieldManager"; + +describe("YieldManager", () => { + it("allowYield yields once per 'iterationsBeforeYield' iterations", async () => { + class CountingYieldManager extends YieldManager { + public actualYieldCount = 0; + protected override async actualYield() { this.actualYieldCount++; } + } + + const expectedYieldTimes = 5; + const yieldManager = new CountingYieldManager(); + for (let i = 0; i < expectedYieldTimes * yieldManager.options.iterationsBeforeYield; ++i) { + await yieldManager.allowYield(); + } + expect(yieldManager.actualYieldCount).to.equal(expectedYieldTimes); + }); +}); diff --git a/core/common/CHANGELOG.json b/core/common/CHANGELOG.json index 3557632e7ad3..f5711fab31af 100644 --- a/core/common/CHANGELOG.json +++ b/core/common/CHANGELOG.json @@ -1,6 +1,24 @@ { "name": "@itwin/core-common", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-common_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-common_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": { + "none": [ + { + "comment": "Migrated from deprecated MapBox api." + } + ] + } + }, { "version": "3.0.0", "tag": "@itwin/core-common_v3.0.0", diff --git a/core/common/CHANGELOG.md b/core/common/CHANGELOG.md index 020d4b9b7a37..12e0919fc4e4 100644 --- a/core/common/CHANGELOG.md +++ b/core/common/CHANGELOG.md @@ -1,6 +1,18 @@ # Change Log - @itwin/core-common -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +### Updates + +- Migrated from deprecated MapBox api. ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/common/package.json b/core/common/package.json index 7c100e148da9..73053c21c9c1 100644 --- a/core/common/package.json +++ b/core/common/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-common", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js components common to frontend and backend", "main": "lib/cjs/core-common.js", "module": "lib/esm/core-common.js", "typings": "lib/cjs/core-common", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s build:cjs", @@ -35,14 +34,15 @@ "url": "http://www.bentley.com" }, "dependencies": { - "@ungap/url-search-params": "^0.1.2", + "buffer": "^6.0.3", "flatbuffers": "~1.12.0", "semver": "^5.5.0", + "string_decoder": "^1.3.0", "js-base64": "^3.6.1" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21" }, "devDependencies": { "@itwin/build-tools": "workspace:*", diff --git a/core/common/src/BackgroundMapProvider.ts b/core/common/src/BackgroundMapProvider.ts index 99d69676a5d1..efa111644943 100644 --- a/core/common/src/BackgroundMapProvider.ts +++ b/core/common/src/BackgroundMapProvider.ts @@ -80,4 +80,14 @@ export class BackgroundMapProvider { public equals(other: BackgroundMapProvider): boolean { return this.name === other.name && this.type === other.type; } + + /** Produce a copy of this provider with identical properties except for those explicitly specified by `changedProps`. + * Any properties explicitly set to `undefined` in `changedProps` will be reset to their default values. + */ + public clone(changedProps: BackgroundMapProviderProps): BackgroundMapProvider { + return BackgroundMapProvider.fromJSON({ + ...this.toJSON(), + ...changedProps, + }); + } } diff --git a/core/common/src/ColorByName.ts b/core/common/src/ColorByName.ts index dc1174615e18..1a9cdff6a9e4 100644 --- a/core/common/src/ColorByName.ts +++ b/core/common/src/ColorByName.ts @@ -12,155 +12,155 @@ * @note If your colors don't look right, likely you're using 0xRRGGBB where ColorDef expects 0xBBGGRR. * @public */ -export enum ColorByName { - aliceBlue = 0xFFF8F0, - amber = 0x00BFFF, - antiqueWhite = 0xD7EBFA, - aqua = 0xFFFF00, - aquamarine = 0xD4FF7F, - azure = 0xFFFFF0, - beige = 0xDCF5F5, - bisque = 0xC4E4FF, - black = 0x000000, - blanchedAlmond = 0xCDEBFF, - blue = 0xFF0000, - blueViolet = 0xE22B8A, - brown = 0x2A2AA5, - burlyWood = 0x87B8DE, - cadetBlue = 0xA09E5F, - chartreuse = 0x00FF7F, - chocolate = 0x1E69D2, - coral = 0x507FFF, - cornflowerBlue = 0xED9564, - cornSilk = 0xDCF8FF, - crimson = 0x3C14DC, - cyan = 0xFFFF00, - darkBlue = 0x8B0000, - darkBrown = 0x214365, - darkCyan = 0x8B8B00, - darkGoldenrod = 0x0B86B8, - darkGray = 0xA9A9A9, - darkGreen = 0x006400, - darkGrey = 0xA9A9A9, - darkKhaki = 0x6BB7BD, - darkMagenta = 0x8B008B, - darkOliveGreen = 0x2F6B55, - darkOrange = 0x008CFF, - darkOrchid = 0xCC3299, - darkRed = 0x00008B, - darkSalmon = 0x7A96E9, - darkSeagreen = 0x8FBC8F, - darkSlateBlue = 0x8B3D48, - darkSlateGray = 0x4F4F2F, - darkSlateGrey = 0x4F4F2F, - darkTurquoise = 0xD1CE00, - darkViolet = 0xD30094, - deepPink = 0x9314FF, - deepSkyBlue = 0xFFBF00, - dimGray = 0x696969, - dimGrey = 0x696969, - dodgerBlue = 0xFF901E, - fireBrick = 0x2222B2, - floralWhite = 0xF0FAFF, - forestGreen = 0x228B22, - fuchsia = 0xFF00FF, - gainsboro = 0xDCDCDC, - ghostWhite = 0xFFF8F8, - gold = 0x00D7FF, - goldenrod = 0x20A5DA, - gray = 0x808080, - green = 0x008000, - greenYellow = 0x2FFFAD, - grey = 0x808080, - honeydew = 0xF0FFF0, - hotPink = 0xB469FF, - indianRed = 0x5C5CCD, - indigo = 0x82004B, - ivory = 0xF0FFFF, - khaki = 0x8CE6F0, - lavender = 0xFAE6E6, - lavenderBlush = 0xF5F0FF, - lawnGreen = 0x00FC7C, - lemonChiffon = 0xCDFAFF, - lightBlue = 0xE6D8AD, - lightCoral = 0x8080F0, - lightCyan = 0xFFFFE0, - lightGoldenrodYellow = 0xD2FAFA, - lightGray = 0xD3D3D3, - lightGreen = 0x90EE90, - lightGrey = 0xD3D3D3, - lightPink = 0xC1B6FF, - lightSalmon = 0x7AA0FF, - lightSeagreen = 0xAAB220, - lightSkyBlue = 0xFACE87, - lightSlateGray = 0x998877, - lightSlateGrey = 0x998877, - lightSteelBlue = 0xDEC4B0, - lightyellow = 0xE0FFFF, - lime = 0x00FF00, - limeGreen = 0x32CD32, - linen = 0xE6F0FA, - magenta = 0xFF00FF, - maroon = 0x000080, - mediumAquamarine = 0xAACD66, - mediumBlue = 0xCD0000, - mediumOrchid = 0xD355BA, - mediumPurple = 0xDB7093, - mediumSeaGreen = 0x71B33C, - mediumSlateBlue = 0xEE687B, - mediumSpringGreen = 0x9AFA00, - mediumTurquoise = 0xCCD148, - mediumVioletRed = 0x8515C7, - midnightBlue = 0x701919, - mintCream = 0xFAFFF5, - mistyRose = 0xE1E4FF, - moccasin = 0xB5E4FF, - navajoWhite = 0xADDEFF, - navy = 0x800000, - oldLace = 0xE6F5FD, - olive = 0x008080, - oliveDrab = 0x238E6B, - orange = 0x00A5FF, - orangeRed = 0x0045FF, - orchid = 0xD670DA, - paleGoldenrod = 0xAAE8EE, - paleGreen = 0x98FB98, - paleTurquoise = 0xEEEEAF, - paleVioletRed = 0x9370DB, - papayaWhip = 0xD5EFFF, - peachPuff = 0xB9DAFF, - peru = 0x3F85CD, - pink = 0xCBC0FF, - plum = 0xDDA0DD, - powderBlue = 0xE6E0B0, - purple = 0x800080, - rebeccaPurple = 0x993366, - red = 0x0000FF, - rosyBrown = 0x8F8FBC, - royalBlue = 0xE16941, - saddleBrown = 0x13458B, - salmon = 0x7280FA, - sandyBrown = 0x60A4F4, - seaGreen = 0x578B2E, - seaShell = 0xEEF5FF, - sienna = 0x2D52A0, - silver = 0xC0C0C0, - skyBlue = 0xEBCE87, - slateBlue = 0xCD5A6A, - slateGray = 0x908070, - slateGrey = 0x908070, - snow = 0xFAFAFF, - springGreen = 0x7FFF00, - steelBlue = 0xB48246, - tan = 0x8CB4D2, - teal = 0x808000, - thistle = 0xD8BFD8, - tomato = 0x4763FF, - turquoise = 0xD0E040, - violet = 0xEE82EE, - wheat = 0xB3DEF5, - white = 0xFFFFFF, - whiteSmoke = 0xF5F5F5, - yellow = 0x00FFFF, - yellowGreen = 0x32CD9A, -} +export const ColorByName = { // eslint-disable-line @typescript-eslint/naming-convention + aliceBlue: 0xFFF8F0, + amber: 0x00BFFF, + antiqueWhite: 0xD7EBFA, + aqua: 0xFFFF00, + aquamarine: 0xD4FF7F, + azure: 0xFFFFF0, + beige: 0xDCF5F5, + bisque: 0xC4E4FF, + black: 0x000000, + blanchedAlmond: 0xCDEBFF, + blue: 0xFF0000, + blueViolet: 0xE22B8A, + brown: 0x2A2AA5, + burlyWood: 0x87B8DE, + cadetBlue: 0xA09E5F, + chartreuse: 0x00FF7F, + chocolate: 0x1E69D2, + coral: 0x507FFF, + cornflowerBlue: 0xED9564, + cornSilk: 0xDCF8FF, + crimson: 0x3C14DC, + cyan: 0xFFFF00, + darkBlue: 0x8B0000, + darkBrown: 0x214365, + darkCyan: 0x8B8B00, + darkGoldenrod: 0x0B86B8, + darkGray: 0xA9A9A9, + darkGreen: 0x006400, + darkGrey: 0xA9A9A9, + darkKhaki: 0x6BB7BD, + darkMagenta: 0x8B008B, + darkOliveGreen: 0x2F6B55, + darkOrange: 0x008CFF, + darkOrchid: 0xCC3299, + darkRed: 0x00008B, + darkSalmon: 0x7A96E9, + darkSeagreen: 0x8FBC8F, + darkSlateBlue: 0x8B3D48, + darkSlateGray: 0x4F4F2F, + darkSlateGrey: 0x4F4F2F, + darkTurquoise: 0xD1CE00, + darkViolet: 0xD30094, + deepPink: 0x9314FF, + deepSkyBlue: 0xFFBF00, + dimGray: 0x696969, + dimGrey: 0x696969, + dodgerBlue: 0xFF901E, + fireBrick: 0x2222B2, + floralWhite: 0xF0FAFF, + forestGreen: 0x228B22, + fuchsia: 0xFF00FF, + gainsboro: 0xDCDCDC, + ghostWhite: 0xFFF8F8, + gold: 0x00D7FF, + goldenrod: 0x20A5DA, + gray: 0x808080, + green: 0x008000, + greenYellow: 0x2FFFAD, + grey: 0x808080, + honeydew: 0xF0FFF0, + hotPink: 0xB469FF, + indianRed: 0x5C5CCD, + indigo: 0x82004B, + ivory: 0xF0FFFF, + khaki: 0x8CE6F0, + lavender: 0xFAE6E6, + lavenderBlush: 0xF5F0FF, + lawnGreen: 0x00FC7C, + lemonChiffon: 0xCDFAFF, + lightBlue: 0xE6D8AD, + lightCoral: 0x8080F0, + lightCyan: 0xFFFFE0, + lightGoldenrodYellow: 0xD2FAFA, + lightGray: 0xD3D3D3, + lightGreen: 0x90EE90, + lightGrey: 0xD3D3D3, + lightPink: 0xC1B6FF, + lightSalmon: 0x7AA0FF, + lightSeagreen: 0xAAB220, + lightSkyBlue: 0xFACE87, + lightSlateGray: 0x998877, + lightSlateGrey: 0x998877, + lightSteelBlue: 0xDEC4B0, + lightyellow: 0xE0FFFF, + lime: 0x00FF00, + limeGreen: 0x32CD32, + linen: 0xE6F0FA, + magenta: 0xFF00FF, + maroon: 0x000080, + mediumAquamarine: 0xAACD66, + mediumBlue: 0xCD0000, + mediumOrchid: 0xD355BA, + mediumPurple: 0xDB7093, + mediumSeaGreen: 0x71B33C, + mediumSlateBlue: 0xEE687B, + mediumSpringGreen: 0x9AFA00, + mediumTurquoise: 0xCCD148, + mediumVioletRed: 0x8515C7, + midnightBlue: 0x701919, + mintCream: 0xFAFFF5, + mistyRose: 0xE1E4FF, + moccasin: 0xB5E4FF, + navajoWhite: 0xADDEFF, + navy: 0x800000, + oldLace: 0xE6F5FD, + olive: 0x008080, + oliveDrab: 0x238E6B, + orange: 0x00A5FF, + orangeRed: 0x0045FF, + orchid: 0xD670DA, + paleGoldenrod: 0xAAE8EE, + paleGreen: 0x98FB98, + paleTurquoise: 0xEEEEAF, + paleVioletRed: 0x9370DB, + papayaWhip: 0xD5EFFF, + peachPuff: 0xB9DAFF, + peru: 0x3F85CD, + pink: 0xCBC0FF, + plum: 0xDDA0DD, + powderBlue: 0xE6E0B0, + purple: 0x800080, + rebeccaPurple: 0x993366, + red: 0x0000FF, + rosyBrown: 0x8F8FBC, + royalBlue: 0xE16941, + saddleBrown: 0x13458B, + salmon: 0x7280FA, + sandyBrown: 0x60A4F4, + seaGreen: 0x578B2E, + seaShell: 0xEEF5FF, + sienna: 0x2D52A0, + silver: 0xC0C0C0, + skyBlue: 0xEBCE87, + slateBlue: 0xCD5A6A, + slateGray: 0x908070, + slateGrey: 0x908070, + snow: 0xFAFAFF, + springGreen: 0x7FFF00, + steelBlue: 0xB48246, + tan: 0x8CB4D2, + teal: 0x808000, + thistle: 0xD8BFD8, + tomato: 0x4763FF, + turquoise: 0xD0E040, + violet: 0xEE82EE, + wheat: 0xB3DEF5, + white: 0xFFFFFF, + whiteSmoke: 0xF5F5F5, + yellow: 0x00FFFF, + yellowGreen: 0x32CD9A, +}; diff --git a/core/common/src/ColorDef.ts b/core/common/src/ColorDef.ts index 96b2b878ba17..5c213df368cd 100644 --- a/core/common/src/ColorDef.ts +++ b/core/common/src/ColorDef.ts @@ -18,26 +18,28 @@ import { HSVColor, HSVConstants } from "./HSVColor"; const scratchBytes = new Uint8Array(4); const scratchUInt32 = new Uint32Array(scratchBytes.buffer); -/** An unsigned 32-bit integer in 0xTTBBGGRR format +/** The JSON representation of a [[ColorDef]] - an unsigned 32-bit integer in 0xTTBBGGRR format. * @public */ export type ColorDefProps = number; /** An immutable integer representation of a color. * - * Colors are stored as 4 components: Red, Blue, Green, and Transparency (0=fully opaque). Each is an 8-bit integer between 0-255. + * A color consists of 4 components: Red, Blue, Green, and Transparency. Each component is an 8-bit unsigned integer in the range [0..255]. A value of zero means that component contributes nothing + * to the color: e.g., a color with Red=0 contains no shade of red, and a color with Transparency=0 is fully opaque. A value of 255 means that component contributes its maximum + * value to the color: e.g., a color with Red=255 is as red as it is possible to be, and a color with Transparency=255 is fully transparent. * - * Much confusion results from attempting to interpret those 4 one-byte values as a 4 byte integer. There are generally two sources - * of confusion: - * 1. The ordering of the Red, Green, Blue bytes; and + * Internally, these 4 components are combined into a single 32-bit unsigned integer as represented by [[ColorDefProps]]. This representation can result in some confusion regarding: + * 1. The ordering of the individual components; and * 2. Whether to specify transparency or opacity (sometimes referred to as "alpha"). * - * ColorDef uses `0xTTBBGGRR` (red in the low byte. 0==fully opaque in high byte) internally, but it also provides methods - * to convert to `0xRRGGBB` (see [[getRgb]]) and `0xAABBGGRR` (red in the low byte, 0==fully transparent in high byte. see [[getAbgr]]). + * ColorDef uses `0xTTBBGGRR` internally, which uses Transparency and puts Red in the low byte and Transparency in the high byte. It can be converted to `0xRRGGBB` format (blue in the low byte) + * using [[getRgb]] and `0xAABBGGRRx format (red in the low byte, using opacity instead of transparency) using [[getAbgr]]. * - * The [[create]] method also accepts strings in the common HTML formats. + * A ColorDef can be created from a numeric [[ColorDefProps]], from a string in one of the common HTML formats (e.g., [[fromString]]), or by specifying values for the individual components + * (e.g., [[from]]). * - * ColorDef is immutable. To obtain a modified copy of a ColorDef, use methods like [[adjustedForContrast]], [[inverse]], or [[withTransparency]]. For example: + * ColorDef is **immutable**. To obtain a modified copy of a ColorDef, use methods like [[adjustedForContrast]], [[inverse]], or [[withTransparency]]. For example: * ```ts * const semiTransparentBlue = ColorDef.blue.withTransparency(100); * ``` @@ -55,21 +57,14 @@ export class ColorDef { * Create a new ColorDef. * @param val value to use. * If a number, it is interpreted as a 0xTTBBGGRR (Red in the low byte, high byte is transparency 0==fully opaque) value. - * - * If a string, must be in one of the following forms: - * *"rgb(255,0,0)"* - * *"rgba(255,0,0,.2)"* - * *"rgb(100%,0%,0%)"* - * *"hsl(120,50%,50%)"* - * *"#rrggbb"* - * *"blanchedAlmond"* (see possible values from [[ColorByName]]). Case insensitive. + * If a string, it must be in one of the forms supported by [[fromString]] - any unrecognized string will produce [[black]]. */ public static create(val?: string | ColorDefProps) { return this.fromTbgr(this.computeTbgr(val)); } /** @internal */ - public static computeTbgr(val?: string | ColorDefProps): number { + public static computeTbgr(val?: string | ColorDefProps): ColorDefProps { switch (typeof val) { case "number": return val; @@ -94,7 +89,7 @@ export class ColorDef { } /** Compute the 0xTTBBGGRR value corresponding to the specified Red, Green, Blue, Transparency components. All inputs should be integers between 0-255. */ - public static computeTbgrFromComponents(red: number, green: number, blue: number, transparency?: number): number { + public static computeTbgrFromComponents(red: number, green: number, blue: number, transparency?: number): ColorDefProps { scratchBytes[0] = red; scratchBytes[1] = green; scratchBytes[2] = blue; @@ -103,7 +98,7 @@ export class ColorDef { } /** Create a ColorDef from its 0xTTBBGGRR representation. */ - public static fromTbgr(tbgr: number): ColorDef { + public static fromTbgr(tbgr: ColorDefProps): ColorDef { switch (tbgr) { case ColorByName.black: return this.black; @@ -127,22 +122,41 @@ export class ColorDef { * *"hsl(120,50%,50%)"* * *"#rrbbgg"* * *"blanchedAlmond"* (see possible values from [[ColorByName]]). Case-insensitive. + * + * If `val` is not a valid color string, this function returns [[black]]. + * @see [[isValidColor]] to determine if `val` is a valid color string. */ public static fromString(val: string): ColorDef { return this.fromTbgr(this.computeTbgrFromString(val)); } - /** Compute the 0xTTBBGGRR value corresponding to a string representation of a color. The following representations are supported: - * *"rgb(255,0,0)"* - * *"rgba(255,0,0,.2)"* - * *"rgb(100%,0%,0%)"* - * *"hsl(120,50%,50%)"* - * *"#rrbbgg"* - * *"blanchedAlmond"* (see possible values from [[ColorByName]]). Case-insensitive. + /** Determine whether the input is a valid representation of a ColorDef. + * @see [[fromString]] for the definition of a valid string representation. + * @see [[ColorDefProps]] for the definition of a valid numeric representation. + */ + public static isValidColor(val: string | number): boolean { + if (typeof val === "number") + return val >= 0 && val <= 0xffffffff && Math.floor(val) === val; + + return undefined !== this.tryComputeTbgrFromString(val); + } + + /** Compute the 0xTTBBGGRR value corresponding to a string representation of a color. + * If `val` is not a valid color string, this function returns 0 (black). + * @see [[fromString]] for the definition of a valid color string. + * @see [[tryComputeTbgrFromString]] to determine if `val` is a valid color string. */ - public static computeTbgrFromString(val: string): number { + public static computeTbgrFromString(val: string): ColorDefProps { + return this.tryComputeTbgrFromString(val) ?? 0; + } + + /** Try to compute the 0xTTBBGGRR value corresponding to a string representation of a ColorDef. + * @returns the corresponding numeric representation, or `undefined` if the input does not represent a color. + * @see [[fromString]] for the definition of a valid color string. + */ + public static tryComputeTbgrFromString(val: string): ColorDefProps | undefined { if (typeof val !== "string") - return 0; + return undefined; val = val.toLowerCase(); let m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(val); @@ -207,21 +221,21 @@ export class ColorDef { } if (val && val.length > 0) { // ColorRgb value - const colorByName = Object.entries(ColorByName).find((entry) => typeof entry[1] === "string" && entry[1].toLowerCase() === val); - if (colorByName) - return Number(colorByName[0]); + for (const [key, value] of Object.entries(ColorByName)) + if (key.toLowerCase() === val) + return value; } - return 0; + return undefined; } - /** Get the r,g,b,t values from this ColorDef. Values will be integers between 0-255. */ + /** Get the red, green, blue, and transparency values from this ColorDef. Values will be integers between 0-255. */ public get colors(): { r: number, g: number, b: number, t: number } { return ColorDef.getColors(this._tbgr); } /** Get the r,g,b,t values encoded in an 0xTTBBGGRR value. Values will be integers between 0-255. */ - public static getColors(tbgr: number) { + public static getColors(tbgr: ColorDefProps) { scratchUInt32[0] = tbgr; return { b: scratchBytes[2], @@ -232,7 +246,7 @@ export class ColorDef { } /** The color value of this ColorDef as an integer in the form 0xTTBBGGRR (red in the low byte) */ - public get tbgr(): number { return this._tbgr; } + public get tbgr(): ColorDefProps { return this._tbgr; } /** Get the value of the color as a number in 0xAABBGGRR format (i.e. red is in low byte). Transparency (0==fully opaque) converted to alpha (0==fully transparent). */ public getAbgr(): number { @@ -240,7 +254,7 @@ export class ColorDef { } /** Get the value of a 0xTTBBGGRR color as a number in 0xAABBGGRR format (i.e. red is in low byte). Transparency (0==fully opaque) converted to alpha (0==fully transparent). */ - public static getAbgr(tbgr: number): number { + public static getAbgr(tbgr: ColorDefProps): number { scratchUInt32[0] = tbgr; scratchBytes[3] = 255 - scratchBytes[3]; return scratchUInt32[0]; @@ -252,7 +266,7 @@ export class ColorDef { } /** Get the RGB value of the 0xTTBBGGRR color as a number in 0xRRGGBB format (i.e blue is in the low byte). Transparency is ignored. Value will be from 0 to 2^24 */ - public static getRgb(tbgr: number): number { + public static getRgb(tbgr: ColorDefProps): number { scratchUInt32[0] = tbgr; return (scratchBytes[0] << 16) + (scratchBytes[1] << 8) + scratchBytes[2]; } @@ -270,7 +284,7 @@ export class ColorDef { * @param alpha the new alpha value as an integer between 0-255. * @returns The 0xTTBBGGRR value equivalent to `tbgr` but with the specified alpha. */ - public static withAlpha(tbgr: number, alpha: number): number { + public static withAlpha(tbgr: ColorDefProps, alpha: number): number { scratchUInt32[0] = tbgr; scratchBytes[3] = 255 - (alpha | 0); return scratchUInt32[0]; @@ -282,7 +296,7 @@ export class ColorDef { } /** Extract the alpha value from a 0xTTBBGGRR color. */ - public static getAlpha(tbgr: number): number { + public static getAlpha(tbgr: ColorDefProps): number { scratchUInt32[0] = tbgr; return 255 - scratchBytes[3]; } @@ -293,7 +307,7 @@ export class ColorDef { } /** True if the specified 0xTTBBGGRR color is fully opaque. */ - public static isOpaque(tbgr: number): boolean { + public static isOpaque(tbgr: ColorDefProps): boolean { return 255 === this.getAlpha(tbgr); } @@ -303,7 +317,7 @@ export class ColorDef { } /** Extract the transparency component from a 0xTTBBGGRR color as an integer between 0-255.. */ - public static getTransparency(tbgr: number): number { + public static getTransparency(tbgr: ColorDefProps): number { scratchUInt32[0] = tbgr; return scratchBytes[3]; } @@ -321,7 +335,7 @@ export class ColorDef { * @param transparency the new transparency as an integer between 0-255. * @returns The 0xTTBBGGRR value equivalent to `tbgr` but with the specified transparency. */ - public static withTransparency(tbgr: number, transparency: number): number { + public static withTransparency(tbgr: ColorDefProps, transparency: number): ColorDefProps { return this.withAlpha(tbgr, 255 - transparency); } @@ -330,9 +344,15 @@ export class ColorDef { return ColorDef.getName(this.tbgr); } - /** Obtain the name of the color in the [[ColorByName]] list associated with the specified 0xTTBBGGRR value, or undefined if no such named color exists. */ - public static getName(tbgr: number): string | undefined { - return ColorByName[tbgr]; + /** Obtain the name of the color in the [[ColorByName]] list associated with the specified 0xTTBBGGRR value, or undefined if no such named color exists. + * @note A handful of colors (like "aqua" and "cyan") have identical tbgr values; in such cases the first match will be returned. + */ + public static getName(tbgr: ColorDefProps): string | undefined { + for (const [key, value] of Object.entries(ColorByName)) + if (value === tbgr) + return key; + + return undefined; } /** Convert this ColorDef to a string in the form "#rrggbb" where values are hex digits of the respective colors */ @@ -341,11 +361,11 @@ export class ColorDef { } /** Convert the 0xTTBBGGRR value to a string in the form "#rrggbb". */ - public static toHexString(tbgr: number): string { + public static toHexString(tbgr: ColorDefProps): string { return `#${(`000000${this.getRgb(tbgr).toString(16)}`).slice(-6)}`; } - private static getColorsString(tbgr: number) { + private static getColorsString(tbgr: ColorDefProps) { const c = this.getColors(tbgr); return `${c.r},${c.g},${c.b}`; } @@ -356,7 +376,7 @@ export class ColorDef { } /** Convert the 0xTTBBGGRR color to a string in the form "rgb(r,g,b)" where each component is specified in decimal. */ - public static toRgbString(tbgr: number): string { + public static toRgbString(tbgr: ColorDefProps): string { return `rgb(${this.getColorsString(tbgr)})`; } @@ -366,7 +386,7 @@ export class ColorDef { } /** Convert the 0xTTBBGGRR color to a string of the form "rgba(r,g,b,a)" where the color components are specified in decimal and the alpha component is a fraction. */ - public static toRgbaString(tbgr: number): string { + public static toRgbaString(tbgr: ColorDefProps): string { return `rgba(${this.getColorsString(tbgr)},${this.getAlpha(tbgr) / 255.})`; } @@ -385,7 +405,7 @@ export class ColorDef { * @param weight The weighting factor in [0..1]. A value of 0.0 selects `tbgr1`; 1.0 selects `tbgr2`; 0.5 mixes them evenly; etc. * @returns The linear interpolation between `tbgr1` and `tbgr2` using the specified weight. */ - public static lerp(tbgr1: number, tbgr2: number, weight: number): number { + public static lerp(tbgr1: ColorDefProps, tbgr2: ColorDefProps, weight: number): ColorDefProps { const c = this.getColors(tbgr1); const color = this.getColors(tbgr2); c.r += (color.r - c.r) * weight; @@ -400,7 +420,7 @@ export class ColorDef { } /** Return a 0xTTBBGGRR color whose color components are the inverse of the input color. The result has 0 transparency. */ - public static inverse(tbgr: number): number { + public static inverse(tbgr: ColorDefProps): ColorDefProps { const colors = this.getColors(tbgr); return this.computeTbgrFromComponents(255 - colors.r, 255 - colors.g, 255 - colors.b); } @@ -411,7 +431,7 @@ export class ColorDef { } /** Compute the 0xTTBBGGRR color corresponding to the specified hue, saturation, lightness values. */ - public static computeTbgrFromHSL(h: number, s: number, l: number, transparency = 0): number { + public static computeTbgrFromHSL(h: number, s: number, l: number, transparency = 0): ColorDefProps { const torgb = (p1: number, q1: number, t: number) => { if (t < 0) t += 1; if (t > 1) t -= 1; diff --git a/core/common/src/rpc/core/RpcInvocation.ts b/core/common/src/rpc/core/RpcInvocation.ts index cd073c87690d..312b5fd2d9b7 100644 --- a/core/common/src/rpc/core/RpcInvocation.ts +++ b/core/common/src/rpc/core/RpcInvocation.ts @@ -216,15 +216,12 @@ export class RpcInvocation { const result = await RpcMarshaling.serialize(this.protocol, reason); - let isNoContentError = false; - try { isNoContentError = reason.errorNumber === IModelStatus.NoContent; } catch { } - if (reason instanceof RpcPendingResponse) { this._pending = true; this._threw = false; result.objects = reason.message; this.protocol.events.raiseEvent(RpcProtocolEvent.BackendReportedPending, this); - } else if (this.supportsNoContent() && isNoContentError) { + } else if (this.supportsNoContent() && reason?.errorNumber === IModelStatus.NoContent) { this._noContent = true; this._threw = false; this.protocol.events.raiseEvent(RpcProtocolEvent.BackendReportedNoContent, this); diff --git a/core/common/src/rpc/core/RpcMarshaling.ts b/core/common/src/rpc/core/RpcMarshaling.ts index 64ddc8698de9..d15a2c29d4e1 100644 --- a/core/common/src/rpc/core/RpcMarshaling.ts +++ b/core/common/src/rpc/core/RpcMarshaling.ts @@ -6,6 +6,7 @@ * @module RpcInterface */ +import { Buffer } from "buffer"; import { Readable } from "stream"; import { BentleyStatus, IModelError } from "../../IModelError"; import { RpcProtocol } from "./RpcProtocol"; diff --git a/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts b/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts index 0f52611b32d3..524514365119 100644 --- a/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts +++ b/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts @@ -6,7 +6,6 @@ * @module RpcInterface */ -import { URL } from "url"; import { BentleyStatus } from "@itwin/core-bentley"; import { IModelRpcProps } from "../../IModel"; import { IModelError } from "../../IModelError"; diff --git a/core/common/src/rpc/web/WebAppRpcLogging.ts b/core/common/src/rpc/web/WebAppRpcLogging.ts index 557826cd4312..129d4a1516ab 100644 --- a/core/common/src/rpc/web/WebAppRpcLogging.ts +++ b/core/common/src/rpc/web/WebAppRpcLogging.ts @@ -16,18 +16,22 @@ import { SerializedRpcOperation, SerializedRpcRequest } from "../core/RpcProtoco import { RpcRequest } from "../core/RpcRequest"; import { WebAppRpcRequest } from "./WebAppRpcRequest"; -// eslint-disable-next-line @typescript-eslint/no-var-requires -const os = (typeof (process) !== "undefined") ? require("os") : undefined; +let hostname = ""; function getHostname(): string { - if (os !== undefined) { - return os.hostname(); - } else { - if (typeof (window) !== "undefined") { - return window.location.host; - } else { - return "imodeljs-mobile"; + if (!hostname) { + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const os = require("os"); + hostname = os.hostname(); + } catch (_) { + if (globalThis.window) { + hostname = globalThis.window.location.host; + } else { + hostname = "imodeljs-mobile"; + } } } + return hostname; } /** @internal */ diff --git a/core/common/src/rpc/web/WebAppRpcRequest.ts b/core/common/src/rpc/web/WebAppRpcRequest.ts index 5b4a3a26cec3..30bdb14ff73f 100644 --- a/core/common/src/rpc/web/WebAppRpcRequest.ts +++ b/core/common/src/rpc/web/WebAppRpcRequest.ts @@ -6,7 +6,6 @@ * @module RpcInterface */ -import "@ungap/url-search-params/index"; import { BentleyStatus } from "@itwin/core-bentley"; import { IModelError, ServerError, ServerTimeoutError } from "../../IModelError"; import { RpcInterface } from "../../RpcInterface"; diff --git a/core/common/src/test/ColorDef.test.ts b/core/common/src/test/ColorDef.test.ts index d764fbafdb59..bfd567660d79 100644 --- a/core/common/src/test/ColorDef.test.ts +++ b/core/common/src/test/ColorDef.test.ts @@ -2,7 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { assert, expect } from "chai"; import { ColorByName } from "../ColorByName"; import { ColorDef } from "../ColorDef"; @@ -130,4 +130,46 @@ describe("ColorDef", () => { assert.equal(100, t2.t); }); + + it("determines whether string and numeric values represent valid colors", () => { + for (const [key, value] of Object.entries(ColorByName)) { + expect(ColorDef.isValidColor(key)).to.be.true; + expect(ColorDef.isValidColor(`${key}xx`)).to.be.false; + + expect(ColorDef.isValidColor(value)).to.be.true; + expect(ColorDef.isValidColor(value + 0.5)).to.be.false; + expect(ColorDef.isValidColor(-value)).to.equal(0 === value); + } + + expect(ColorDef.isValidColor(0x100000000)).to.be.false; + }); + + it("looks up name from numeric representation", () => { + interface Duplicates { + [key: string]: keyof typeof ColorByName | undefined; + } + + const duplicates: Duplicates = { + cyan: "aqua", + darkGrey: "darkGray", + darkSlateGrey: "darkSlateGray", + dimGrey: "dimGray", + grey: "gray", + lightGrey: "lightGray", + lightSlateGrey: "lightSlateGray", + magenta: "fuchsia", + slateGrey: "slateGray", + }; + + for (const [key, value] of Object.entries(ColorByName)) { + const name = ColorDef.getName(value); + const duplicate = duplicates[key]; + if (duplicate) { + expect(name).to.equal(duplicate); + expect(value).to.equal(ColorByName[duplicate]); + } else { + expect(name).to.equal(key); + } + } + }); }); diff --git a/core/ecschema-editing/CHANGELOG.json b/core/ecschema-editing/CHANGELOG.json index f9eff3c65521..993cc618ded8 100644 --- a/core/ecschema-editing/CHANGELOG.json +++ b/core/ecschema-editing/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/ecschema-editing", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/ecschema-editing_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/ecschema-editing_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/ecschema-editing_v3.0.0", diff --git a/core/ecschema-editing/CHANGELOG.md b/core/ecschema-editing/CHANGELOG.md index a9d408ae1e74..85c4fc71b164 100644 --- a/core/ecschema-editing/CHANGELOG.md +++ b/core/ecschema-editing/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/ecschema-editing -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/ecschema-editing/package.json b/core/ecschema-editing/package.json index 111aabfaa92d..a968f0a9cf9d 100644 --- a/core/ecschema-editing/package.json +++ b/core/ecschema-editing/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/ecschema-editing", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "ECSchema editing and validation API", "license": "MIT", "main": "lib/cjs/ecschema-editing.js", @@ -62,9 +62,9 @@ "typescript": "~4.4.0" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-quantity": "workspace:^3.1.0-dev.33", - "@itwin/ecschema-metadata": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-quantity": "workspace:^3.2.0-dev.21", + "@itwin/ecschema-metadata": "workspace:^3.2.0-dev.21" }, "nyc": { "extends": "./node_modules/@itwin/build-tools/.nycrc" diff --git a/core/ecschema-locaters/CHANGELOG.json b/core/ecschema-locaters/CHANGELOG.json index 64294b12f86c..ffc8a7266d0d 100644 --- a/core/ecschema-locaters/CHANGELOG.json +++ b/core/ecschema-locaters/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/ecschema-locaters", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/ecschema-locaters_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/ecschema-locaters_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/ecschema-locaters_v3.0.0", diff --git a/core/ecschema-locaters/CHANGELOG.md b/core/ecschema-locaters/CHANGELOG.md index 2f59724b3e80..dd5b88e919e5 100644 --- a/core/ecschema-locaters/CHANGELOG.md +++ b/core/ecschema-locaters/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/ecschema-locaters -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/ecschema-locaters/package.json b/core/ecschema-locaters/package.json index 41375f794dd4..f2fb7b348e35 100644 --- a/core/ecschema-locaters/package.json +++ b/core/ecschema-locaters/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/ecschema-locaters", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "EC Schema file locaters", "license": "MIT", "main": "lib/cjs/ecschema-locaters.js", @@ -56,7 +56,7 @@ "glob": "^7.1.2" }, "peerDependencies": { - "@itwin/ecschema-metadata": "workspace:^3.1.0-dev.33" + "@itwin/ecschema-metadata": "workspace:^3.2.0-dev.21" }, "nyc": { "extends": "./node_modules/@itwin/build-tools/.nycrc", diff --git a/core/ecschema-metadata/CHANGELOG.json b/core/ecschema-metadata/CHANGELOG.json index 7859f7709614..3ffd2223ee67 100644 --- a/core/ecschema-metadata/CHANGELOG.json +++ b/core/ecschema-metadata/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/ecschema-metadata", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/ecschema-metadata_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/ecschema-metadata_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/ecschema-metadata_v3.0.0", diff --git a/core/ecschema-metadata/CHANGELOG.md b/core/ecschema-metadata/CHANGELOG.md index 063a0624dbaa..1766415a2807 100644 --- a/core/ecschema-metadata/CHANGELOG.md +++ b/core/ecschema-metadata/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/ecschema-metadata -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/ecschema-metadata/package.json b/core/ecschema-metadata/package.json index 7f8faeaeac2c..782232be187c 100644 --- a/core/ecschema-metadata/package.json +++ b/core/ecschema-metadata/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/ecschema-metadata", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "ECObjects core concepts in typescript", "license": "MIT", "main": "lib/cjs/ecschema-metadata.js", "typings": "lib/cjs/ecschema-metadata", - "imodeljsSharedLibrary": true, "repository": { "type": "git", "url": "https://github.com/iTwin/itwinjs-core/tree/master/core/ecschema-metadata" @@ -60,8 +59,8 @@ "typescript": "~4.4.0" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-quantity": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-quantity": "workspace:^3.2.0-dev.21" }, "dependencies": { "almost-equal": "^1.1.0" diff --git a/core/ecschema-rpc/common/CHANGELOG.json b/core/ecschema-rpc/common/CHANGELOG.json index e2851ceb683f..23ca1f8aec43 100644 --- a/core/ecschema-rpc/common/CHANGELOG.json +++ b/core/ecschema-rpc/common/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/ecschema-rpcinterface-common", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/ecschema-rpcinterface-common_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/ecschema-rpcinterface-common_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/ecschema-rpcinterface-common_v3.0.0", diff --git a/core/ecschema-rpc/common/CHANGELOG.md b/core/ecschema-rpc/common/CHANGELOG.md index da22f9e6d9c7..ffcfcba03109 100644 --- a/core/ecschema-rpc/common/CHANGELOG.md +++ b/core/ecschema-rpc/common/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/ecschema-rpcinterface-common -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/ecschema-rpc/common/package.json b/core/ecschema-rpc/common/package.json index 6d4b280c37d6..744c73401f0f 100644 --- a/core/ecschema-rpc/common/package.json +++ b/core/ecschema-rpc/common/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/ecschema-rpcinterface-common", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "Schema RPC Interface common interface", "main": "lib/cjs/ecschema-rpc-interface.js", "typings": "lib/cjs/ecschema-rpc-interface", diff --git a/core/ecschema-rpc/impl/CHANGELOG.json b/core/ecschema-rpc/impl/CHANGELOG.json index 2b90f6082161..c242ffcf1e7c 100644 --- a/core/ecschema-rpc/impl/CHANGELOG.json +++ b/core/ecschema-rpc/impl/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/ecschema-rpcinterface-impl", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/ecschema-rpcinterface-impl_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/ecschema-rpcinterface-impl_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/ecschema-rpcinterface-impl_v3.0.0", diff --git a/core/ecschema-rpc/impl/CHANGELOG.md b/core/ecschema-rpc/impl/CHANGELOG.md index a1c8379f757f..2eb90f239084 100644 --- a/core/ecschema-rpc/impl/CHANGELOG.md +++ b/core/ecschema-rpc/impl/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/ecschema-rpcinterface-impl -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/ecschema-rpc/impl/package.json b/core/ecschema-rpc/impl/package.json index 9197fe969c49..be1c3fc919ed 100644 --- a/core/ecschema-rpc/impl/package.json +++ b/core/ecschema-rpc/impl/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/ecschema-rpcinterface-impl", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "Schema RPC Interface backend implementation", "main": "lib/cjs/ecschema-rpc-impl.js", "typings": "lib/cjs/ecschema-rpc-impl", diff --git a/core/electron/CHANGELOG.json b/core/electron/CHANGELOG.json index 10f2f6bf957c..0bf0c7180c55 100644 --- a/core/electron/CHANGELOG.json +++ b/core/electron/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-electron", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-electron_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-electron_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-electron_v3.0.0", diff --git a/core/electron/CHANGELOG.md b/core/electron/CHANGELOG.md index 5ed7cbd2a042..1bdaebd6e76c 100644 --- a/core/electron/CHANGELOG.md +++ b/core/electron/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-electron -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/electron/package.json b/core/electron/package.json index ed12ef668184..d511fee471bd 100644 --- a/core/electron/package.json +++ b/core/electron/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/core-electron", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js ElectronHost and ElectronApp", "license": "MIT", "engines": { @@ -31,11 +31,11 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-backend": "workspace:^3.1.0-dev.33", - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-frontend": "workspace:^3.1.0-dev.33", - "@itwin/presentation-common": "workspace:^3.1.0-dev.33", + "@itwin/core-backend": "workspace:^3.2.0-dev.21", + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-frontend": "workspace:^3.2.0-dev.21", + "@itwin/presentation-common": "workspace:^3.2.0-dev.21", "electron": "^14.0.0" }, "devDependencies": { diff --git a/core/express-server/CHANGELOG.json b/core/express-server/CHANGELOG.json index f295b2b327fa..2263b9960b00 100644 --- a/core/express-server/CHANGELOG.json +++ b/core/express-server/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/express-server", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/express-server_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/express-server_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/express-server_v3.0.0", diff --git a/core/express-server/CHANGELOG.md b/core/express-server/CHANGELOG.md index 0a4196637c8c..4be04d3cebd2 100644 --- a/core/express-server/CHANGELOG.md +++ b/core/express-server/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/express-server -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/express-server/package.json b/core/express-server/package.json index c165b2c713a0..a2c7cbe4295a 100644 --- a/core/express-server/package.json +++ b/core/express-server/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/express-server", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js express utilities", "main": "lib/cjs/ExpressServer.js", "typings": "lib/cjs/ExpressServer", diff --git a/core/extension/.npmignore b/core/extension/.npmignore new file mode 100644 index 000000000000..53e923a86aa3 --- /dev/null +++ b/core/extension/.npmignore @@ -0,0 +1,5 @@ +# start off ignoring everything, and then add back only the files we want +* +!*.md +!*.d.ts +!*.js \ No newline at end of file diff --git a/core/extension/LICENSE.md b/core/extension/LICENSE.md new file mode 100644 index 000000000000..c1b0e7f3c704 --- /dev/null +++ b/core/extension/LICENSE.md @@ -0,0 +1,9 @@ +# MIT License + +Copyright © 2022 Bentley Systems, Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/core/extension/README.md b/core/extension/README.md new file mode 100644 index 000000000000..647f86b0915b --- /dev/null +++ b/core/extension/README.md @@ -0,0 +1,11 @@ +# @itwin/core-extension + +Copyright © Bentley Systems, Incorporated. All rights reserved. See LICENSE.md for license terms and full copyright notice. + +## Description + +The **@itwin/core-extension** package defines all of the types and apis that can be used by an extension. + +## Documentation + +See the [iTwin.js](https://www.itwinjs.org) documentation for more information. diff --git a/core/extension/common_types.d.ts b/core/extension/common_types.d.ts new file mode 100644 index 000000000000..9f191cba26fc --- /dev/null +++ b/core/extension/common_types.d.ts @@ -0,0 +1,290 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +// Enums (note these are all real!) +export { + BackgroundFill, + BackgroundMapType, + BatchType, + BisCodeSpec, + ChangedValueState, + ChangeOpCode, + ColorByName, + CommonLoggerCategory, + ECSqlSystemProperty, + ECSqlValueType, + ElementGeometryOpcode, + FeatureOverrideType, + FillDisplay, + FillFlags, + FontType, + GeoCoordStatus, + GeometryClass, + GeometryStreamFlags, + GeometrySummaryVerbosity, + GlobeMode, + GridOrientationType, + HSVConstants, + ImageBufferFormat, + ImageSourceFormat, + LinePixels, + MassPropertiesOperation, + MonochromeMode, + Npc, + PlanarClipMaskMode, + PlanarClipMaskPriority, + QueryRowFormat, + Rank, + RenderMode, + SectionType, + SkyBoxImageType, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + TerrainHeightOriginMode, + TextureMapUnits, + ThematicDisplayMode, + ThematicGradientColorScheme, + ThematicGradientMode, + TxnAction, + TypeOfChange, +} from "@itwin/core-common"; + +// Interfaces +export type { + AdditionalTransformProps, + AffineTransformProps, + AmbientLightProps, + AnalysisStyleDisplacementProps, + AnalysisStyleProps, + AnalysisStyleThematicProps, + AppearanceOverrideProps, + AreaFillProps, + AuxCoordSystem2dProps, + AuxCoordSystem3dProps, + AuxCoordSystemProps, + BackgroundMapProps, + BaseReaderOptions, + BRepPrimitive, + CalloutProps, + CameraProps, + Carto2DDegreesProps, + CartographicProps, + CategoryProps, + CategorySelectorProps, + ChangedElements, + ChangedEntities, + ChangesetIdWithIndex, + ChangesetIndexAndId, + ChangesetRange, + ChannelRootAspectProps, + ClipStyleProps, + CodeProps, + ContextRealityModelProps, + ContextRealityModelsContainer, + CutStyleProps, + DefinitionElementProps, + DeletedElementGeometryChange, + DeprecatedBackgroundMapProps, + DisplayStyle3dProps, + DisplayStyle3dSettingsProps, + DisplayStyleLoadProps, + DisplayStyleModelAppearanceProps, + DisplayStyleOverridesOptions, + DisplayStylePlanarClipMaskProps, + DisplayStyleProps, + DisplayStyleSettingsOptions, + DisplayStyleSettingsProps, + DisplayStyleSubCategoryProps, + DynamicGraphicsRequest2dProps, + DynamicGraphicsRequest3dProps, + DynamicGraphicsRequestProps, + EcefLocationProps, + ElementAspectProps, + ElementGeometryDataEntry, + ElementIdsAndRangesProps, + ElementLoadOptions, + ElementLoadProps, + ElementProps, + EmphasizeElementsProps, + EntityIdAndClassId, + EntityProps, + EntityQueryParams, + EnvironmentProps, + ExtantElementGeometryChange, + ExternalSourceAspectProps, + FeatureAppearanceProps, + FeatureAppearanceProvider, + FeatureAppearanceSource, + FilePropertyProps, + FlatBufferGeometryStream, + FontMapProps, + FontProps, + FresnelSettingsProps, + FunctionalElementProps, + GeocentricTransformProps, + GeodeticDatumProps, + GeodeticEllipsoidProps, + GeodeticTransformProps, + GeographicCRSProps, + GeometricElement2dProps, + GeometricElement3dProps, + GeometricElementProps, + GeometricModel2dProps, + GeometricModel3dProps, + GeometricModelProps, + GeometryAppearanceProps, + GeometryContainmentRequestProps, + GeometryContainmentResponseProps, + GeometryPartInstanceProps, + GeometryPartProps, + GeometryPrimitive, + GeometryStreamEntryProps, + GeometryStreamHeaderProps, + GeometryStreamIteratorEntry, + GeometrySummaryOptions, + GeometrySummaryRequestProps, + GraphicsRequestProps, + GridFileDefinitionProps, + GridFileTransformProps, + GroundPlaneProps, + Helmert2DWithZOffsetProps, + HemisphereLightsProps, + HorizontalCRSExtentProps, + HorizontalCRSProps, + ImageGraphicProps, + ImagePrimitive, + InformationPartitionElementProps, + JsonGeometryStream, + LightSettingsProps, + LineStyleProps, + LocalBriefcaseProps, + Localization, + MassPropertiesRequestProps, + MassPropertiesResponseProps, + MaterialProps, + ModelClipGroupProps, + ModelGeometryChanges, + ModelGeometryChangesProps, + ModelIdAndGeometryGuid, + ModelLoadProps, + ModelProps, + ModelQueryParams, + ModelSelectorProps, + NavigationBindingValue, + NavigationValue, + PartReference, + PersistentGraphicsRequestProps, + PhysicalElementProps, + PhysicalTypeProps, + Placement2dProps, + Placement3dProps, + PlanarClipMaskProps, + PlanProjectionSettingsProps, + PositionalVectorTransformProps, + ProjectionProps, + QueryLimit, + QueryOptions, + QueryQuota, + RelatedElementProps, + RelationshipProps, + RenderMaterialAssetProps, + RenderMaterialProps, + RenderTimelineLoadProps, + RenderTimelineProps, + RepositoryLinkProps, + RequestNewBriefcaseProps, + RgbColorProps, + RootSubjectProps, + RpcActivity, + SectionDrawingLocationProps, + SectionDrawingProps, + SectionDrawingViewProps, + SessionProps, + SheetProps, + SkyBoxImageProps, + SkyBoxProps, + SkyCubeProps, + SolarLightProps, + SolarShadowSettingsProps, + SourceAndTarget, + SpatialClassifierFlagsProps, + SpatialClassifierProps, + SpatialClassifiersContainer, + SpatialViewDefinitionProps, + SubCategoryProps, + SubjectProps, + TerrainProps, + TextStringPrimitive, + TextStringProps, + TextureData, + TextureLoadProps, + TextureMapProps, + TextureProps, + ThematicDisplayProps, + ThematicDisplaySensorProps, + ThematicDisplaySensorSettingsProps, + ThematicGradientSettingsProps, + ThumbnailFormatProps, + ThumbnailProps, + TileVersionInfo, + TypeDefinitionElementProps, + UrlLinkProps, + VerticalCRSProps, + ViewAttachmentLabelProps, + ViewAttachmentProps, + ViewDefinition2dProps, + ViewDefinition3dProps, + ViewDefinitionProps, + ViewDetails3dProps, + ViewDetailsProps, + ViewFlagProps, + ViewQueryParams, + ViewStateLoadProps, + ViewStateProps, + WhiteOnWhiteReversalProps, + XyzRotationProps, +} from "@itwin/core-common" + +// Types +export { + AxisAlignedBox3d, + AxisAlignedBox3dProps, + BackgroundMapProviderName, + Base64EncodedString, + BriefcaseId, + ChangesetId, + ChangesetIndex, + ChangesetIndexOrId, + CodeScopeProps, + ColorDefProps, + DanishSystem34Region, + EasingFunction, + ElementAlignedBox2d, + ElementAlignedBox3d, + ElementGeometryChange, + ElementGraphicsRequestProps, + EntityIdAndClassIdIterable, + GeodeticTransformMethod, + GeometryStreamPrimitive, + GeometryStreamProps, + GridFileDirection, + GridFileFormat, + HemisphereEnum, + ImageGraphicCornersProps, + InterpolationFunction, + LocalAlignedBox3d, + PersistentBackgroundMapProps, + Placement, + PlacementProps, + Point2dProps, + ProjectionMethod, + RemoveFunction, + RgbFactorProps, + TerrainProviderName, + TweenCallback, + UnitType, + UpdateCallback, + ViewFlagOverrides, + ViewFlagsProperties, +} from "@itwin/core-common" \ No newline at end of file diff --git a/core/extension/frontend_types.d.ts b/core/extension/frontend_types.d.ts new file mode 100644 index 000000000000..7c0f7323b185 --- /dev/null +++ b/core/extension/frontend_types.d.ts @@ -0,0 +1,295 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +// Interfaces +export type { + Animator, + BatchOptions, + BeButtonEventProps, + BeTouchEventProps, + BeWheelEventProps, + CanvasDecoration, + ChangeViewedModel2dOptions, + ComputeChordToleranceArgs, + CreateTextureArgs, + CreateTextureFromSourceArgs, + CustomGraphicBuilderOptions, + Decorator, + DepthPointOptions, + DepthRangeNpc, + ExtentLimits, + FeatureOverrideProvider, + FrontendSecurityOptions, + FuzzySearchResult, + GlobalAlignmentOptions, + GlobalLocation, + GlobalLocationArea, + GpuMemoryLimits, + GraphicArc, + GraphicArc2d, + GraphicBranchOptions, + GraphicBuilderOptions, + GraphicLineString, + GraphicLineString2d, + GraphicLoop, + GraphicPath, + GraphicPointString, + GraphicPointString2d, + GraphicPolyface, + GraphicPrimitive2d, + GraphicShape, + GraphicShape2d, + GraphicSolidPrimitive, + HitListHolder, + IModelIdArg, + MarginOptions, + OffScreenViewportOptions, + OnViewExtentsError, + OsmBuildingDisplayOptions, + ParsedKeyin, + ParseKeyinError, + ParticleCollectionBuilder, + ParticleCollectionBuilderParams, + ParticleProps, + PickableGraphicOptions, + ScreenSpaceEffectBuilder, + ScreenSpaceEffectBuilderParams, + ScreenSpaceEffectContext, + ScreenSpaceEffectSource, + SelectAddEvent, + SelectedViewportChangedArgs, + SelectRemoveEvent, + SelectReplaceEvent, + TextureCacheOwnership, + TextureImage, + TileContent, + TiledGraphicsProvider, + TileDrawArgParams, + TileParams, + TileTreeDiscloser, + TileTreeOwner, + TileTreeParams, + TileTreeSupplier, + ToolAssistanceInstruction, + ToolAssistanceInstructions, + ToolAssistanceKeyboardInfo, + ToolAssistanceSection, + ToolTipOptions, + Uniform, + UniformArrayParams, + UniformContext, + UniformParams, + ViewAnimationOptions, + ViewChangeOptions, + ViewClipEventHandler, + ViewCreator2dOptions, + ViewCreator3dOptions, + ViewportDecorator, + ViewportGraphicBuilderOptions, + ZoomToOptions, +} from "@itwin/core-frontend"; + +// Types +export type { + CanvasDecorationList, + FlashSettingsOptions, + GpuMemoryLimit, + GraphicList, + GraphicPrimitive, + MarkerFillStyle, + MarkerImage, + MarkerTextAlign, + MarkerTextBaseline, + OnFlashedIdChangedEventArgs, + ParseKeyinResult, + SelectionSetEvent, + TextureCacheKey, + TextureImageSource, + TextureOwnership, + ToolList, + ToolType, +} from "@itwin/core-frontend"; + +// Enums (note these are all real!) +export { + ACSDisplayOptions, + ACSType, + ActivityMessageEndReason, + BeButton, + BeModifierKeys, + ClipEventType, + ContextRotationId, + CoordinateLockOverrides, + CoordSource, + CoordSystem, + DepthPointSource, + EventHandled, + FlashMode, + GraphicType, + HitDetailType, + HitGeomType, + HitParentGeomType, + HitPriority, + HitSource, + InputSource, + KeyinParseError, + LocateAction, + LocateFilterStatus, + ManipulatorToolEvent, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + OutputMessageAlert, + OutputMessagePriority, + OutputMessageType, + ParseAndRunResult, + SelectionMethod, + SelectionMode, + SelectionProcessing, + SelectionSetEventType, + SnapHeat, + SnapMode, + SnapStatus, + StandardViewId, + StartOrResume, + TextureTransparency, + TileBoundingBoxes, + TileGraphicType, + TileLoadPriority, + TileLoadStatus, + TileTreeLoadStatus, + TileVisibility, + ToolAssistanceImage, + ToolAssistanceInputMethod, + UniformType, + VaryingType, + ViewStatus, + ViewUndoEvent, +} from "@itwin/core-frontend"; + +// Abstract Classes +export type { + AuxCoordSystemState, + DisplayStyleState, + GeometricModelState, + GraphicBuilder, + IModelConnection, + // InputCollector, @REAL + // InteractiveTool, @REAL + MarkerSet, + NotificationHandler, + // PrimitiveTool, @REAL + RenderClipVolume, + RenderGraphic, + RenderGraphicOwner, + RenderSystem, + Tile, + TileTree, + TileTreeReference, + ViewManip, + Viewport, + ViewPose, + ViewState, + ViewState2d, + ViewState3d, + // ViewTool @REAL +} from "@itwin/core-frontend"; + +// Classes +export type { + // AccuDrawHintBuilder, @REAL + AccuSnap, + ActivityMessageDetails, + AuxCoordSystem2dState, + AuxCoordSystem3dState, + AuxCoordSystemSpatialState, + // BeButtonEvent, @REAL + BeButtonState, + BeTouchEvent, + BeWheelEvent, + // BingElevationProvider, @REAL + // BingLocationProvider, @REAL + CategorySelectorState, + ChangeFlags, + // Cluster, @REAL + ContextRealityModelState, + DecorateContext, + Decorations, + DisclosedTileTreeSet, + DisplayStyle2dState, + DisplayStyle3dState, + DrawingModelState, + DrawingViewState, + DynamicsContext, + ElementLocateManager, + ElementPicker, + ElementState, + // EmphasizeElements, @REAL + EntityState, + EventController, + FlashSettings, + // FrustumAnimator, @REAL + GeometricModel2dState, + GeometricModel3dState, + // GlobeAnimator, @REAL + // GraphicBranch, @REAL + HiliteSet, + HitDetail, + HitList, + IconSprites, + // IModelApp, @BANNED + IntersectDetail, + // IpcApp, @BANNED + LocateOptions, + // LocateResponse, @REAL + // MarginPercent, @REAL + // Marker, @REAL + ModelSelectorState, + ModelState, + NotificationManager, + // NotifyMessageDetails, @REAL + OffScreenViewport, + OrthographicViewState, + PhysicalModelState, + RenderContext, + Scene, + SceneContext, + ScreenViewport, + SectionDrawingModelState, + SelectionSet, + SheetModelState, + SheetViewState, + SnapDetail, + SpatialLocationModelState, + SpatialModelState, + SpatialViewState, + Sprite, + SpriteLocation, + TentativePoint, + TileAdmin, + TileDrawArgs, + TileRequest, + TileRequestChannel, + TileRequestChannels, + TileRequestChannelStatistics, + Tiles, + TileUsageMarker, + // Tool, @REAL + ToolAdmin, + // ToolAssistance, @REAL + ToolSettings, + ViewCreator2d, + ViewCreator3d, + ViewingSpace, + ViewManager, + // ViewRect, @REAL +} from "@itwin/core-frontend"; + +// namespaces (minus conflicts) +export type { + // EditManipulator, @REAL + // FeatureSymbology, @REAL + PerModelCategoryVisibility, + // Pixel @REAL +} from "@itwin/core-frontend"; diff --git a/core/extension/index.d.ts b/core/extension/index.d.ts new file mode 100644 index 000000000000..0b40c68cb396 --- /dev/null +++ b/core/extension/index.d.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ + +// Export all types here. +export * from "./common_types"; +export * from "./frontend_types"; + +// Export all real values here. +export { + InteractiveTool, + PrimitiveTool, + ViewTool, + Tool, + ToolAssistance, + BeButtonEvent, + ViewRect, + Pixel, + LocateResponse, + EditManipulator, + AccuDrawHintBuilder, + EmphasizeElements, + FeatureSymbology, + GraphicBranch, + NotifyMessageDetails, + ExtensionHost, + BingElevationProvider, + BingLocationProvider, + InputCollector, + FrustumAnimator, + GlobeAnimator, + MarginPercent, + Marker, + Cluster, + getCompressedJpegFromCanvas, + getImageSourceFormatForMimeType, + getImageSourceMimeType, + imageBufferToBase64EncodedPng, + imageBufferToCanvas, + imageBufferToPngDataUrl, + imageElementFromImageSource, + imageElementFromUrl, + queryTerrainElevationOffset, + readElementGraphics, + canvasToImageBuffer, + canvasToResizedCanvasWithBars, + extractImageSourceDimensions, +} from "@itwin/core-frontend"; + +export { ColorDef } from "@itwin/core-common"; + +export function registerTool(t: typeof import("@itwin/core-frontend").Tool): Promise diff --git a/core/extension/index.js b/core/extension/index.js new file mode 100644 index 000000000000..d0929048b81b --- /dev/null +++ b/core/extension/index.js @@ -0,0 +1,171 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Bentley Systems, Incorporated. All rights reserved. + * See LICENSE.md in the project root for license terms and full copyright notice. + *--------------------------------------------------------------------------------------------*/ + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis +const globalSymbol = Symbol.for("itwin.core.frontend.globals"); +const ext = globalThis[globalSymbol].getExtensionApi(import.meta.url); + +// re-export tool +export const { + InteractiveTool, + PrimitiveTool, + ViewTool, + Tool, + + ToolAssistance, + BeButtonEvent, + ViewRect, + Pixel, + LocateResponse, + EditManipulator, + AccuDrawHintBuilder, + EmphasizeElements, + FeatureSymbology, + GraphicBranch, + NotifyMessageDetails, + + ExtensionHost, +} = ext.exports; + +// re-export frontend items +export const { + BingElevationProvider, + BingLocationProvider, + InputCollector, + FrustumAnimator, + GlobeAnimator, + MarginPercent, + Marker, + Cluster +} = ext.exports; + +// re-export functions +export const { + getCompressedJpegFromCanvas, + getImageSourceFormatForMimeType, + getImageSourceMimeType, + imageBufferToBase64EncodedPng, + imageBufferToCanvas, + imageBufferToPngDataUrl, + imageElementFromImageSource, + imageElementFromUrl, + queryTerrainElevationOffset, + readElementGraphics, + canvasToImageBuffer, + canvasToResizedCanvasWithBars, + extractImageSourceDimensions +} = ext.exports; + +// re-export enums +export const { + // core-frontend: + ACSDisplayOptions, + ACSType, + ActivityMessageEndReason, + BeButton, + BeModifierKeys, + ClipEventType, + ContextRotationId, + CoordinateLockOverrides, + CoordSource, + CoordSystem, + DepthPointSource, + EventHandled, + FlashMode, + FrontendLoggerCategory, + GraphicType, + HitDetailType, + HitGeomType, + HitParentGeomType, + HitPriority, + HitSource, + InputSource, + KeyinParseError, + LocateAction, + LocateFilterStatus, + ManipulatorToolEvent, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + OutputMessageAlert, + OutputMessagePriority, + OutputMessageType, + ParseAndRunResult, + SelectionMethod, + SelectionMode, + SelectionProcessing, + SelectionSetEventType, + SnapHeat, + SnapMode, + SnapStatus, + StandardViewId, + StartOrResume, + TextureTransparency, + TileBoundingBoxes, + TileGraphicType, + TileLoadPriority, + TileLoadStatus, + TileTreeLoadStatus, + TileVisibility, + ToolAssistanceImage, + ToolAssistanceInputMethod, + UniformType, + VaryingType, + ViewStatus, + ViewUndoEvent, + // core-common: + BackgroundFill, + BackgroundMapType, + BatchType, + BisCodeSpec, + BriefcaseIdValue, + ChangedValueState, + ChangeOpCode, + ChangesetType, + ColorByName, + CommonLoggerCategory, + ECSqlSystemProperty, + ECSqlValueType, + ElementGeometryOpcode, + FeatureOverrideType, + FillDisplay, + FillFlags, + FontType, + GeoCoordStatus, + GeometryClass, + GeometryStreamFlags, + GeometrySummaryVerbosity, + GlobeMode, + GridOrientationType, + HSVConstants, + ImageBufferFormat, + ImageSourceFormat, + LinePixels, + MassPropertiesOperation, + MonochromeMode, + Npc, + PlanarClipMaskMode, + PlanarClipMaskPriority, + QueryRowFormat, + Rank, + RenderMode, + SectionType, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + SyncMode, + TerrainHeightOriginMode, + TextureMapUnits, + ThematicDisplayMode, + ThematicGradientColorScheme, + ThematicGradientMode, + TxnAction, + TypeOfChange, +} = ext.exports; + +// re-export commmon +export const { ColorDef } = ext.exports; + +// export extension stuff +export const { registerTool } = ext.api; diff --git a/core/extension/package.json b/core/extension/package.json new file mode 100644 index 000000000000..762e6b8cebe1 --- /dev/null +++ b/core/extension/package.json @@ -0,0 +1,48 @@ +{ + "name": "@itwin/core-extension", + "version": "3.2.0-dev.21", + "description": "iTwin.js Extension API", + "typings": "index.d.ts", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/iTwin/itwinjs-core/tree/master/core/extension" + }, + "scripts": { + "compile": "", + "build": "", + "build:ci": "", + "clean": "rimraf .rush/temp/package-deps*.json", + "cover": "", + "docs": "", + "lint": "", + "test": "" + }, + "keywords": [ + "Bentley", + "BIM", + "iModel", + "iTwin", + "Extension" + ], + "author": { + "name": "Bentley Systems, Inc.", + "url": "http://www.bentley.com" + }, + "dependencies": { + "@itwin/core-frontend": "workspace:*", + "@itwin/core-common": "workspace:*" + }, + "devDependencies": { + "@itwin/build-tools": "workspace:*", + "@itwin/eslint-plugin": "workspace:*", + "eslint": "^7.11.0", + "rimraf": "^3.0.2" + }, + "eslintConfig": { + "plugins": [ + "@itwin" + ], + "extends": "plugin:@itwin/itwinjs-recommended" + } +} diff --git a/core/frontend-devtools/CHANGELOG.json b/core/frontend-devtools/CHANGELOG.json index 8c99df00925d..7e75395c081c 100644 --- a/core/frontend-devtools/CHANGELOG.json +++ b/core/frontend-devtools/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/frontend-devtools", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/frontend-devtools_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/frontend-devtools_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/frontend-devtools_v3.0.0", diff --git a/core/frontend-devtools/CHANGELOG.md b/core/frontend-devtools/CHANGELOG.md index 6dbc4b141247..ceb26ff5565f 100644 --- a/core/frontend-devtools/CHANGELOG.md +++ b/core/frontend-devtools/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/frontend-devtools -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/frontend-devtools/package.json b/core/frontend-devtools/package.json index a8bd4513ad86..48c93f1822ce 100644 --- a/core/frontend-devtools/package.json +++ b/core/frontend-devtools/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/frontend-devtools", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "Debug menu and supporting UI widgets", "main": "lib/cjs/frontend-devtools.js", "module": "lib/esm/frontend-devtools.js", "typings": "lib/cjs/frontend-devtools", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s copy:public && npm run -s build:cjs", diff --git a/core/frontend/CHANGELOG.json b/core/frontend/CHANGELOG.json index 7dbd04dce605..869e037b8984 100644 --- a/core/frontend/CHANGELOG.json +++ b/core/frontend/CHANGELOG.json @@ -1,6 +1,24 @@ { "name": "@itwin/core-frontend", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-frontend_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-frontend_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": { + "none": [ + { + "comment": "Fixed MapBox imagery failing to display." + } + ] + } + }, { "version": "3.0.0", "tag": "@itwin/core-frontend_v3.0.0", diff --git a/core/frontend/CHANGELOG.md b/core/frontend/CHANGELOG.md index f6518c119a79..587a01b5cfef 100644 --- a/core/frontend/CHANGELOG.md +++ b/core/frontend/CHANGELOG.md @@ -1,6 +1,18 @@ # Change Log - @itwin/core-frontend -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +### Updates + +- Fixed MapBox imagery failing to display. ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/frontend/package.json b/core/frontend/package.json index 186f66f59583..644a551e0871 100644 --- a/core/frontend/package.json +++ b/core/frontend/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-frontend", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js frontend components", "main": "lib/cjs/core-frontend.js", "module": "lib/esm/core-frontend.js", "typings": "lib/cjs/core-frontend", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s copy:public && npm run -s build:cjs", @@ -39,13 +38,13 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/appui-abstract": "workspace:^3.1.0-dev.33", - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33", - "@itwin/core-orbitgt": "workspace:^3.1.0-dev.33", - "@itwin/core-quantity": "workspace:^3.1.0-dev.33", - "@itwin/webgl-compatibility": "workspace:^3.1.0-dev.33" + "@itwin/appui-abstract": "workspace:^3.2.0-dev.21", + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21", + "@itwin/core-orbitgt": "workspace:^3.2.0-dev.21", + "@itwin/core-quantity": "workspace:^3.2.0-dev.21", + "@itwin/webgl-compatibility": "workspace:^3.2.0-dev.21" }, "//devDependencies": [ "NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install", diff --git a/core/frontend/src/BriefcaseConnection.ts b/core/frontend/src/BriefcaseConnection.ts index 04175ffac6d0..06b6619e8aa5 100644 --- a/core/frontend/src/BriefcaseConnection.ts +++ b/core/frontend/src/BriefcaseConnection.ts @@ -146,6 +146,57 @@ class ModelChangeMonitor { } } +/** Settings that can be used to control the behavior of [[Tool]]s that modify a [[BriefcaseConnection]]. + * For example, tools that want to create new elements can consult the briefcase's editor tool settings to + * determine into which model and category to insert the elements. + * Specialized tools are free to ignore these settings. + * @see [[BriefcaseConnection.editorToolSettings]] to query or modify the current settings for a briefcase. + * @see [CreateElementTool]($editor-frontend) for an example of a tool that uses these settings. + * @alpha + */ +export class BriefcaseEditorToolSettings { + private _category?: Id64String; + private _model?: Id64String; + + /** An event raised just after the default [[category]] is changed. */ + public readonly onCategoryChanged = new BeEvent<(previousCategory: Id64String | undefined) => void>(); + + /** An event raised just after the default [[model]] is changed. */ + public readonly onModelChanged = new BeEvent<(previousModel: Id64String | undefined) => void>(); + + /** The [Category]($backend) into which new elements should be inserted by default. + * Specialized tools are free to ignore this setting and instead use their own logic to select an appropriate category. + * @see [[onCategoryChanged]] to be notified when this property is modified. + * @see [CreateElementTool.targetCategory]($editor-frontend) for an example of a tool that uses this setting. + */ + public get category(): Id64String | undefined { + return this._category; + } + public set category(category: Id64String | undefined) { + const previousCategory = this.category; + if (category !== this.category) { + this._category = category; + this.onCategoryChanged.raiseEvent(previousCategory); + } + } + + /** The [Model]($backend) into which new elements should be inserted by default. + * Specialized tools are free to ignore this setting and instead use their own logic to select an appropriate model. + * @see [[onModelChanged]] to be notified when this property is modified. + * @see [CreateElementTool.targetModel]($editor-frontend) for an example of a tool that uses this setting. + */ + public get model(): Id64String | undefined { + return this._model; + } + public set model(model: Id64String | undefined) { + const previousModel = this.model; + if (model !== this.model) { + this._model = model; + this.onModelChanged.raiseEvent(previousModel); + } + } +} + /** A connection to an editable briefcase on the backend. This class uses [Ipc]($docs/learning/IpcInterface.md) to communicate * to the backend and may only be used by [[IpcApp]]s. * @public @@ -153,6 +204,10 @@ class ModelChangeMonitor { export class BriefcaseConnection extends IModelConnection { protected _isClosed?: boolean; private readonly _modelsMonitor: ModelChangeMonitor; + /** Default settings that can be used to control the behavior of [[Tool]]s that modify this briefcase. + * @alpha + */ + public readonly editorToolSettings = new BriefcaseEditorToolSettings(); /** Manages local changes to the briefcase via [Txns]($docs/learning/InteractiveEditing.md). */ public readonly txns: BriefcaseTxns; diff --git a/core/frontend/src/CategorySelectorState.ts b/core/frontend/src/CategorySelectorState.ts index 311572809215..224712f250cd 100644 --- a/core/frontend/src/CategorySelectorState.ts +++ b/core/frontend/src/CategorySelectorState.ts @@ -71,7 +71,7 @@ export class CategorySelectorState extends ElementState { public get name(): string { return this.code.value; } /** Determine whether this CategorySelector includes the specified categoryId string */ - public has(id: Id64String): boolean { return this.categories.has(id.toString()); } + public has(id: Id64String): boolean { return this.categories.has(id); } /** Determine whether this CategorySelector includes the specified category */ public isCategoryViewed(categoryId: Id64String): boolean { return this.has(categoryId); } diff --git a/core/frontend/src/DisplayStyleState.ts b/core/frontend/src/DisplayStyleState.ts index 33651e13a0b0..8a16094c02e0 100644 --- a/core/frontend/src/DisplayStyleState.ts +++ b/core/frontend/src/DisplayStyleState.ts @@ -218,12 +218,13 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS * @public */ public changeBackgroundMapProvider(props: BackgroundMapProviderProps): void { - const provider = BackgroundMapProvider.fromJSON(props); const base = this.settings.mapImagery.backgroundBase; - if (base instanceof ColorDef) - this.settings.mapImagery.backgroundBase = BaseMapLayerSettings.fromProvider(provider); - else + if (base instanceof ColorDef) { + this.settings.mapImagery.backgroundBase = BaseMapLayerSettings.fromProvider(BackgroundMapProvider.fromJSON(props)); + } else { + const provider = base.provider ? base.provider.clone(props) : BackgroundMapProvider.fromJSON(props); this.settings.mapImagery.backgroundBase = base.cloneWithProvider(provider); + } this._synchBackgroundMapImagery(); } diff --git a/core/frontend/src/HitDetail.ts b/core/frontend/src/HitDetail.ts index 82dd24d8a862..a0c5d7a854ad 100644 --- a/core/frontend/src/HitDetail.ts +++ b/core/frontend/src/HitDetail.ts @@ -261,7 +261,7 @@ export class SnapDetail extends HitDetail { val.parentGeomType = this.parentGeomType; val.adjustedPoint.setFrom(this.adjustedPoint); if (undefined !== this.primitive) - val.primitive = this.primitive.clone() as CurvePrimitive; + val.primitive = this.primitive.clone(); if (undefined !== this.normal) val.normal = this.normal.clone(); return val; diff --git a/core/frontend/src/IModelApp.ts b/core/frontend/src/IModelApp.ts index 4166780957cb..c8f1c7349d90 100644 --- a/core/frontend/src/IModelApp.ts +++ b/core/frontend/src/IModelApp.ts @@ -6,7 +6,10 @@ * @module IModelApp */ -const copyrightNotice = 'Copyright © 2017-2022 Bentley Systems, Inc.'; +/** @public */ +// eslint-disable-next-line @typescript-eslint/no-var-requires +export const ITWINJS_CORE_VERSION = require("../../package.json").version as string; // require resolves from the lib/{cjs,esm} dir +const COPYRIGHT_NOTICE = 'Copyright © 2017-2022 Bentley Systems, Inc.'; import { TelemetryManager } from "@itwin/core-telemetry"; import { UiAdmin } from "@itwin/appui-abstract"; @@ -20,6 +23,7 @@ import { AccuDraw } from "./AccuDraw"; import { AccuSnap } from "./AccuSnap"; import * as auxCoordState from "./AuxCoordSys"; import * as categorySelectorState from "./CategorySelectorState"; +import { ExtensionAdmin } from "./extension/ExtensionAdmin"; import * as displayStyleState from "./DisplayStyleState"; import * as drawingViewState from "./DrawingViewState"; import { ElementLocateManager } from "./ElementLocateManager"; @@ -201,6 +205,11 @@ export class IModelApp { /** Event raised just before the frontend IModelApp is to be shut down */ public static readonly onBeforeShutdown = new BeEvent<() => void>(); + /** Event raised after IModelApp is finished starting up. + * @internal + */ + public static readonly onAfterStartup = new BeEvent<() => void>(); + /** Provides authorization information for various frontend APIs */ public static authorizationClient?: AuthorizationClient; /** The [[ToolRegistry]] for this session. */ @@ -230,7 +239,6 @@ export class IModelApp { public static get accuDraw(): AccuDraw { return this._accuDraw; } /** The [[AccuSnap]] for this session. */ public static get accuSnap(): AccuSnap { return this._accuSnap; } - /** @internal */ public static get locateManager(): ElementLocateManager { return this._locateManager; } /** @internal */ public static get tentativePoint(): TentativePoint { return this._tentativePoint; } @@ -271,6 +279,9 @@ export class IModelApp { */ public static readonly telemetry: TelemetryManager = new TelemetryManager(); + /** @alpha */ + public static readonly extensionAdmin = new ExtensionAdmin(); + /** Map of classFullName to EntityState class */ private static _entityClasses = new Map(); @@ -397,7 +408,8 @@ export class IModelApp { this.uiAdmin, ].forEach((sys) => sys.onInitialized()); - return this.quantityFormatter.onInitialized(); + await this.quantityFormatter.onInitialized(); + this.onAfterStartup.raiseEvent(); } /** Must be called before the application exits to release any held resources. */ @@ -422,6 +434,7 @@ export class IModelApp { this._entityClasses.clear(); this.authorizationClient = undefined; this._initialized = false; + this.onAfterStartup.clear(); } /** Controls how frequently the application polls for changes that may require a new animation frame to be requested. @@ -678,7 +691,7 @@ export class IModelApp { return this.makeLogoCard({ iconSrc: `${this.publicPath}images/about-imodeljs.svg`, heading: `${this.localization.getLocalizedString("iModelJs:Notices.PoweredBy")} iTwin.js`, - notice: `${require("../../package.json").version}
${copyrightNotice}`, // eslint-disable-line @typescript-eslint/no-var-requires + notice: `${ITWINJS_CORE_VERSION}
${COPYRIGHT_NOTICE}`, }); } diff --git a/core/frontend/src/IModelConnection.ts b/core/frontend/src/IModelConnection.ts index 9be09e6b01f6..8ce573e42314 100644 --- a/core/frontend/src/IModelConnection.ts +++ b/core/frontend/src/IModelConnection.ts @@ -12,7 +12,7 @@ import { import { AxisAlignedBox3d, Cartographic, CodeProps, CodeSpec, DbQueryRequest, DbResult, EcefLocation, EcefLocationProps, ECSqlReader, ElementLoadOptions, ElementProps, EntityQueryParams, FontMap, GeoCoordStatus, GeometryContainmentRequestProps, GeometryContainmentResponseProps, - GeometrySummaryRequestProps, IModel, IModelConnectionProps, IModelError, IModelReadRpcInterface, IModelStatus, + GeometrySummaryRequestProps, ImageSourceFormat, IModel, IModelConnectionProps, IModelError, IModelReadRpcInterface, IModelStatus, mapToGeoServiceStatus, MassPropertiesRequestProps, MassPropertiesResponseProps, ModelProps, ModelQueryParams, NoContentError, Placement, Placement2d, Placement3d, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat, RpcManager, SnapRequestProps, SnapResponseProps, SnapshotIModelRpcInterface, TextureData, TextureLoadProps, ThumbnailProps, ViewDefinitionProps, ViewQueryParams, ViewStateLoadProps, @@ -1045,11 +1045,21 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare return viewState; } - /** @deprecated - * @throws This function is deprecated and will always throw a "no content" error. + /** Get a thumbnail for a view. + * @param viewId The id of the view of the thumbnail. + * @returns A Promise of the ThumbnailProps. + * @throws "No content" error if invalid thumbnail. + * @deprecated */ public async getThumbnail(_viewId: Id64String): Promise { - throw new NoContentError(); + // eslint-disable-next-line deprecation/deprecation + const val = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getViewThumbnail(this._iModel.getRpcProps(), _viewId.toString()); + const intValues = new Uint32Array(val.buffer, 0, 4); + + if (intValues[1] !== ImageSourceFormat.Jpeg && intValues[1] !== ImageSourceFormat.Png) + throw new NoContentError(); + + return { format: intValues[1] === ImageSourceFormat.Jpeg ? "jpeg" : "png", width: intValues[2], height: intValues[3], image: new Uint8Array(val.buffer, 16, intValues[0]) }; } } } diff --git a/core/frontend/src/ImageUtil.ts b/core/frontend/src/ImageUtil.ts index a5bb56a24e7e..a23c6b5c3661 100644 --- a/core/frontend/src/ImageUtil.ts +++ b/core/frontend/src/ImageUtil.ts @@ -196,15 +196,18 @@ export async function imageElementFromImageSource(source: ImageSource): Promise< /** Create an html Image element from a URL. * @param url The URL pointing to the image data. + * @param skipCrossOriginCheck Set this to true to allow an image from a different origin than the web app to load. Default is false. * @returns A Promise resolving to an HTMLImageElement when the image data has been loaded from the URL. * @see tryImageElementFromUrl. * @public */ -export async function imageElementFromUrl(url: string): Promise { +export async function imageElementFromUrl(url: string, skipCrossOriginCheck = false): Promise { // We must set crossorigin property so that images loaded from same origin can be used with texImage2d. // We must do that outside of the promise constructor or it won't work, for reasons. const image = new Image(); - image.crossOrigin = "anonymous"; + if (!skipCrossOriginCheck) { + image.crossOrigin = "anonymous"; + } return new Promise((resolve: (image: HTMLImageElement) => void, reject) => { image.onload = () => resolve(image); @@ -216,13 +219,14 @@ export async function imageElementFromUrl(url: string): Promise { +export async function tryImageElementFromUrl(url: string, skipCrossOriginCheck = false): Promise { try { - return await imageElementFromUrl(url); + return await imageElementFromUrl(url, skipCrossOriginCheck); } catch { return undefined; } diff --git a/core/frontend/src/Viewport.ts b/core/frontend/src/Viewport.ts index e1189425ed1e..d48f9e6cb9a1 100644 --- a/core/frontend/src/Viewport.ts +++ b/core/frontend/src/Viewport.ts @@ -1,3405 +1,3433 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Bentley Systems, Incorporated. All rights reserved. -* See LICENSE.md in the project root for license terms and full copyright notice. -*--------------------------------------------------------------------------------------------*/ -/** @packageDocumentation - * @module Views - */ - -import { - asInstanceOf, assert, BeDuration, BeEvent, BeTimePoint, Constructor, dispose, Id64, Id64Arg, Id64Set, Id64String, IDisposable, isInstanceOf, - StopWatch, -} from "@itwin/core-bentley"; -import { - Angle, AngleSweep, Arc3d, Geometry, LowAndHighXY, LowAndHighXYZ, Map4d, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point4d, Range1d, - Range3d, Ray3d, Transform, Vector3d, XAndY, XYAndZ, XYZ, -} from "@itwin/core-geometry"; -import { - AnalysisStyle, BackgroundMapProps, BackgroundMapProviderProps, BackgroundMapSettings, Camera, ClipStyle, ColorDef, DisplayStyleSettingsProps, Easing, - ElementProps, FeatureAppearance, Frustum, GlobeMode, GridOrientationType, Hilite, ImageBuffer, Interpolation, - isPlacement2dProps, LightSettings, MapLayerSettings, Npc, NpcCenter, Placement, Placement2d, Placement3d, PlacementProps, - SolarShadowSettings, SubCategoryAppearance, SubCategoryOverride, ViewFlags, -} from "@itwin/core-common"; -import { AuxCoordSystemState } from "./AuxCoordSys"; -import { BackgroundMapGeometry } from "./BackgroundMapGeometry"; -import { ChangeFlag, ChangeFlags, MutableChangeFlags } from "./ChangeFlags"; -import { CoordSystem } from "./CoordSystem"; -import { DecorationsCache } from "./DecorationsCache"; -import { DisplayStyleState } from "./DisplayStyleState"; -import { ElementPicker, LocateOptions } from "./ElementLocateManager"; -import { FeatureOverrideProvider } from "./FeatureOverrideProvider"; -import { FrustumAnimator } from "./FrustumAnimator"; -import { GlobeAnimator } from "./GlobeAnimator"; -import { HitDetail, SnapDetail } from "./HitDetail"; -import { IModelApp } from "./IModelApp"; -import { IModelConnection } from "./IModelConnection"; -import { linePlaneIntersect } from "./LinePlaneIntersect"; -import { ToolTipOptions } from "./NotificationManager"; -import { PerModelCategoryVisibility } from "./PerModelCategoryVisibility"; -import { Decorations } from "./render/Decorations"; -import { FeatureSymbology } from "./render/FeatureSymbology"; -import { FrameStats, FrameStatsCollector } from "./render/FrameStats"; -import { GraphicType } from "./render/GraphicBuilder"; -import { Pixel } from "./render/Pixel"; -import { GraphicList } from "./render/RenderGraphic"; -import { RenderMemory } from "./render/RenderMemory"; -import { createRenderPlanFromViewport } from "./render/RenderPlan"; -import { RenderTarget } from "./render/RenderTarget"; -import { StandardView, StandardViewId } from "./StandardView"; -import { SubCategoriesCache } from "./SubCategoriesCache"; -import { - DisclosedTileTreeSet, MapLayerImageryProvider, MapTiledGraphicsProvider, MapTileTreeReference, TileBoundingBoxes, TiledGraphicsProvider, TileTreeReference, TileUser, -} from "./tile/internal"; -import { EventController } from "./tools/EventController"; -import { ToolSettings } from "./tools/ToolSettings"; -import { Animator, MarginOptions, OnViewExtentsError, ViewAnimationOptions, ViewChangeOptions } from "./ViewAnimation"; -import { DecorateContext, SceneContext } from "./ViewContext"; -import { GlobalLocation } from "./ViewGlobalLocation"; -import { ViewingSpace } from "./ViewingSpace"; -import { ViewPose } from "./ViewPose"; -import { ViewRect } from "./ViewRect"; -import { ModelDisplayTransformProvider, ViewState } from "./ViewState"; -import { ViewStatus } from "./ViewStatus"; -import { queryVisibleFeatures, QueryVisibleFeaturesCallback, QueryVisibleFeaturesOptions } from "./render/VisibleFeature"; -import { FlashSettings } from "./FlashSettings"; - -// cSpell:Ignore rect's ovrs subcat subcats unmounting UI's - -/** Interface for drawing [[Decorations]] into, or on top of, a [[ScreenViewport]]. - * @public - */ -export interface ViewportDecorator { - /** Override to enable cached decorations for this decorator. - * By default, a decorator is asked to recreate its decorations from scratch via its [[decorate]] method whenever the viewport's decorations are invalidated. - * Decorations become invalidated for a variety of reasons, including when the scene changes and when the mouse moves. - * Most decorators care only about when the scene changes, and may create decorations that are too expensive to recreate on every mouse motion. - * If `useCachedDecorations` is true, then the viewport will cache the most-recently-created decorations for this decorator, and only invoke its [[decorate]] method if it has no cached decorations for it. - * The cached decorations are discarded: - * - Whenever the scene changes; and - * - When the decorator explicitly requests it via [[Viewport.invalidateCachedDecorations]] or [[ViewManager.invalidateCachedDecorationsAllViews]]. - * The decorator should invoke the latter when the criteria governing its decorations change. - */ - readonly useCachedDecorations?: true; - - /** Implement this method to add [[Decorations]] into the supplied DecorateContext. - * @see [[useCachedDecorations]] to avoid unnecessarily recreating decorations. - */ - decorate(context: DecorateContext): void; -} - -/** Source of depth point returned by [[Viewport.pickDepthPoint]]. - * @public - */ -export enum DepthPointSource { - /** Depth point from geometry within specified radius of pick point */ - Geometry, // eslint-disable-line @typescript-eslint/no-shadow - /** Depth point from reality model within specified radius of pick point */ - Model, - /** Depth point from ray projection to background map plane */ - BackgroundMap, - /** Depth point from ray projection to ground plane */ - GroundPlane, - /** Depth point from ray projection to grid plane */ - Grid, - /** Depth point from ray projection to acs plane */ - ACS, - /** Depth point from plane passing through view target point */ - TargetPoint, - /** Depth point from map/terrain within specified radius of pick point */ - Map, -} - -/** Options to control behavior of [[Viewport.pickDepthPoint]]. - * @public - */ -export interface DepthPointOptions { - /** If true, geometry with the "non-locatable" flag set will not be selected. */ - excludeNonLocatable?: boolean; - /** If true, geometry from pickable decorations will not be selected. */ - excludeDecorations?: boolean; - /** If true, geometry from an IModelConnection other than the one associated with the Viewport will not be selected. */ - excludeExternalIModels?: boolean; -} - -/** The minimum and maximum values for the z-depth of a rectangle of screen space. - * Values are in [[CoordSystem.Npc]] so they will be between 0 and 1.0. - * @public - */ -export interface DepthRangeNpc { - /** The value closest to the back. */ - minimum: number; - /** The value closest to the front. */ - maximum: number; -} - -/** Options to allow changing the view rotation with zoomTo methods. - * @public - */ -export interface ZoomToOptions { - /** Set view rotation from standard view identifier. */ - standardViewId?: StandardViewId; - /** Set view rotation relative to placement of first element or props entry. */ - placementRelativeId?: StandardViewId; - /** Set view rotation from Matrix3d. */ - viewRotation?: Matrix3d; -} - -/** Options for changing the viewed Model of a 2d view via [[Viewport.changeViewedModel2d]] - * @public - */ -export interface ChangeViewedModel2dOptions { - /** If true, perform a "fit view" operation after changing to the new 2d model. */ - doFit?: boolean; -} - -/** Describes an undo or redo event for a [[Viewport]]. - * @see [[Viewport.onViewUndoRedo]]. - * @public - */ -export enum ViewUndoEvent { Undo = 0, Redo = 1 } - -/** @internal */ -export const ELEMENT_MARKED_FOR_REMOVAL = Symbol.for("@bentley/imodeljs/Viewport/__element_marked_for_removal__"); - -declare global { - interface Element { - [ELEMENT_MARKED_FOR_REMOVAL]?: boolean; - } -} - -/** Payload for the [[Viewport.onFlashedIdChanged]] event indicating Ids of the currently- and/or previously-flashed objects. - * @public - */ -export type OnFlashedIdChangedEventArgs = { - readonly current: Id64String; - readonly previous: Id64String; -} | { - readonly current: Id64String; - readonly previous: undefined; -} | { - readonly previous: Id64String; - readonly current: undefined; -}; - -/** Arguments to [[Viewport.getPixelDataWorldPoint]]. - * @public - */ -export interface GetPixelDataWorldPointArgs { - /** The buffer containing the pixel data. @see [[Viewport.readPixels]]. */ - pixels: Pixel.Buffer; - /** The x coordinate of the pixel of interest, in view coordinates. */ - x: number; - /** The y coordinate of the pixel of interest, in view coordinates. */ - y: number; - /** If true, then the world point of a pixel associated with a model will preserve any transforms applied to the model at display time, - * such as those supplied by a [[ModelDisplayTransformProvider]] or [PlanProjectionSettings.elevation]($common). - * Otherwise, the world point will be multiplied by the inverse of any such transforms to correlate it with the model's true coordinate space. - */ - preserveModelDisplayTransforms?: boolean; - /** If supplied, this point will be modified to store the returned point, instead of allocating a new point. */ - out?: Point3d; -} - -/** Arguments supplied to [[Viewport.readImageBuffer]]. - * @public - */ -export interface ReadImageBufferArgs { - /** The region of the viewport's [[ViewRect]] to capture. It must be fully contained within [[Viewport.viewRect]]. - * If unspecified, the entirety of the viewport's view rect is captured. - */ - rect?: ViewRect; - /** Optional dimensions to which to resize the captured image. If the aspect ratio of these dimensions does not match that of the captured image, - * horizontal or vertical bars will be added to the resized image using the viewport's background color. - * If unspecified, the image will not be resized. - */ - size?: XAndY; - /** The image captured by WebGL appears "upside-down" and must be flipped to appear right-side-up; if true, this flipping will not be performed. - * This provides a performance optimization for uncommon cases in which an upside-down image is actually preferred. - */ - upsideDown?: boolean; -} - -/** A Viewport renders the contents of one or more [GeometricModel]($backend)s onto an `HTMLCanvasElement`. - * - * It holds a [[ViewState]] object that defines its viewing parameters; the ViewState in turn defines the [[DisplayStyleState]], - * [[CategorySelectorState]], and - for [[SpatialViewState]]s - the [[ModelSelectorState]]. While a ViewState is being displayed by a Viewport, - * it is considered to be "attached" to that viewport; it remains attached until the Viewport is disposed of or becomes attached to a different ViewState. - * While the ViewState is attached to a Viewport, any changes made to the ViewState or its display style or category/model selectors will be automatically - * reflected in the Viewport. A ViewState can be attached to no more than one Viewport at a time. - * - * As changes to ViewState are made, Viewports also hold a stack of *previous copies* of it, to allow - * for undo/redo (i.e. *View Previous* and *View Next*) of viewing tools. - * - * Changes to a Viewport's state can be monitored by attaching an event listener to a variety of specific events. Most such events are - * triggered only once per frame, just before the Viewport's contents are rendered. For example, if the following sequence of events occurs: - * - * * First frame is rendered - * * ViewFlags are modified - * * ViewFlags are modified again - * * Second frame is rendered - * - * The [[Viewport.onDisplayStyleChanged]] event will be invoked exactly once, when the second frame is rendered. - * - * @see [[ViewManager]] - * @public - */ -export abstract class Viewport implements IDisposable, TileUser { - /** Event called whenever this viewport is synchronized with its [[ViewState]]. - * @note This event is invoked *very* frequently. To avoid negatively impacting performance, consider using one of the more specific Viewport events; - * otherwise, avoid performing excessive computations in response to this event. - * @see [[onViewportChanged]] for receiving events at more regular intervals with more specific information about what changed. - * @see [[onChangeView]] for an event raised specifically when a different [[ViewState]] becomes associated with the viewport. - */ - public readonly onViewChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called after reversing the most recent change to the Viewport from the undo stack or reapplying the - * most recently undone change to the Viewport from the redo stack. - */ - public readonly onViewUndoRedo = new BeEvent<(vp: Viewport, event: ViewUndoEvent) => void>(); - /** Event called on the next frame after this viewport's set of always-drawn elements changes. */ - public readonly onAlwaysDrawnChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's set of never-drawn elements changes. */ - public readonly onNeverDrawnChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's [[DisplayStyleState]] or its members change. - * Aspects of the display style include [ViewFlags]($common), [SubCategoryOverride]($common)s, and [[Environment]] settings. - */ - public readonly onDisplayStyleChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's set of displayed categories changes. */ - public readonly onViewedCategoriesChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's set of [[PerModelCategoryVisibility.Overrides]] changes. */ - public readonly onViewedCategoriesPerModelChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's set of displayed models changes. */ - public readonly onViewedModelsChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's [[FeatureOverrideProvider]] changes, - * or the internal state of the provider changes such that the overrides needed to be recomputed. - */ - public readonly onFeatureOverrideProviderChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after this viewport's [[FeatureSymbology.Overrides]] change. */ - public readonly onFeatureOverridesChanged = new BeEvent<(vp: Viewport) => void>(); - /** Event called on the next frame after any of the viewport's [[ChangeFlags]] changes. */ - public readonly onViewportChanged = new BeEvent<(vp: Viewport, changed: ChangeFlags) => void>(); - /** Event invoked immediately when [[changeView]] is called to replace the current [[ViewState]] with a different one. */ - public readonly onChangeView = new BeEvent<(vp: Viewport, previousViewState: ViewState) => void>(); - /** Event invoked immediately when the viewport is disposed. - * @see [[Viewport.dispose]]. - */ - public readonly onDisposed = new BeEvent<(vp: Viewport) => void>(); - /** Event invoked after [[renderFrame]] detects that the dimensions of the viewport's [[ViewRect]] have changed. - */ - public readonly onResized = new BeEvent<(vp: Viewport) => void>(); - /** Event dispatched immediately after [[flashedId]] changes, supplying the Ids of the previously and/or currently-flashed objects. - * @note Attempting to assign to [[flashedId]] from within the event callback will produce an exception. - */ - public readonly onFlashedIdChanged = new BeEvent<(vp: Viewport, args: OnFlashedIdChangedEventArgs) => void>(); - - /** This is initialized by a call to [[changeView]] sometime shortly after the constructor is invoked. - * During that time it can be undefined. DO NOT assign directly to this member - use `setView()`. - */ - private _view!: ViewState; - /** A function executed by `setView()` when `this._view` changes. */ - private readonly _detachFromView: VoidFunction[] = []; - private readonly _detachFromDisplayStyle: VoidFunction[] = []; - - private readonly _viewportId: number; - private _doContinuousRendering = false; - /** @internal */ - protected _inViewChangedEvent = false; - /** @internal */ - protected _decorationsValid = false; - /** @internal */ - protected _sceneValid = false; - /** @internal */ - public get sceneValid() { return this._sceneValid; } - /** @internal */ - protected _renderPlanValid = false; - /** @internal */ - public get renderPlanValid() { return this._renderPlanValid; } - /** @internal */ - public setRenderPlanValid() { this._renderPlanValid = true; } - /** @internal */ - protected _controllerValid = false; - /** @internal */ - public get controllerValid() { return this._controllerValid; } - private _redrawPending = false; - private _analysisFractionValid = false; - /** @internal */ - public get analysisFractionValid() { return this._analysisFractionValid; } - private _timePointValid = false; - /** @internal */ - public get timePointValid() { return this._timePointValid; } - - /** Strictly for tests. @internal */ - public setAllValid(): void { - this._sceneValid = this._decorationsValid = this._renderPlanValid = this._controllerValid = this._redrawPending - = this._analysisFractionValid = this._timePointValid = true; - } - - /** Mark the current set of decorations invalid, so that they will be recreated on the next render frame. - * This can be useful, for example, if an external event causes one or more current decorations to become invalid and you wish to force - * them to be recreated to show the changes. - * @note On the next frame, the `decorate` method of all [[ViewManager.decorators]] will be called. There is no way (or need) to - * invalidate individual decorations. - */ - public invalidateDecorations(): void { - this._decorationsValid = false; - IModelApp.requestNextAnimation(); - } - - /** Mark the viewport's scene as invalid, so that the next call to [[renderFrame]] will recreate it. - * This method is not typically invoked directly - the scene is automatically invalidated in response to events such as moving the viewing frustum, - * changing the set of viewed models, new tiles being loaded, etc. - */ - public invalidateScene(): void { - this._sceneValid = false; - this._timePointValid = false; - this.invalidateDecorations(); - } - - /** @internal */ - public invalidateRenderPlan(): void { - this._renderPlanValid = false; - this.invalidateScene(); - } - - /** @internal */ - public invalidateController(): void { - this._controllerValid = this._analysisFractionValid = false; - this.invalidateRenderPlan(); - } - - /** @internal */ - public setValidScene() { - this._sceneValid = true; - } - - /** Request that the Viewport redraw its contents on the next frame. This is useful when some state outside of the Viewport's control but affecting its display has changed. - * For example, if the parameters affecting a screen-space effect applied to this Viewport are modified, the Viewport's contents should be redrawn to reflect the change. - * @note This does not necessarily cause the viewport to recreate its scene, decorations, or anything else - it only guarantees that the contents will be repainted. - */ - public requestRedraw(): void { - this._redrawPending = true; - IModelApp.requestNextAnimation(); - } - - private _animator?: Animator; - /** @internal */ - protected _changeFlags = new MutableChangeFlags(); - private _selectionSetDirty = true; - private readonly _perModelCategoryVisibility: PerModelCategoryVisibility.Overrides; - private _tileSizeModifier?: number; - - /** @internal */ - public readonly subcategories = new SubCategoriesCache.Queue(); - - /** Time the current flash started. */ - private _flashUpdateTime?: BeTimePoint; - /** Current flash intensity from [0..this.flashSettings.maxIntensity] */ - private _flashIntensity = 0; - /** Id of the currently flashed element. */ - private _flashedElem?: string; - /** Id of last flashed element. */ - private _lastFlashedElem?: string; - /** The Id of the most recently flashed element, if any. */ - public get lastFlashedElementId(): Id64String | undefined { - return this._lastFlashedElem; - } - - private _wantViewAttachments = true; - /** For debug purposes, controls whether or not view attachments are displayed in sheet views. - * @internal - */ - public get wantViewAttachments() { return this._wantViewAttachments; } - public set wantViewAttachments(want: boolean) { - if (want !== this._wantViewAttachments) { - this._wantViewAttachments = want; - this.invalidateScene(); - } - } - - private _wantViewAttachmentBoundaries = false; - /** For debug purposes, controls whether or not the boundary of each view attachment is displayed in a sheet view. - * @internal - */ - public get wantViewAttachmentBoundaries() { return this._wantViewAttachmentBoundaries; } - public set wantViewAttachmentBoundaries(want: boolean) { - if (want !== this._wantViewAttachmentBoundaries) { - this._wantViewAttachmentBoundaries = want; - this.invalidateScene(); - } - } - - private _wantViewAttachmentClipShapes = false; - /** For debug purposes, controls whether or not graphics representing the clipping shapes of each view attachment are displayed in a sheet view. - * @internal - */ - public get wantViewAttachmentClipShapes() { return this._wantViewAttachmentClipShapes; } - public set wantViewAttachmentClipShapes(want: boolean) { - if (want !== this._wantViewAttachmentClipShapes) { - this._wantViewAttachmentClipShapes = want; - this.invalidateScene(); - } - } - - /** Don't allow entries in the view undo buffer unless they're separated by more than this amount of time. */ - public static undoDelay = BeDuration.fromSeconds(.5); - - private _debugBoundingBoxes: TileBoundingBoxes = TileBoundingBoxes.None; - private _freezeScene = false; - private _viewingSpace!: ViewingSpace; - private _target?: RenderTarget; - private _fadeOutActive = false; - private _neverDrawn?: Id64Set; - private _alwaysDrawn?: Id64Set; - private _alwaysDrawnExclusive: boolean = false; - private readonly _featureOverrideProviders: FeatureOverrideProvider[] = []; - private readonly _tiledGraphicsProviders = new Set(); - private _mapTiledGraphicsProvider?: MapTiledGraphicsProvider; - private _hilite = new Hilite.Settings(); - private _emphasis = new Hilite.Settings(ColorDef.black, 0, 0, Hilite.Silhouette.Thick); - private _flash = new FlashSettings(); - - /** @see [DisplayStyle3dSettings.lights]($common) */ - public get lightSettings(): LightSettings | undefined { - return this.displayStyle.is3d() ? this.displayStyle.settings.lights : undefined; - } - public setLightSettings(settings: LightSettings) { - if (this.displayStyle.is3d()) - this.displayStyle.settings.lights = settings; - } - - /** @see [DisplayStyle3dSettings.solarShadows]($common) */ - public get solarShadowSettings(): SolarShadowSettings | undefined { - return this.view.displayStyle.is3d() ? this.view.displayStyle.settings.solarShadows : undefined; - } - public setSolarShadowSettings(settings: SolarShadowSettings) { - if (this.view.displayStyle.is3d()) - this.view.displayStyle.solarShadows = settings; - } - - /** @public */ - public get viewingSpace(): ViewingSpace { return this._viewingSpace; } - - /** This viewport's rotation matrix. */ - public get rotation(): Matrix3d { return this._viewingSpace.rotation; } - /** The vector between the opposite corners of this viewport's extents. */ - public get viewDelta(): Vector3d { return this._viewingSpace.viewDelta; } - /** Provides conversions between world and view coordinates. */ - public get worldToViewMap(): Map4d { return this._viewingSpace.worldToViewMap; } - /** Provides conversions between world and Npc (non-dimensional perspective) coordinates. */ - public get worldToNpcMap(): Map4d { return this._viewingSpace.worldToNpcMap; } - /** @internal */ - public get frustFraction(): number { return this._viewingSpace.frustFraction; } - - /** @see [DisplayStyleSettings.analysisFraction]($common). */ - public get analysisFraction(): number { - return this.displayStyle.settings.analysisFraction; - } - public set analysisFraction(fraction: number) { - this.displayStyle.settings.analysisFraction = fraction; - } - - /** @see [DisplayStyleSettings.timePoint]($common) */ - public get timePoint(): number | undefined { - return this.displayStyle.settings.timePoint; - } - public set timePoint(time: number | undefined) { - this.displayStyle.settings.timePoint = time; - } - - /** @internal */ - protected readonly _viewRange: ViewRect = new ViewRect(); - - /** Get the rectangle of this Viewport in [[CoordSystem.View]] coordinates. */ - public abstract get viewRect(): ViewRect; - /** @internal */ - public get isAspectRatioLocked(): boolean { return false; } - - /** @internal */ - public get target(): RenderTarget { - assert(undefined !== this._target, "Accessing RenderTarget of a disposed Viewport"); - return this._target; - } - - /** Returns true if this Viewport's [[dispose]] method has been invoked. It is an error to attempt to interact with a disposed Viewport. - * Typically a [[ScreenViewport]] becomes disposed as a result of a call to [[ViewManager.dropViewport]], often indirectly through the unmounting of a nine-zone UI's [[ViewportComponent]] when, e.g., switching front-stages. - * @public - */ - public get isDisposed(): boolean { - return undefined === this._target; - } - - /** The settings that control how elements are hilited in this Viewport. */ - public get hilite(): Hilite.Settings { return this._hilite; } - public set hilite(hilite: Hilite.Settings) { - this._hilite = hilite; - this.invalidateRenderPlan(); - } - - /** The settings that control how emphasized elements are displayed in this Viewport. The default settings apply a thick black silhouette to the emphasized elements. - * @see [FeatureAppearance.emphasized]($common). - */ - public get emphasisSettings(): Hilite.Settings { return this._emphasis; } - public set emphasisSettings(settings: Hilite.Settings) { - this._emphasis = settings; - this.invalidateRenderPlan(); - } - - /** The settings that control how elements are flashed in this viewport. */ - public get flashSettings(): FlashSettings { - return this._flash; - } - public set flashSettings(settings: FlashSettings) { - this._flash = settings; - this.invalidateRenderPlan(); - } - - /** Determine whether the Grid display is currently enabled in this Viewport. - * @return true if the grid display is on. - */ - public get isGridOn(): boolean { return this.viewFlags.grid; } - - /** Flags controlling aspects of how the contents of this viewport are rendered. - * @see [DisplayStyleSettings.viewFlags]($common). - */ - public get viewFlags(): ViewFlags { return this.view.viewFlags; } - public set viewFlags(viewFlags: ViewFlags) { - this.view.displayStyle.viewFlags = viewFlags; - } - - /** @see [[ViewState.displayStyle]] */ - public get displayStyle(): DisplayStyleState { return this.view.displayStyle; } - public set displayStyle(style: DisplayStyleState) { - this.view.displayStyle = style; - } - - /** Selectively override aspects of this viewport's display style. - * @see [DisplayStyleSettings.applyOverrides]($common) - */ - public overrideDisplayStyle(overrides: DisplayStyleSettingsProps): void { - this.displayStyle.settings.applyOverrides(overrides); - } - - /** @see [DisplayStyleSettings.clipStyle]($common) */ - public get clipStyle(): ClipStyle { return this.displayStyle.settings.clipStyle; } - public set clipStyle(style: ClipStyle) { - this.displayStyle.settings.clipStyle = style; - } - - /** Sets the number of [MSAA]($docs/learning/display/MSAA.md) samples for this viewport. - * The number of samples is a power of two. Values of 1 or less indicates anti-aliasing should be disabled. Non-power-of-two values are rounded - * down to the nearest power of two. The maximum number of samples supported depends upon the client's graphics hardware capabilities. Higher values produce - * a higher-quality image but also may also reduce framerate. - * @see [[ViewManager.setAntialiasingAllViews]] to adjust the number of samples for all viewports. - */ - public get antialiasSamples(): number { - return undefined !== this._target ? this._target.antialiasSamples : 1; - } - public set antialiasSamples(numSamples: number) { - if (undefined !== this._target) { - this._target.antialiasSamples = numSamples; - this.invalidateRenderPlan(); - } - } - - /** return true if viewing globe (globeMode is 3D and eye location is far above globe - * @alpha - */ - public get viewingGlobe() { - const view = this.view; - if (!view.is3d()) - return false; - - return this.displayStyle.globeMode === GlobeMode.Ellipsoid && view.isGlobalView; - } - - /** Remove any [[SubCategoryOverride]] for the specified subcategory. - * @param id The Id of the subcategory. - * @see [[overrideSubCategory]] - */ - public dropSubCategoryOverride(id: Id64String): void { - this.view.displayStyle.dropSubCategoryOverride(id); - } - - /** Override the symbology of geometry belonging to a specific subcategory when rendered within this viewport. - * @param id The Id of the subcategory. - * @param ovr The symbology overrides to apply to all geometry belonging to the specified subcategory. - * @see [[dropSubCategoryOverride]] - */ - public overrideSubCategory(id: Id64String, ovr: SubCategoryOverride): void { - this.view.displayStyle.overrideSubCategory(id, ovr); - } - - /** Query the symbology overrides applied to geometry belonging to a specific subcategory when rendered within this viewport. - * @param id The Id of the subcategory. - * @return The symbology overrides applied to all geometry belonging to the specified subcategory, or undefined if no such overrides exist. - * @see [[overrideSubCategory]] - */ - public getSubCategoryOverride(id: Id64String): SubCategoryOverride | undefined { - return this.view.displayStyle.getSubCategoryOverride(id); - } - - /** Query the symbology with which geometry belonging to a specific subcategory is rendered within this viewport. - * Every [[SubCategory]] defines a base symbology independent of any [[Viewport]]. - * If a [[SubCategoryOverride]] has been applied to the subcategory within the context of this [[Viewport]], it will be applied to the subcategory's base symbology. - * @param id The Id of the subcategory. - * @return The symbology of the subcategory within this viewport, including any overrides. - * @see [[overrideSubCategory]] - */ - public getSubCategoryAppearance(id: Id64String): SubCategoryAppearance { - const app = this.iModel.subcategories.getSubCategoryAppearance(id); - if (undefined === app) - return SubCategoryAppearance.defaults; - - const ovr = this.getSubCategoryOverride(id); - return undefined !== ovr ? ovr.override(app) : app; - } - - /** Determine whether geometry belonging to a specific SubCategory is visible in this viewport, assuming the containing Category is displayed. - * @param id The Id of the subcategory - * @returns true if the subcategory is visible in this viewport. - * @note Because this function does not know the Id of the containing Category, it does not check if the Category is enabled for display. The caller should check that separately if he knows the Id of the Category. - */ - public isSubCategoryVisible(id: Id64String): boolean { return this.view.isSubCategoryVisible(id); } - - /** Override the appearance of a model when rendered within this viewport. - * @param id The Id of the model. - * @param ovr The symbology overrides to apply to all geometry belonging to the specified subcategory. - * @see [DisplayStyleSettings.overrideModelAppearance]($common) - */ - public overrideModelAppearance(id: Id64String, ovr: FeatureAppearance): void { - this.view.displayStyle.settings.overrideModelAppearance(id, ovr); - } - - /** Remove any model appearance override for the specified model. - * @param id The Id of the model. - * @see [DisplayStyleSettings.dropModelAppearanceOverride]($common) - */ - public dropModelAppearanceOverride(id: Id64String): void { - this.view.displayStyle.settings.dropModelAppearanceOverride(id); - } - - /** Some changes may or may not require us to invalidate the scene. - * Specifically, when shadows are enabled or we are displaying view attachments, the following changes may affect the visibility or transparency of elements or features: - * - Viewed categories and subcategories; - * - Always/never drawn elements - * - Symbology overrides. - */ - private maybeInvalidateScene(): void { - // When shadows are being displayed and the set of displayed categories changes, we must invalidate the scene so that shadows will be regenerated. - // Same occurs when changing feature symbology overrides (e.g., always/never-drawn element sets, transparency override) - if (!this._sceneValid) - return; - - if (this.view.displayStyle.wantShadows || this.view.isSheetView()) - this.invalidateScene(); - } - - /** Enable or disable display of elements belonging to a set of categories specified by Id. - * Visibility of individual subcategories belonging to a category can be controlled separately through the use of [[SubCategoryOverride]]s. - * By default, enabling display of a category does not affect display of subcategories thereof which have been overridden to be invisible. - * @param categories The Id(s) of the categories to which the change should be applied. No other categories will be affected. - * @param display Whether or not elements on the specified categories should be displayed in the viewport. - * @param enableAllSubCategories Specifies that when enabling display for a category, all of its subcategories should also be displayed even if they are overridden to be invisible. - */ - public changeCategoryDisplay(categories: Id64Arg, display: boolean, enableAllSubCategories: boolean = false): void { - if (!display) { - this.view.categorySelector.dropCategories(categories); - return; - } - - this.view.categorySelector.addCategories(categories); - const categoryIds = Id64.toIdSet(categories); - - this.updateSubCategories(categoryIds, enableAllSubCategories); - } - - private updateSubCategories(categoryIds: Id64Arg, enableAllSubCategories: boolean): void { - this.subcategories.push(this.iModel.subcategories, categoryIds, () => { - if (enableAllSubCategories) - this.enableAllSubCategories(categoryIds); - - this._changeFlags.setViewedCategories(); - }); - } - - private enableAllSubCategories(categoryIds: Id64Arg): void { - for (const categoryId of Id64.iterable(categoryIds)) { - const subCategoryIds = this.iModel.subcategories.getSubCategories(categoryId); - if (undefined !== subCategoryIds) { - for (const subCategoryId of subCategoryIds) - this.changeSubCategoryDisplay(subCategoryId, true); - } - } - } - - /** @internal */ - public getSubCategories(categoryId: Id64String): Id64Set | undefined { return this.iModel.subcategories.getSubCategories(categoryId); } - - /** Change the visibility of geometry belonging to the specified subcategory when displayed in this viewport. - * @param subCategoryId The Id of the subcategory - * @param display: True to make geometry belonging to the subcategory visible within this viewport, false to make it invisible. - */ - public changeSubCategoryDisplay(subCategoryId: Id64String, display: boolean): void { - const app = this.iModel.subcategories.getSubCategoryAppearance(subCategoryId); - if (undefined === app) - return; // category not enabled or subcategory not found - - const curOvr = this.getSubCategoryOverride(subCategoryId); - const isAlreadyVisible = undefined !== curOvr && undefined !== curOvr.invisible ? !curOvr.invisible : !app.invisible; - if (isAlreadyVisible === display) - return; - - // Preserve existing overrides - just flip the visibility flag. - const json = undefined !== curOvr ? curOvr.toJSON() : {}; - json.invisible = !display; - this.overrideSubCategory(subCategoryId, SubCategoryOverride.fromJSON(json)); // will set the ChangeFlag appropriately - this.maybeInvalidateScene(); - } - - /** The settings controlling how a background map is displayed within a view. - * @see [[ViewFlags.backgroundMap]] for toggling display of the map on or off. - * @see [DisplayStyleSettings.backgroundMap]($common) - */ - public get backgroundMapSettings(): BackgroundMapSettings { return this.displayStyle.backgroundMapSettings; } - public set backgroundMapSettings(settings: BackgroundMapSettings) { - this.displayStyle.backgroundMapSettings = settings; - } - - /** @see [[DisplayStyleState.changeBackgroundMapProps]] */ - public changeBackgroundMapProps(props: BackgroundMapProps): void { - this.displayStyle.changeBackgroundMapProps(props); - } - - /** @see [[DisplayStyleState.changeBackgroundMapProvider]] */ - public changeBackgroundMapProvider(props: BackgroundMapProviderProps): void { - this.displayStyle.changeBackgroundMapProvider(props); - } - - /** @internal */ - public get backgroundMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundMap; } - - /** @internal */ - public get overlayMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.overlayMap; } - - /** @internal */ - public get backgroundDrapeMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundDrapeMap; } - - /** @internal */ - public getMapLayerImageryProvider(index: number, isOverlay: boolean): MapLayerImageryProvider | undefined { return this._mapTiledGraphicsProvider?.getMapLayerImageryProvider(index, isOverlay); } - - /** Returns true if this Viewport is currently displaying the model with the specified Id. */ - public viewsModel(modelId: Id64String): boolean { return this.view.viewsModel(modelId); } - - /** Attempt to change the 2d Model this Viewport is displaying, if its ViewState is a ViewState2d. - * @param baseModelId The Id of the new 2d Model to be displayed. - * @param options options that determine how the new view is displayed - * @note This function *only works* if the viewport is viewing a [[ViewState2d]], otherwise it does nothing. Also note that - * the Model of baseModelId should be the same type (Drawing or Sheet) as the current view. - * @note this method clones the current ViewState2d and sets its baseModelId to the supplied value. The DisplayStyle and CategorySelector remain unchanged. - */ - public async changeViewedModel2d(baseModelId: Id64String, options?: ChangeViewedModel2dOptions & ViewChangeOptions & MarginOptions): Promise { - if (!this.view.is2d()) - return; - - // Clone the current ViewState, change its baseModelId, and ensure the new model is loaded. - const newView = this.view.clone(); // start by cloning the current ViewState - await newView.changeViewedModel(baseModelId); - - this.changeView(newView, options); // switch this viewport to use new ViewState2d - - if (options && options.doFit) { // optionally fit view to the extents of the new model - const range = await this.iModel.models.queryModelRanges([baseModelId]); - this.zoomToVolume(Range3d.fromJSON(range[0]), options); - } - } - - /** Attempt to replace the set of models currently viewed by this viewport, if it is displaying a SpatialView - * @param modelIds The Ids of the models to be displayed. - * @returns false if this Viewport is not viewing a [[SpatialViewState]] - * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. - * @note This function *does not load* any models. If any of the supplied `modelIds` refers to a model that has not been loaded, no graphics will be loaded+displayed in the viewport for that model. - * @see [[replaceViewedModels]] for a similar function that also ensures the requested models are loaded. - */ - public changeViewedModels(modelIds: Id64Arg): boolean { - if (!this.view.isSpatialView()) - return false; - - this.view.modelSelector.models.clear(); - this.view.modelSelector.addModels(modelIds); - return true; - } - - /** Attempt to replace the set of models currently viewed by this viewport, if it is displaying a SpatialView - * @param modelIds The Ids of the models to be displayed. - * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. - * @note If any of the requested models is not yet loaded this function will asynchronously load them before updating the set of displayed models. - */ - public async replaceViewedModels(modelIds: Id64Arg): Promise { - if (this.view.isSpatialView()) { - this.view.modelSelector.models.clear(); - return this.addViewedModels(modelIds); - } - } - - /** Add or remove a set of models from those models currently displayed in this viewport. - * @param modelIds The Ids of the models to add or remove. - * @param display Whether or not to display the specified models in the viewport. - * @returns false if this Viewport is not viewing a [[SpatialViewState]] - * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. - * @note This function *does not load* any models. If `display` is `true` and any of the supplied `models` refers to a model that has not been loaded, no graphics will be loaded+displayed in the viewport for that model. - * @see [[addViewedModels]] for a similar function that also ensures the requested models are loaded. - */ - public changeModelDisplay(models: Id64Arg, display: boolean): boolean { - if (!this.view.isSpatialView()) - return false; - - if (display) - this.view.modelSelector.addModels(models); - else - this.view.modelSelector.dropModels(models); - - return true; - } - - /** Adds a set of models to the set of those currently displayed in this viewport. - * @param modelIds The Ids of the models to add or remove. - * @param display Whether or not to display the specified models in the viewport. - * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. - * @note If any of the requested models is not yet loaded this function will asynchronously load them before updating the set of displayed models. - */ - public async addViewedModels(models: Id64Arg): Promise { - // NB: We want the model selector to update immediately, to avoid callers repeatedly requesting we load+display the same models while we are already loading them. - // This will also trigger scene invalidation and changed events. - if (!this.changeModelDisplay(models, true)) - return; // means it's a 2d model - this function can do nothing useful in 2d. - - const unloaded = this.iModel.models.filterLoaded(models); - if (undefined === unloaded) - return; - - // Need to redraw once models are available. Don't want to trigger events again. - await this.iModel.models.load(models); - this.invalidateScene(); - assert(this.view.isSpatialView()); - this.view.markModelSelectorChanged(); - } - - /** Determines what type (if any) of debug graphics will be displayed to visualize [[Tile]] volumes. Chiefly for debugging. - * @see [[TileBoundingBoxes]] - */ - public get debugBoundingBoxes(): TileBoundingBoxes { return this._debugBoundingBoxes; } - public set debugBoundingBoxes(boxes: TileBoundingBoxes) { - if (boxes !== this.debugBoundingBoxes) { - this._debugBoundingBoxes = boxes; - this.invalidateScene(); - } - } - /** When true, the scene will never be recreated. Chiefly for debugging purposes. - * @internal - */ - public get freezeScene(): boolean { return this._freezeScene; } - public set freezeScene(freeze: boolean) { - if (freeze !== this._freezeScene) { - this._freezeScene = freeze; - if (!freeze) - this.invalidateScene(); - } - } - - /** The iModel of this Viewport */ - public get iModel(): IModelConnection { return this.view.iModel; } - /** @internal */ - public get isPointAdjustmentRequired(): boolean { return this.view.is3d(); } - /** @internal */ - public get isSnapAdjustmentRequired(): boolean { return IModelApp.toolAdmin.acsPlaneSnapLock && this.view.is3d(); } - /** @internal */ - public get isContextRotationRequired(): boolean { return IModelApp.toolAdmin.acsContextLock; } - - /** Enables or disables "fade-out" mode. When this mode is enabled, transparent graphics are rendered with a flat alpha weight, - * causing them to appear de-emphasized. This is typically used in contexts in which a handful of elements are to be emphasized in the view, - * while the rest of the graphics are drawn transparently. - */ - public get isFadeOutActive(): boolean { return this._fadeOutActive; } - public set isFadeOutActive(active: boolean) { - if (active !== this._fadeOutActive) { - this._fadeOutActive = active; - this.invalidateRenderPlan(); - } - } - /** @internal */ - public async getToolTip(hit: HitDetail): Promise { - const promises = new Array>(); - if (this.displayStyle) { - this.displayStyle.forEachTileTreeRef(async (tree) => { - promises.push(tree.getToolTip(hit)); - }); - } - this.forEachMapTreeRef(async (tree) => promises.push(tree.getToolTip(hit))); - - const results = await Promise.all(promises); - for (const result of results) - if (result !== undefined) - return result; - - return ""; - } - - /** If this event has one or more listeners, collection of timing statistics related to rendering frames is enabled. Frame statistics will be received by the listeners whenever a frame is finished rendering. - * @note The timing data collected using this event only collects the amount of time spent on the CPU. Due to performance considerations, time spent on the GPU is not collected. Therefore, these statistics are not a direct mapping to user experience. - * @note In order to avoid interfering with the rendering loop, take care to avoid performing any intensive tasks in your event listeners. - * @see [[FrameStats]] - * @alpha - */ - public readonly onFrameStats = new BeEvent<(frameStats: Readonly) => void>(); - - private _frameStatsCollector = new FrameStatsCollector(this.onFrameStats); - - /** @internal */ - protected constructor(target: RenderTarget) { - this._target = target; - target.assignFrameStatsCollector(this._frameStatsCollector); - this._viewportId = TileUser.generateId(); - this._perModelCategoryVisibility = PerModelCategoryVisibility.createOverrides(this); - IModelApp.tileAdmin.registerUser(this); - } - - public dispose(): void { - if (this.isDisposed) - return; - - this._target = dispose(this._target); - this.subcategories.dispose(); - IModelApp.tileAdmin.forgetUser(this); - this.onDisposed.raiseEvent(this); - this.detachFromView(); - } - - private setView(view: ViewState): void { - if (view === this._view) - return; - - if (this._mapTiledGraphicsProvider) - this._mapTiledGraphicsProvider.setView(view); - this.detachFromView(); - this._view = view; - this.attachToView(); - } - - /** @internal Invoked when the viewport becomes associated with a new ViewState to register event listeners with the view - * and allow the ViewState to set up internal state that is only relevant when associated with a Viewport. - * Also invoked after changing OffScreenViewport.drawingToSheetTransform. - * @internal - */ - protected attachToView(): void { - this.registerDisplayStyleListeners(this.view.displayStyle); - this.registerViewListeners(); - this.view.attachToViewport(this); - this._mapTiledGraphicsProvider = new MapTiledGraphicsProvider(this.viewportId, this.displayStyle); - } - - private registerViewListeners(): void { - const view = this.view; - const removals = this._detachFromView; - - // When we detach from the view, also unregister display style listeners. - removals.push(() => this.detachFromDisplayStyle()); - - removals.push(view.onModelDisplayTransformProviderChanged.addListener(() => this.invalidateScene())); - removals.push(view.details.onClipVectorChanged.addListener(() => this.invalidateRenderPlan())); - - removals.push(view.onViewedCategoriesChanged.addListener(() => { - this._changeFlags.setViewedCategories(); - this.maybeInvalidateScene(); - })); - - removals.push(view.onDisplayStyleChanged.addListener((newStyle) => { - this._changeFlags.setDisplayStyle(); - this.setFeatureOverrideProviderChanged(); - this.invalidateRenderPlan(); - - this.detachFromDisplayStyle(); - this._mapTiledGraphicsProvider = new MapTiledGraphicsProvider(this.viewportId, newStyle); - this.registerDisplayStyleListeners(newStyle); - })); - - if (view.isSpatialView()) { - removals.push(view.onViewedModelsChanged.addListener(() => { - this._changeFlags.setViewedModels(); - this.invalidateScene(); - })); - - removals.push(view.details.onModelClipGroupsChanged.addListener(() => { - this.invalidateScene(); - })); - // If a map elevation request is required (only in cases where terrain is not geodetic) - // then the completion of the request will require synching with the view so that the - // frustum depth is recalculated correctly. Register this for removal when the view is detached. - removals.push(this.iModel.onMapElevationLoaded.addListener((_iModel: IModelConnection) => { - this.synchWithView(); - })); - } - } - - private registerDisplayStyleListeners(style: DisplayStyleState): void { - const settings = style.settings; - const removals = this._detachFromDisplayStyle; - - const displayStyleChanged = () => { - this.invalidateRenderPlan(); - this._changeFlags.setDisplayStyle(); - }; - - const styleAndOverridesChanged = () => { - displayStyleChanged(); - this.setFeatureOverrideProviderChanged(); - }; - - removals.push(settings.onSubCategoryOverridesChanged.addListener(styleAndOverridesChanged)); - removals.push(settings.onModelAppearanceOverrideChanged.addListener(styleAndOverridesChanged)); - removals.push(settings.onBackgroundColorChanged.addListener(displayStyleChanged)); - removals.push(settings.onMonochromeColorChanged.addListener(displayStyleChanged)); - removals.push(settings.onMonochromeModeChanged.addListener(displayStyleChanged)); - removals.push(settings.onClipStyleChanged.addListener(styleAndOverridesChanged)); - removals.push(settings.onPlanarClipMaskChanged.addListener(displayStyleChanged)); - removals.push(settings.onWhiteOnWhiteReversalChanged.addListener(displayStyleChanged)); - removals.push(settings.contextRealityModels.onPlanarClipMaskChanged.addListener(displayStyleChanged)); - removals.push(settings.contextRealityModels.onAppearanceOverridesChanged.addListener(displayStyleChanged)); - removals.push(settings.contextRealityModels.onChanged.addListener(displayStyleChanged)); - - removals.push(style.onOSMBuildingDisplayChanged.addListener(() => { - displayStyleChanged(); - this.synchWithView({ noSaveInUndo: true }); // May change frustum depth. - })); - - const analysisChanged = () => { - this._changeFlags.setDisplayStyle(); - this._analysisFractionValid = false; - IModelApp.requestNextAnimation(); - }; - const analysisStyleChanged = () => { - this.invalidateRenderPlan(); - analysisChanged(); - }; - removals.push(settings.onAnalysisFractionChanged.addListener(analysisChanged)); - removals.push(settings.onAnalysisStyleChanged.addListener(analysisStyleChanged)); - - const scheduleChanged = () => { - this._timePointValid = false; - this._changeFlags.setDisplayStyle(); - this.setFeatureOverrideProviderChanged(); - IModelApp.requestNextAnimation(); - }; - - removals.push(style.onScheduleScriptReferenceChanged.addListener(scheduleChanged)); - removals.push(settings.onTimePointChanged.addListener(scheduleChanged)); - - removals.push(settings.onViewFlagsChanged.addListener((vf) => { - if (vf.backgroundMap !== this.viewFlags.backgroundMap) - this.invalidateController(); - else - this.invalidateRenderPlan(); - - this._changeFlags.setDisplayStyle(); - })); - - // ###TODO detach/attach reality model - // ###TODO reality model appearance overrides - // ###TODO OSM Building display - - const mapChanged = () => { - this.invalidateController(); - this._changeFlags.setDisplayStyle(); - }; - - removals.push(settings.onBackgroundMapChanged.addListener(mapChanged)); - removals.push(settings.onMapImageryChanged.addListener(mapChanged)); - - removals.push(settings.onExcludedElementsChanged.addListener(() => { - this._changeFlags.setDisplayStyle(); - this.maybeInvalidateScene(); - this.setFeatureOverrideProviderChanged(); - })); - - if (settings.is3d()) { - removals.push(settings.onLightsChanged.addListener(displayStyleChanged)); - removals.push(settings.onSolarShadowsChanged.addListener(displayStyleChanged)); - removals.push(settings.onThematicChanged.addListener(displayStyleChanged)); - removals.push(settings.onHiddenLineSettingsChanged.addListener(displayStyleChanged)); - removals.push(settings.onAmbientOcclusionSettingsChanged.addListener(displayStyleChanged)); - removals.push(settings.onEnvironmentChanged.addListener(displayStyleChanged)); - removals.push(settings.onPlanProjectionSettingsChanged.addListener(displayStyleChanged)); - } - } - - /** @internal Invoked when the viewport becomes associated with a new ViewState to unregister event listeners for - * the previous ViewState and allow the previous ViewState to clean up any internal state that is only relevant while - * associated with a Viewport. - * Also invoked after changing OffScreenViewport.drawingToSheetTransform. - * @internal - */ - protected detachFromView(): void { - this._detachFromView.forEach((f) => f()); - this._detachFromView.length = 0; - - if (this._view) - this._view.detachFromViewport(); - - } - - private detachFromDisplayStyle(): void { - this._detachFromDisplayStyle.forEach((f) => f()); - this._detachFromDisplayStyle.length = 0; - - if (this._mapTiledGraphicsProvider) { - this._mapTiledGraphicsProvider.detachFromDisplayStyle(); - this._mapTiledGraphicsProvider = undefined; - } - } - - /** Enables or disables continuous rendering. Ideally, during each render frame a Viewport will do as little work as possible. - * To make that possible, the viewport keeps track of what has changed about its internal state from one frame to the next. - * For example, if the view frustum has not changed since the previous frame, it is likely that the viewport does not need to be - * re-rendered at all. - * - * In some circumstances, it is desirable to bypass the logic that limits the amount of work performed each frame. A primary example - * is a viewport that has some animations applied to it, or when diagnostic information like frames-per-second is being monitored. - * - * @note An application which enables continuous rendering should disable it as soon as it is no longer needed. - */ - public get continuousRendering(): boolean { return this._doContinuousRendering; } - public set continuousRendering(contRend: boolean) { - if (contRend !== this._doContinuousRendering) { - this._doContinuousRendering = contRend; - if (contRend) - IModelApp.requestNextAnimation(); - } - } - /** This gives each Viewport a unique Id, which can be used for comparing and sorting Viewport objects inside collections. - * @internal - */ - /** A unique integer Id for this viewport that can be used for comparing and sorting Viewport objects inside collections like [SortedArray]($core-bentley)s. */ - public get viewportId(): number { - return this._viewportId; - } - - /** The ViewState for this Viewport */ - public get view(): ViewState { - return this._view; - } - - /** @internal */ - public get pixelsPerInch() { - // ###TODO? This is apparently unobtainable information in a browser... - return 96; - } - - /** @internal */ - public get backgroundMapGeometry(): BackgroundMapGeometry | undefined { return this.view.displayStyle.getBackgroundMapGeometry(); } - - /** Ids of a set of elements which should not be rendered within this view. - * @note Do not modify this set directly - use [[setNeverDrawn]] or [[clearNeverDrawn]] instead. - * @note This set takes precedence over the [[alwaysDrawn]] set - if an element is present in both sets, it is never drawn. - */ - public get neverDrawn(): Id64Set | undefined { return this._neverDrawn; } - - /** Ids of a set of elements which should always be rendered within this view, regardless of category and subcategory visibility. - * If the [[isAlwaysDrawnExclusive]] flag is also set, *only* those elements in this set will be drawn. - * @note Do not modify this set directly - use [[setAlwaysDrawn]] or [[clearAlwaysDrawn]] instead. - * @note The [[neverDrawn]] set takes precedence - if an element is present in both sets, it is never drawn. - */ - public get alwaysDrawn(): Id64Set | undefined { return this._alwaysDrawn; } - - /** Clear the set of always-drawn elements. - * @see [[alwaysDrawn]] - */ - public clearAlwaysDrawn(): void { - if ((undefined !== this.alwaysDrawn && 0 < this.alwaysDrawn.size) || this._alwaysDrawnExclusive) { - if (undefined !== this.alwaysDrawn) - this.alwaysDrawn.clear(); - - this._alwaysDrawnExclusive = false; - this._changeFlags.setAlwaysDrawn(); - this.maybeInvalidateScene(); - } - } - - /** Clear the set of never-drawn elements. - * @see [[neverDrawn]] - */ - public clearNeverDrawn(): void { - if (undefined !== this.neverDrawn && 0 < this.neverDrawn.size) { - this.neverDrawn.clear(); - this._changeFlags.setNeverDrawn(); - this.maybeInvalidateScene(); - } - } - - /** Specify the Ids of a set of elements which should never be rendered within this view. - * @see [[neverDrawn]]. - */ - public setNeverDrawn(ids: Id64Set): void { - this._neverDrawn = ids; - this._changeFlags.setNeverDrawn(); - this.maybeInvalidateScene(); - } - - /** Specify the Ids of a set of elements which should always be rendered within this view, regardless of category and subcategory visibility. - * @param ids The Ids of the elements to always draw. - * @param exclusive If true, *only* the specified elements will be drawn. - * @see [[alwaysDrawn]] - * @see [[isAlwaysDrawnExclusive]] - */ - public setAlwaysDrawn(ids: Id64Set, exclusive: boolean = false): void { - this._alwaysDrawn = ids; - this._alwaysDrawnExclusive = exclusive; - this._changeFlags.setAlwaysDrawn(); - this.maybeInvalidateScene(); - } - - /** Returns true if the set of elements in the [[alwaysDrawn]] set are the *only* elements rendered within this view. */ - public get isAlwaysDrawnExclusive(): boolean { return this._alwaysDrawnExclusive; } - - /** Allows visibility of categories within this viewport to be overridden on a per-model basis. */ - public get perModelCategoryVisibility(): PerModelCategoryVisibility.Overrides { return this._perModelCategoryVisibility; } - - /** Adds visibility overrides for any subcategories whose visibility differs from that defined by the view's - * category selector in the context of specific models. - * @internal - */ - public addModelSubCategoryVisibilityOverrides(fs: FeatureSymbology.Overrides, ovrs: Id64.Uint32Map): void { - this._perModelCategoryVisibility.addOverrides(fs, ovrs); - } - - /** Add a [[FeatureOverrideProvider]] to customize the appearance of [[Feature]]s within the viewport. - * The provider will be invoked whenever the overrides are determined to need updating. - * The overrides can be explicitly marked as needing a refresh by calling [[Viewport.setFeatureOverrideProviderChanged]]. This is typically called when - * the internal state of the provider changes such that the computed overrides must also change. - * @note A Viewport can have any number of FeatureOverrideProviders. No attempt is made to resolve conflicts between two different providers overriding the same Feature. - * @param provider The provider to register. - * @returns true if the provider was registered, or false if the provider was already registered. - * @see [[dropFeatureOverrideProvider]] to remove the provider. - * @see [[findFeatureOverrideProvider]] to find an existing provider. - * @see [[FeatureSymbology.Overrides]]. - */ - public addFeatureOverrideProvider(provider: FeatureOverrideProvider): boolean { - if (this._featureOverrideProviders.includes(provider)) - return false; - - this._featureOverrideProviders.push(provider); - this.setFeatureOverrideProviderChanged(); - return true; - } - - /** Removes the specified FeatureOverrideProvider from the viewport. - * @param provider The provider to drop. - * @returns true if the provider was dropped, or false if it was not registered. - * @see [[addFeatureOverrideProvider]]. - */ - public dropFeatureOverrideProvider(provider: FeatureOverrideProvider): boolean { - const index = this._featureOverrideProviders.indexOf(provider); - if (-1 === index) - return false; - - this._featureOverrideProviders.splice(index, 1); - this.setFeatureOverrideProviderChanged(); - return true; - } - - /** Locate the first registered FeatureOverrideProvider matching the supplied criterion. - * @param predicate A function that will be invoked for each provider currently registered with the viewport, returning true to accept the provider. - * @returns The first registered provider that matches the predicate, or undefined if no providers match the predicate. - * @see [[findFeatureOverrideProviderOfType]] to locate a provider of a specific class. - * @see [[addFeatureOverrideProvider]] to register a provider. - */ - public findFeatureOverrideProvider(predicate: (provider: FeatureOverrideProvider) => boolean): FeatureOverrideProvider | undefined { - for (const provider of this._featureOverrideProviders) - if (predicate(provider)) - return provider; - - return undefined; - } - - /** The list of [[FeatureOverrideProvider]]s registered with this viewport. - * @see [[addFeatureOverrideProvider]] to register a new provider. - * @see [[dropFeatureOverrideProvider]] to unregister a provider. - * @see [[findFeatureOverrideProvider]] or [[findFeatureOverrideProviderOfType]] to find a registered provider. - */ - public get featureOverrideProviders(): Iterable { - return this._featureOverrideProviders; - } - - /** Locate the first registered FeatureOverrideProvider of the specified class. For example, to locate a registered [[EmphasizeElements]] provider: - * ```ts - * const provider: EmphasizeElements = viewport.findFeatureOverrideProviderOfType(EmphasizeElements); - * ``` - * @see [[findFeatureOverrideProvider]] to locate a registered provider matching any arbitrary criterion. - */ - public findFeatureOverrideProviderOfType(type: Constructor): T | undefined { - const provider = this.findFeatureOverrideProvider((x) => isInstanceOf(x, type)); - return asInstanceOf(provider, type); - } - - /** @internal */ - public addFeatureOverrides(ovrs: FeatureSymbology.Overrides): void { - for (const provider of this._featureOverrideProviders) - provider.addFeatureOverrides(ovrs, this); - } - - /** Notifies this viewport that the internal state of its [[FeatureOverrideProvider]] has changed such that its - * [[FeatureSymbology.Overrides]] should be recomputed. - */ - public setFeatureOverrideProviderChanged(): void { - this._changeFlags.setFeatureOverrideProvider(); - this.maybeInvalidateScene(); - } - - /** The [[TiledGraphicsProvider]]s currently registered with this viewport. - * @see [[addTiledGraphicsProvider]]. - */ - public get tiledGraphicsProviders(): Iterable { - return this._tiledGraphicsProviders; - } - - /** @internal */ - public forEachTiledGraphicsProvider(func: (provider: TiledGraphicsProvider) => void): void { - for (const provider of this._tiledGraphicsProviders) - func(provider); - } - - /** @internal */ - protected forEachTiledGraphicsProviderTree(func: (ref: TileTreeReference) => void): void { - for (const provider of this._tiledGraphicsProviders) - provider.forEachTileTreeRef(this, (ref) => func(ref)); - } - - /** @internal */ - public forEachMapTreeRef(func: (ref: TileTreeReference) => void): void { - if (this._mapTiledGraphicsProvider) - this._mapTiledGraphicsProvider.forEachTileTreeRef(this, (ref) => func(ref)); - } - - /** @internal */ - public forEachTileTreeRef(func: (ref: TileTreeReference) => void): void { - this.view.forEachTileTreeRef(func); - this.forEachTiledGraphicsProviderTree(func); - this.forEachMapTreeRef(func); - } - - /** - * Returns true if all [[TileTree]]s required by this viewport have been loaded. - */ - public get areAllTileTreesLoaded(): boolean { - if (!this.view.areAllTileTreesLoaded) - return false; - - if (this._mapTiledGraphicsProvider && !TiledGraphicsProvider.isLoadingComplete(this._mapTiledGraphicsProvider, this)) - return false; - - for (const provider of this._tiledGraphicsProviders) - if (!TiledGraphicsProvider.isLoadingComplete(provider, this)) - return false; - - return true; - } - - /** Disclose *all* TileTrees currently in use by this Viewport. This set may include trees not reported by [[forEachTileTreeRef]] - e.g., those used by view attachments, map-draped terrain, etc. - * @internal - */ - public discloseTileTrees(trees: DisclosedTileTreeSet): void { - this.forEachTiledGraphicsProviderTree((ref) => trees.disclose(ref)); - this.forEachMapTreeRef((ref) => trees.disclose(ref)); - trees.disclose(this.view); - } - - /** Register a provider of tile graphics to be drawn in this viewport. - * @see [[dropTiledGraphicsProvider]] - */ - public addTiledGraphicsProvider(provider: TiledGraphicsProvider): void { - this._tiledGraphicsProviders.add(provider); - this.invalidateScene(); - } - - /** Remove a previously-registered provider of tile graphics. - * @see [[addTiledGraphicsProvider]] - */ - public dropTiledGraphicsProvider(provider: TiledGraphicsProvider): void { - this._tiledGraphicsProviders.delete(provider); - this.invalidateScene(); - } - - /** Returns true if the specified provider has been registered with this viewport via [[addTiledGraphicsProvider]]. */ - public hasTiledGraphicsProvider(provider: TiledGraphicsProvider): boolean { - return this._tiledGraphicsProviders.has(provider); - } - - /** @internal */ - public mapLayerFromHit(hit: HitDetail): MapLayerSettings | undefined { - return undefined === hit.modelId ? undefined : this.mapLayerFromIds(hit.modelId, hit.sourceId); - } - - /** @internal */ - public mapLayerFromIds(mapTreeId: Id64String, layerTreeId: Id64String): MapLayerSettings | undefined { - return this._mapTiledGraphicsProvider?.mapLayerFromIds(mapTreeId, layerTreeId); - } - - /** @internal */ - public getTerrainHeightRange(): Range1d { - const heightRange = Range1d.createNull(); - this.forEachTileTreeRef((ref) => ref.getTerrainHeight(heightRange)); - return heightRange; - } - /** @internal */ - public setViewedCategoriesPerModelChanged(): void { - this._changeFlags.setViewedCategoriesPerModel(); - } - - /** @internal */ - public markSelectionSetDirty() { this._selectionSetDirty = true; } - - /** True if this is a 3d view with the camera turned on. */ - public get isCameraOn(): boolean { - return this.view.is3d() && this.view.isCameraOn; - } - - /** @internal */ - public changeDynamics(dynamics: GraphicList | undefined): void { - this.target.changeDynamics(dynamics); - this.invalidateDecorations(); - } - - private _assigningFlashedId = false; - - /** The Id of the currently-flashed object. - * The "flashed" visual effect is typically applied to the object in the viewport currently under the mouse cursor, to indicate - * it is ready to be interacted with by a tool. [[ToolAdmin]] is responsible for updating it when the mouse cursor moves. - * The object is usually an [Element]($backend) but could also be a [Model]($backend) or pickable decoration produced by a [[Decorator]]. - * The setter ignores any string that is not a well-formed [Id64String]($core-bentley). Passing [Id64.invalid]($core-bentley) to the - * setter is equivalent to passing `undefined` - both mean "nothing is flashed". - * @throws Error if an attempt is made to change this property from within an [[onFlashedIdChanged]] event callback. - * @see [[onFlashedIdChanged]] to be notified when the flashed object changes. - * @see [[flashSettings]] to customize the visual effect. - */ - public get flashedId(): Id64String | undefined { - return this._flashedElem; - } - public set flashedId(id: Id64String | undefined) { - if (this._assigningFlashedId) - throw new Error("Cannot assign to Viewport.flashedId from within an onFlashedIdChanged event callback."); - - if (id === Id64.invalid) - id = undefined; - - const previous = this._flashedElem; - if (id === previous || (undefined !== id && !Id64.isId64(id))) - return; - - this._lastFlashedElem = this._flashedElem; - this._flashedElem = id; - - this._assigningFlashedId = true; - try { - // The comparison `id !== previous` above ensures the following assertion, but the compiler doesn't recognize it. - assert(undefined !== id || undefined !== previous); - this.onFlashedIdChanged.raiseEvent(this, { current: id!, previous }); - } finally { - this._assigningFlashedId = false; - } - } - - public get auxCoordSystem(): AuxCoordSystemState { return this.view.auxiliaryCoordinateSystem; } - public getAuxCoordRotation(result?: Matrix3d) { return this.auxCoordSystem.getRotation(result); } - public getAuxCoordOrigin(result?: Point3d) { return this.auxCoordSystem.getOrigin(result); } - - /** The number of outstanding requests for tiles to be displayed in this viewport. - * @see Viewport.numSelectedTiles - */ - public get numRequestedTiles(): number { return IModelApp.tileAdmin.getNumRequestsForUser(this); } - - /** The number of tiles selected for display in the view as of the most recently-drawn frame. - * The tiles selected may not meet the desired level-of-detail for the view, instead being temporarily drawn while - * tiles of more appropriate level-of-detail are loaded asynchronously. - * @see Viewport.numRequestedTiles - * @see Viewport.numReadyTiles - */ - public get numSelectedTiles(): number { - const tiles = IModelApp.tileAdmin.getTilesForUser(this); - return undefined !== tiles ? tiles.selected.size + tiles.external.selected : 0; - } - - /** The number of tiles which were ready and met the desired level-of-detail for display in the view as of the most recently-drawn frame. - * These tiles may *not* have been selected because some other (probably sibling) tiles were *not* ready for display. - * This is a useful metric for determining how "complete" the view is - e.g., one indicator of progress toward view completion can be expressed as: - * ` (numReadyTiles) / (numReadyTiles + numRequestedTiles)` - * @see Viewport.numSelectedTiles - * @see Viewport.numRequestedTiles - */ - public get numReadyTiles(): number { - const tiles = IModelApp.tileAdmin.getTilesForUser(this); - return undefined !== tiles ? tiles.ready.size + tiles.external.ready : 0; - } - - /** @internal */ - public toViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.toViewOrientation(from, to); } - /** @internal */ - public fromViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.fromViewOrientation(from, to); } - - /** Change the ViewState of this Viewport - * @param view a fully loaded (see discussion at [[ViewState.load]] ) ViewState - * @param _opts options for how the view change operation should work - */ - public changeView(view: ViewState, _opts?: ViewChangeOptions) { - const prevView = this.view; - - this.updateChangeFlags(view); - this.doSetupFromView(view); - this.invalidateController(); - this.target.reset(); - - if (undefined !== prevView && prevView !== view) { - this.onChangeView.raiseEvent(this, prevView); - this._changeFlags.setViewState(); - } - } - - /** Determine whether the supplied point is visible in the viewport rectangle. - * @param point the point to test - * @param coordSys the coordinate system of the specified point - * @param borderPaddingFactor optional border for testing with inset view rectangle. - */ - public isPointVisibleXY(point: Point3d, coordSys: CoordSystem = CoordSystem.World, borderPaddingFactor: number = 0.0): boolean { - let testPtView = point; - switch (coordSys) { - case CoordSystem.Npc: - testPtView = this.npcToView(point); - break; - case CoordSystem.World: - testPtView = this.worldToView(point); - break; - } - - const frustum = this.getFrustum(CoordSystem.View); - const screenRangeX = frustum.points[Npc._000].distance(frustum.points[Npc._100]); - const screenRangeY = frustum.points[Npc._000].distance(frustum.points[Npc._010]); - const xBorder = screenRangeX * borderPaddingFactor; - const yBorder = screenRangeY * borderPaddingFactor; - - return (!(testPtView.x < xBorder || testPtView.x > (screenRangeX - xBorder) || testPtView.y < yBorder || testPtView.y > (screenRangeY - yBorder))); - } - - /** Computes the range of npc depth values for a region of the screen - * @param rect the rectangle to test. If undefined, test entire view - * @param result optional DepthRangeNpc to store the result - * @returns the minimum and maximum depth values within the region, or undefined. - */ - public determineVisibleDepthRange(rect?: ViewRect, result?: DepthRangeNpc): DepthRangeNpc | undefined { - if (result) { // Null result if given - result.minimum = 1; - result.maximum = 0; - } - - // Default to a (0, 0, 0) to (1, 1, 1) range if no range was provided - rect = (rect && rect.isValid) ? rect : this.viewRect; - - // Determine the screen rectangle in which to query visible depth min + max - const readRect = rect.computeOverlap(this.viewRect); - if (undefined === readRect) - return undefined; - - let retVal: DepthRangeNpc | undefined; - this.readPixels(readRect, Pixel.Selector.GeometryAndDistance, (pixels) => { - if (!pixels) - return; - - readRect.left = this.cssPixelsToDevicePixels(readRect.left); - readRect.right = this.cssPixelsToDevicePixels(readRect.right); - readRect.bottom = this.cssPixelsToDevicePixels(readRect.bottom); - readRect.top = this.cssPixelsToDevicePixels(readRect.top); - - let maximum = 0; - let minimum = 1; - const frac = this._viewingSpace.frustFraction; - for (let x = readRect.left; x < readRect.right; ++x) { - for (let y = readRect.top; y < readRect.bottom; ++y) { - let npcZ = pixels.getPixel(x, y).distanceFraction; - if (npcZ <= 0.0) - continue; - - if (frac < 1.0) - npcZ *= frac / (1.0 + npcZ * (frac - 1.0)); - - minimum = Math.min(minimum, npcZ); - maximum = Math.max(maximum, npcZ); - } - } - - if (maximum <= 0) - return; - - if (undefined === result) { - result = { minimum, maximum }; - } else { - result.minimum = minimum; - result.maximum = maximum; - } - - retVal = result; - }); - - return retVal; - } - - /** Turn the camera off it is currently on. - * @see [[turnCameraOn]] to turn the camera on. - */ - public turnCameraOff(): void { - if (this.view.is3d() && this.view.isCameraOn) { - this.view.turnCameraOff(); - this.setupFromView(); - } - } - - /** Turn the camera on if it is currently off. If the camera is already on, adjust it to use the supplied lens angle. - * @param lensAngle The lens angle for the camera. If undefined, use view.camera.lens. - * @note This method will fail if the ViewState is not 3d. - * @see [[turnCameraOff]] to turn the camera off. - */ - public turnCameraOn(lensAngle?: Angle): ViewStatus { - const view = this.view; - if (!view.is3d() || !view.supportsCamera()) - return ViewStatus.InvalidViewport; - - if (!lensAngle) - lensAngle = view.camera.lens; - - Camera.validateLensAngle(lensAngle); - - let status; - if (view.isCameraOn) { - status = view.lookAt({ eyePoint: view.getEyePoint(), targetPoint: view.getTargetPoint(), upVector: view.getYVector(), lensAngle }); - } else { - // We need to figure out a new camera target. To do that, we need to know where the geometry is in the view. - // We use the depth of the center of the view for that. - let depthRange = this.determineVisibleDepthRange(); - if (undefined === depthRange || Geometry.isAlmostEqualNumber(depthRange.minimum, depthRange.maximum)) - depthRange = { minimum: 0, maximum: 1 }; - - const middle = depthRange.minimum + ((depthRange.maximum - depthRange.minimum) / 2.0); - const corners = [ - new Point3d(0.0, 0.0, middle), // lower left, at target depth - new Point3d(1.0, 1.0, middle), // upper right at target depth - new Point3d(0.0, 0.0, depthRange.maximum), // lower left, at closest npc - new Point3d(1.0, 1.0, depthRange.maximum), // upper right at closest - ]; - - this.npcToWorldArray(corners); - - const eyePoint = corners[2].interpolate(0.5, corners[3]); // middle of closest plane - const targetPoint = corners[0].interpolate(0.5, corners[1]); // middle of halfway plane - const backDistance = eyePoint.distance(targetPoint) * 2.0; - const frontDistance = view.minimumFrontDistance(); - status = view.lookAt({ eyePoint, targetPoint, upVector: view.getYVector(), lensAngle, frontDistance, backDistance }); - } - - if (ViewStatus.Success === status) - this.setupFromView(); - - return status; - } - - /** Orient this viewport to one of the [[StandardView]] rotations. */ - public setStandardRotation(id: StandardViewId): void { - this.view.setStandardRotation(id); - this.setupFromView(); - } - - private doSetupFromView(view: ViewState) { - if (this._inViewChangedEvent) - return ViewStatus.Success; // ignore echos - - if (!this.isAspectRatioLocked) - view.fixAspectRatio(this.viewRect.aspect); - - this.setView(view); - - const viewSpace = ViewingSpace.createFromViewport(this); - if (undefined === viewSpace) - return ViewStatus.InvalidViewport; - - this._viewingSpace = viewSpace; - - this.invalidateRenderPlan(); - this._controllerValid = true; - - this._inViewChangedEvent = true; - this.onViewChanged.raiseEvent(this); - this._inViewChangedEvent = false; - return ViewStatus.Success; - } - - /** Establish the parameters of this Viewport from the current information in its ViewState */ - public setupFromView(pose?: ViewPose): ViewStatus { - if (undefined !== pose) - this.view.applyPose(pose); - return this.doSetupFromView(this.view); - } - - /** Call [[setupFromView]] on this Viewport and then apply optional behavior. - * @param options _options for behavior of view change. If undefined, all options have their default values (see [[ViewChangeOptions]] for details.) - */ - public synchWithView(_options?: ViewChangeOptions): void { this.setupFromView(); } - - /** Convert an array of points from CoordSystem.View to CoordSystem.Npc */ - public viewToNpcArray(pts: Point3d[]): void { this._viewingSpace.viewToNpcArray(pts); } - /** Convert an array of points from CoordSystem.Npc to CoordSystem.View */ - public npcToViewArray(pts: Point3d[]): void { this._viewingSpace.npcToViewArray(pts); } - /** Convert a point from CoordSystem.View to CoordSystem.Npc - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public viewToNpc(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.viewToNpc(pt, out); } - /** Convert a point from CoordSystem.Npc to CoordSystem.View - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public npcToView(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.npcToView(pt, out); } - /** Convert an array of points from CoordSystem.World to CoordSystem.Npc */ - public worldToNpcArray(pts: Point3d[]): void { this._viewingSpace.worldToNpcArray(pts); } - /** Convert an array of points from CoordSystem.Npc to CoordSystem.World */ - public npcToWorldArray(pts: Point3d[]): void { this._viewingSpace.npcToWorldArray(pts); } - /** Convert an array of points from CoordSystem.World to CoordSystem.View */ - public worldToViewArray(pts: Point3d[]): void { this._viewingSpace.worldToViewArray(pts); } - /** Convert an array of points from CoordSystem.World to CoordSystem.View, as Point4ds */ - public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { this._viewingSpace.worldToView4dArray(worldPts, viewPts); } - /** Convert an array of points from CoordSystem.View to CoordSystem.World */ - public viewToWorldArray(pts: Point3d[]) { this._viewingSpace.viewToWorldArray(pts); } - /** Convert an array of points from CoordSystem.View as Point4ds to CoordSystem.World */ - public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { this._viewingSpace.view4dToWorldArray(viewPts, worldPts); } - /** Convert a point from CoordSystem.World to CoordSystem.Npc - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToNpc(pt, out); } - /** Convert a point from CoordSystem.Npc to CoordSystem.World - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.npcToWorld(pt, out); } - /** Convert a point from CoordSystem.World to CoordSystem.View - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public worldToView(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToView(input, out); } - /** Convert a point from CoordSystem.World to CoordSystem.View as Point4d - * @param input the point to convert - * @param out optional location for result. If undefined, a new Point4d is created. - */ - public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { return this._viewingSpace.worldToView4d(input, out); } - /** Convert a point from CoordSystem.View to CoordSystem.World - * @param pt the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.viewToWorld(input, out); } - /** Convert a point from CoordSystem.View as a Point4d to CoordSystem.View - * @param input the point to convert - * @param out optional location for result. If undefined, a new Point3d is created. - */ - public view4dToWorld(input: Point4d, out?: Point3d): Point3d { return this._viewingSpace.view4dToWorld(input, out); } - - /** Converts inches to pixels based on screen DPI. - * @Note this information may not be accurate in some browsers. - * @param inches the number of inches to convert - * @returns the corresponding number of pixels - */ - public pixelsFromInches(inches: number): number { return inches * this.pixelsPerInch; } - - /** Get an 8-point Frustum corresponding to the 8 corners of the Viewport in the specified coordinate system. - * - * There are two sets of corners that may be of interest. - * The "adjusted" box is the one that is computed by examining the "viewed extents" and moving - * the front and back planes to enclose everything in the view. - * The "unadjusted" box is the one that is stored in the ViewState. - * @param sys Coordinate system for points - * @param adjustedBox If true, retrieve the adjusted box. Otherwise retrieve the box that came from the view definition. - * @param box optional Frustum for return value - * @return the view frustum - * @note The "adjusted" box may be either larger or smaller than the "unadjusted" box. - */ - public getFrustum(sys: CoordSystem = CoordSystem.World, adjustedBox: boolean = true, box?: Frustum): Frustum { return this._viewingSpace.getFrustum(sys, adjustedBox, box); } - - /** Get a copy of the current (unadjusted) frustum of this viewport, in world coordinates. */ - public getWorldFrustum(box?: Frustum): Frustum { return this.getFrustum(CoordSystem.World, false, box); } - - /** Scroll the view by a given number of pixels. - * @param screenDist distance to scroll, in pixels - */ - public scroll(screenDist: XAndY, options?: ViewChangeOptions) { - const view = this.view; - if (!view) - return; - - const distXYZ = new Point3d(screenDist.x, screenDist.y, 0); - if (view.is3d() && view.isCameraOn) { - const frust = this.getFrustum(CoordSystem.View, false)!; - frust.translate(distXYZ); - this.viewToWorldArray(frust.points); - view.setupFromFrustum(frust); - view.centerEyePoint(); - } else { - const pts = [new Point3d(), distXYZ]; - this.viewToWorldArray(pts); - const dist = pts[1].minus(pts[0]); - view.setOrigin(view.getOrigin().plus(dist)); - } - - this.synchWithView(options); - } - - /** Zoom the view by a scale factor, placing the new center at the given point (world coordinates). - * @param newCenter The new center point of the view, in world coordinates. If undefined, use current center. - * @param factor the zoom factor. - * @param options options for behavior of view change - */ - public zoom(newCenter: Point3d | undefined, factor: number, options?: ViewChangeOptions & MarginOptions & OnViewExtentsError): ViewStatus { - const view = this.view; - if (undefined === view) - return ViewStatus.InvalidViewport; - - if (view.is3d() && view.isCameraOn) { - const centerNpc = newCenter ? this.worldToNpc(newCenter) : NpcCenter.clone(); - const scaleTransform = Transform.createFixedPointAndMatrix(centerNpc, Matrix3d.createScale(factor, factor, 1.0)); - - const offset = centerNpc.minus(NpcCenter); // offset by difference of old/new center - offset.z = 0.0; // z center stays the same. - - const offsetTransform = Transform.createTranslationXYZ(offset.x, offset.y, offset.z); - const product = offsetTransform.multiplyTransformTransform(scaleTransform); - - const frust = new Frustum(); - product.multiplyPoint3dArrayInPlace(frust.points); - - this.npcToWorldArray(frust.points); - view.setupFromFrustum(frust); - view.centerEyePoint(); - } else { - // for non-camera views, do the zooming by adjusting the origin and delta directly so there can be no - // chance of the rotation changing due to numerical precision errors calculating it from the frustum corners. - const delta = view.getExtents().scale(factor); - - const rot = view.getRotation(); - const center = rot.multiplyVector(newCenter ? newCenter : view.getCenter()); - - // fix for min/max delta - const stat = view.adjustViewDelta(delta, center, rot, this.viewRect.aspect, options); - if (ViewStatus.Success !== stat) - return stat; - - if (!view.allow3dManipulations()) - center.z = 0.0; - - view.setOrigin(rot.multiplyTransposeVector(delta.scale(.5).vectorTo(center))); - view.setExtents(delta); - } - - this.synchWithView(options); - return ViewStatus.Success; - } - - /** @see [[zoomToPlacements]]. */ - public zoomToPlacementProps(placementProps: PlacementProps[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { - const placements = placementProps.map((props) => isPlacement2dProps(props) ? Placement2d.fromJSON(props) : Placement3d.fromJSON(props)); - this.zoomToPlacements(placements, options); - } - - /** Zoom the view in or out to a fit to the tightest volume enclosing a given set of placements, optionally also changing the view rotation. - * @param placements The array of placements. The view will zoom to fit the union of the placements. - * @param options Options controlling how the view change works and whether to change view rotation. - * @note any invalid placements are ignored. If no valid placements are supplied, this function does nothing. - * @see [[zoomToElements]] to zoom to a set of elements. - * @see [[IModelConnection.Elements.getPlacements]] to obtain the placements for a set of elements. - */ - public zoomToPlacements(placements: Placement[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { - placements = placements.filter((x) => x.isValid); - if (placements.length === 0) - return; - - const view = this.view; - if (undefined !== options) { - if (undefined !== options.standardViewId) { - view.setStandardRotation(options.standardViewId); - } else if (undefined !== options.placementRelativeId) { - const viewRotation = StandardView.getStandardRotation(options.placementRelativeId).clone(); - viewRotation.multiplyMatrixMatrixTranspose(placements[0].transform.matrix, viewRotation); - view.setRotation(viewRotation); - } else if (undefined !== options.viewRotation) { - view.setRotation(options.viewRotation); - } - } - - const viewTransform = Transform.createOriginAndMatrix(undefined, view.getRotation()); - const frust = new Frustum(); - const viewRange = new Range3d(); - for (const placement of placements) - viewRange.extendArray(placement.getWorldCorners(frust).points, viewTransform); - - const ignoreError: ViewChangeOptions & MarginOptions & OnViewExtentsError = { - ...options, - onExtentsError: () => ViewStatus.Success, - }; - - view.lookAtViewAlignedVolume(viewRange, this.viewRect.aspect, ignoreError); - this.synchWithView(options); - } - - /** Zoom the view to a show the tightest box around a given set of ElementProps. Optionally, change view rotation. - * @param props element props. Will zoom to the union of the placements. - * @param options options that control how the view change works and whether to change view rotation. - * @note Do not query for ElementProps just to zoom to their placements - [[zoomToElements]] is much more efficient because it queries only for the placement properties. - */ - public zoomToElementProps(elementProps: ElementProps[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { - if (elementProps.length === 0) - return; - - const placementProps: PlacementProps[] = []; - for (const props of elementProps) { - const placement = (props as any).placement; - if (placement !== undefined && this.view.viewsModel(props.model)) - placementProps.push(placement); - } - - this.zoomToPlacementProps(placementProps, options); - } - - /** Zoom the view to a show the tightest box around a given set of elements. Optionally, change view rotation. - * @param ids the element id(s) to include. Will zoom to the union of the placements. - * @param options options that control how the view change works and whether to change view rotation. - */ - public async zoomToElements(ids: Id64Arg, options?: ViewChangeOptions & MarginOptions & ZoomToOptions): Promise { - const placements = await this.iModel.elements.getPlacements(ids, { type: this.view.is3d() ? "3d" : "2d" }); - this.zoomToPlacements(placements, options); - } - - /** Zoom the view to a volume of space in world coordinates. - * @param volume The low and high corners, in world coordinates. - * @param options options that control how the view change works - */ - public zoomToVolume(volume: LowAndHighXYZ | LowAndHighXY, options?: ViewChangeOptions & MarginOptions) { - this.view.lookAtVolume(volume, this.viewRect.aspect, options); - this.synchWithView(options); - } - - /** Shortcut to call view.setupFromFrustum and then [[setupFromView]] - * @param inFrustum the new viewing frustum - * @returns true if both steps were successful - */ - public setupViewFromFrustum(inFrustum: Frustum): boolean { - const validSize = this.view.setupFromFrustum(inFrustum); - // note: always call setupFromView, even if setupFromFrustum failed - return (ViewStatus.Success === this.setupFromView() && ViewStatus.Success === validSize); - } - - /** Compute the range of all geometry to be displayed in this viewport. */ - public computeViewRange(): Range3d { - const fitRange = this.view.computeFitRange(); - this.forEachTiledGraphicsProviderTree((ref) => { - ref.unionFitRange(fitRange); - }); - return fitRange; - } - - /** Set or clear the animator for this Viewport. - * @param animator The new animator for this Viewport, or undefined to remove current animator. - * @note current animator's `interrupt` method will be called (if it has not completed yet) - * @public - */ - public setAnimator(animator?: Animator) { - this._animator?.interrupt(); - this._animator = animator; - - // Immediately invoke the animator to set up the initial frustum. - // This is important for TwoWayViewportSync; otherwise, the synced viewport will have its frustum set to the final frustum, - // producing a flicker to that frustum during the first frame of animation. - this.animate(); - } - - /** Used strictly by TwoWayViewportSync to change the reactive viewport's view to a clone of the active viewport's ViewState. - * Does *not* trigger "ViewState changed" events. - * @internal - */ - public applyViewState(val: ViewState) { - this.updateChangeFlags(val); - this.setView(val); - this._viewingSpace.view = val; - this.synchWithView({ noSaveInUndo: true }); - } - - /** Invoked from finishUndoRedo, applyViewState, and changeView to potentially recompute change flags based on differences between current and new ViewState. */ - protected updateChangeFlags(newView: ViewState): void { - // Before the first call to changeView, this.view is undefined because we have no frustum. Our API pretends it is never undefined. - const oldView = undefined !== this.viewingSpace ? this.view : undefined; - - if (undefined === oldView || oldView === newView) - return; - - const flags = this._changeFlags; - if (!flags.displayStyle && !oldView.displayStyle.equalState(newView.displayStyle)) - flags.setDisplayStyle(); - - if (!flags.viewedCategories && !oldView.categorySelector.equalState(newView.categorySelector)) - flags.setViewedCategories(); - - if (!flags.neverDrawn) { - if (oldView.displayStyle.settings.compressedExcludedElementIds !== newView.displayStyle.settings.compressedExcludedElementIds) - flags.setNeverDrawn(); - } - - if (flags.viewedModels) - return; - - if (oldView.is2d() && newView.is2d()) { - if (oldView.baseModelId !== newView.baseModelId) - flags.setViewedModels(); - } else if (oldView.isSpatialView() && newView.isSpatialView()) { - if (!oldView.modelSelector.equalState(newView.modelSelector)) - flags.setViewedModels(); - } else { - // switched between 2d and 3d view. - flags.setViewedModels(); - } - } - - private static roundGrid(num: number, units: number): number { - const sign = ((num * units) < 0.0) ? -1.0 : 1.0; - num = (num * sign) / units + 0.5; - return units * sign * Math.floor(num); - } - - private getGridOrientation(origin: Point3d, rMatrix: Matrix3d) { - if (this.view.isSpatialView()) - origin.setFrom(this.iModel.globalOrigin); - - switch (this.view.getGridOrientation()) { - case GridOrientationType.View: { - const center = this.view.getCenter(); - this.toViewOrientation(center); - this.toViewOrientation(origin); - origin.z = center.z; - this.fromViewOrientation(origin); - break; - } - - case GridOrientationType.WorldXY: - break; - - case GridOrientationType.WorldYZ: { - Matrix3d.createRows(rMatrix.getRow(1), rMatrix.getRow(2), rMatrix.getRow(0), rMatrix); - break; - } - - case GridOrientationType.WorldXZ: { - Matrix3d.createRows(rMatrix.getRow(0), rMatrix.getRow(2), rMatrix.getRow(1), rMatrix); - break; - } - } - } - - private pointToStandardGrid(point: Point3d, rMatrix: Matrix3d, origin: Point3d): void { - const planeNormal = rMatrix.getRow(2); - - let eyeVec: Vector3d; - if (this.view.is3d() && this.view.isCameraOn) - eyeVec = this.view.camera.eye.vectorTo(point); - else - eyeVec = this._viewingSpace.rotation.getRow(2); - - eyeVec.normalizeInPlace(); - linePlaneIntersect(point, point, eyeVec, origin, planeNormal, false); - - // // get origin and point in view coordinate system - const pointView = point.clone(); - const originView = origin.clone(); - this.toViewOrientation(pointView); - this.toViewOrientation(originView); - - // subtract off the origin - pointView.y -= originView.y; - pointView.x -= originView.x; - - // round off the remainder to the grid distances - const gridSpacing = this.view.getGridSpacing(); - pointView.x = Viewport.roundGrid(pointView.x, gridSpacing.x); - pointView.y = Viewport.roundGrid(pointView.y, gridSpacing.y); - - // add the origin back in - pointView.x += originView.x; - pointView.y += originView.y; - - // go back to root coordinate system - this.fromViewOrientation(pointView); - point.setFrom(pointView); - } - - /** @internal */ - public pointToGrid(point: Point3d): void { - if (GridOrientationType.AuxCoord === this.view.getGridOrientation()) { - this.pointToStandardGrid(point, this.getAuxCoordRotation(), this.getAuxCoordOrigin()); - return; - } - - const origin = new Point3d(); - const rMatrix = Matrix3d.createIdentity(); - this.getGridOrientation(origin, rMatrix); - this.pointToStandardGrid(point, rMatrix, origin); - } - - /** Get the width of a pixel (a unit vector in the x direction in view coordinates) at a given point in world coordinates, returning the result in meters (world units). - * - * This is most useful to determine how large something is in a view. In particular, in a perspective view - * the result of this method will be a larger number for points closer to the back of the view Frustum (that is, - * one pixel of the view represents more spatial area at the back of the Frustum than the front.) - * @param point The point to test, in World coordinates. If undefined, the center of the view in NPC space is used. - * @returns The width of a view pixel at the supplied world point, in meters. - * @note A "pixel" refers to a logical (CSS) pixel, not a device pixel. - */ - public getPixelSizeAtPoint(point?: Point3d): number { - if (point === undefined) - point = this.npcToWorld(NpcCenter); // if undefined, use center of view - - const worldPts: Point3d[] = []; - const viewPts: Point4d[] = []; - viewPts[0] = this.worldToView4d(point); - viewPts[1] = viewPts[0].clone(); - viewPts[1].x += viewPts[1].w; // form a vector one pixel wide in x direction. - this.view4dToWorldArray(viewPts, worldPts); - - return worldPts[0].distance(worldPts[1]); - } - - private get _wantInvertBlackAndWhite(): boolean { - const bgColor = this.view.backgroundColor.colors; - return ((bgColor.r + bgColor.g + bgColor.b) > (255 * 3) / 2); - } - - /** Get a color that will contrast to the current background color of this Viewport. Either Black or White depending on which will have the most contrast. */ - public getContrastToBackgroundColor(): ColorDef { - return this._wantInvertBlackAndWhite ? ColorDef.black : ColorDef.white; // should we use black or white? - } - - private processFlash(): boolean { - let needsFlashUpdate = false; - - if (this.flashedId !== this._lastFlashedElem) { - this._flashIntensity = 0.0; - this._flashUpdateTime = BeTimePoint.now(); - this._lastFlashedElem = this.flashedId; // flashing has begun; this is now the previous flash - needsFlashUpdate = this.flashedId === undefined; // notify render thread that flash has been turned off (signified by undefined elem) - } - - if (this.flashedId !== undefined && this._flashIntensity < this.flashSettings.maxIntensity) { - assert(undefined !== this._flashUpdateTime); - - const flashDuration = this.flashSettings.duration; - const flashElapsed = BeTimePoint.now().milliseconds - this._flashUpdateTime.milliseconds; - this._flashIntensity = Math.min(flashElapsed, flashDuration.milliseconds) / flashDuration.milliseconds; - this._flashIntensity = Math.min(this._flashIntensity, this.flashSettings.maxIntensity); - - needsFlashUpdate = true; - } - - return needsFlashUpdate; - } - - /** Create a context appropriate for producing the scene to be rendered by this viewport, e.g., by [[createScene]]. */ - public createSceneContext(): SceneContext { - return new SceneContext(this); - } - - /** Populate the context with the scene to be rendered by this viewport. - * @note This method is not typically invoked directly - [[renderFrame]] invokes it as needed to recreate the scene. - */ - public createScene(context: SceneContext): void { - this.view.createScene(context); - if (this._mapTiledGraphicsProvider) - TiledGraphicsProvider.addToScene(this._mapTiledGraphicsProvider, context); - - for (const provider of this._tiledGraphicsProviders) - TiledGraphicsProvider.addToScene(provider, context); - } - - /** Called when the visible contents of the viewport are redrawn. - * @note Due to the frequency of this event, avoid performing expensive work inside event listeners. - */ - public readonly onRender = new BeEvent<(vp: Viewport) => void>(); - - /** @internal */ - protected validateRenderPlan() { - this.target.changeRenderPlan(createRenderPlanFromViewport(this)); - this._renderPlanValid = true; - } - - private animate(): void { - if (this._animator?.animate()) - this._animator = undefined; // animation completed. - } - - /** Renders the contents of this viewport. This method performs only as much work as necessary based on what has changed since - * the last frame. If nothing has changed since the last frame, nothing is rendered. - * @note This method should almost never be invoked directly - it is invoked on your behalf by [[ViewManager]]'s render loop. - */ - public renderFrame(): void { - this._frameStatsCollector.beginFrame(); - - const changeFlags = this._changeFlags; - if (changeFlags.hasChanges) - this._changeFlags = new MutableChangeFlags(ChangeFlag.None); - - const view = this.view; - const target = this.target; - - // Start timer for tile loading time - const timer = new StopWatch(undefined, true); - this._frameStatsCollector.beginTime("totalSceneTime"); - - this._frameStatsCollector.beginTime("animationTime"); - // if any animation is active, perform it now - this.animate(); - this._frameStatsCollector.endTime("animationTime"); - - let isRedrawNeeded = this._redrawPending || this._doContinuousRendering; - this._redrawPending = false; - - const resized = target.updateViewRect(); - if (resized) { - target.onResized(); - this.invalidateController(); - } - - if (!this._controllerValid) - this.setupFromView(); - - if (this._selectionSetDirty) { - target.setHiliteSet(view.iModel.hilited); - this._selectionSetDirty = false; - isRedrawNeeded = true; - } - - let overridesNeeded = changeFlags.areFeatureOverridesDirty; - - if (!this._analysisFractionValid) { - this._analysisFractionValid = isRedrawNeeded = true; - target.analysisFraction = this.displayStyle.settings.analysisFraction; - } - - if (!this._timePointValid) { - isRedrawNeeded = true; - const scheduleScript = view.displayStyle.scheduleState; - if (scheduleScript) { - target.animationBranches = scheduleScript.getAnimationBranches(this.timePoint ?? scheduleScript.duration.low); - if (scheduleScript.containsFeatureOverrides) - overridesNeeded = true; - - if (scheduleScript.script.containsTransform && !this._freezeScene) - this.invalidateScene(); - } - - this._timePointValid = true; - } - - if (overridesNeeded) { - const ovr = new FeatureSymbology.Overrides(this); - target.overrideFeatureSymbology(ovr); - isRedrawNeeded = true; - } - - if (!this._sceneValid) { - if (!this._freezeScene) { - this._frameStatsCollector.beginTime("createChangeSceneTime"); - IModelApp.tileAdmin.clearTilesForUser(this); - IModelApp.tileAdmin.clearUsageForUser(this); - - const context = this.createSceneContext(); - this.createScene(context); - - context.requestMissingTiles(); - target.changeScene(context.scene); - isRedrawNeeded = true; - this._frameStatsCollector.endTime("createChangeSceneTime"); - } - - this._sceneValid = true; - } - - if (!this._renderPlanValid) { - this._frameStatsCollector.beginTime("validateRenderPlanTime"); - this.validateRenderPlan(); - this._frameStatsCollector.endTime("validateRenderPlanTime"); - isRedrawNeeded = true; - } - - if (!this._decorationsValid) { - this._frameStatsCollector.beginTime("decorationsTime"); - const decorations = new Decorations(); - this.addDecorations(decorations); - target.changeDecorations(decorations); - this._decorationsValid = true; - isRedrawNeeded = true; - this._frameStatsCollector.endTime("decorationsTime"); - } - - let requestNextAnimation = false; - if (this.processFlash()) { - target.setFlashed(undefined !== this.flashedId ? this.flashedId : Id64.invalid, this._flashIntensity); - isRedrawNeeded = true; - requestNextAnimation = undefined !== this.flashedId; - } - - this._frameStatsCollector.beginTime("onBeforeRenderTime"); - target.onBeforeRender(this, (redraw: boolean) => { - isRedrawNeeded = isRedrawNeeded || redraw; - }); - this._frameStatsCollector.endTime("onBeforeRenderTime"); - - this._frameStatsCollector.endTime("totalSceneTime"); - timer.stop(); - if (isRedrawNeeded) { - target.drawFrame(timer.elapsed.milliseconds); - this.onRender.raiseEvent(this); - } - this._frameStatsCollector.endFrame(isRedrawNeeded); - - // Dispatch change events after timer has stopped and update has finished. - if (resized) - this.onResized.raiseEvent(this); - - if (changeFlags.hasChanges) { - this.onViewportChanged.raiseEvent(this, changeFlags); - - if (changeFlags.displayStyle) - this.onDisplayStyleChanged.raiseEvent(this); - - if (changeFlags.viewedModels) - this.onViewedModelsChanged.raiseEvent(this); - - if (changeFlags.areFeatureOverridesDirty) { - this.onFeatureOverridesChanged.raiseEvent(this); - - if (changeFlags.alwaysDrawn) - this.onAlwaysDrawnChanged.raiseEvent(this); - - if (changeFlags.neverDrawn) - this.onNeverDrawnChanged.raiseEvent(this); - - if (changeFlags.viewedCategories) - this.onViewedCategoriesChanged.raiseEvent(this); - - if (changeFlags.viewedCategoriesPerModel) - this.onViewedCategoriesPerModelChanged.raiseEvent(this); - - if (changeFlags.featureOverrideProvider) - this.onFeatureOverrideProviderChanged.raiseEvent(this); - } - } - - if (requestNextAnimation || undefined !== this._animator || this.continuousRendering) - IModelApp.requestNextAnimation(); - } - - /** @internal */ - protected addDecorations(_decorations: Decorations): void { } - - /** Read selected data about each pixel within a rectangular region of this Viewport. - * @param rect The area of the viewport's contents to read. The origin specifies the upper-left corner. Must lie entirely within the viewport's dimensions. This input viewport is specified using CSS pixels not device pixels. - * @param selector Specifies which aspect(s) of data to read. - * @param receiver A function accepting a [[Pixel.Buffer]] object from which the selected data can be retrieved, or receiving undefined if the viewport is not active, the rect is out of bounds, or some other error. The pixels received will be device pixels, not CSS pixels. See [[Viewport.devicePixelRatio]] and [[Viewport.cssPixelsToDevicePixels]]. - * @param excludeNonLocatable If true, geometry with the "non-locatable" flag set will not be drawn. - * @note The [[Pixel.Buffer]] supplied to the `receiver` function becomes invalid once that function exits. Do not store a reference to it. - */ - public readPixels(rect: ViewRect, selector: Pixel.Selector, receiver: Pixel.Receiver, excludeNonLocatable = false): void { - const viewRect = this.viewRect; - if (!rect.isContained(viewRect)) - receiver(undefined); - else - this.target.readPixels(rect, selector, receiver, excludeNonLocatable); - } - - /** @internal */ - public isPixelSelectable(pixel: Pixel.Data) { - if (undefined === pixel.featureTable || undefined === pixel.elementId) - return false; - - if (pixel.featureTable.modelId === pixel.elementId) - return false; // Reality Models not selectable - - return undefined === this.mapLayerFromIds(pixel.featureTable.modelId, pixel.elementId); // Maps no selectable. - } - - /** Read the current image from this viewport from the rendering system. If a view rectangle outside the actual view is specified, the entire view is captured. - * @param rect The area of the view to read. The origin of a viewRect must specify the upper left corner. - * @param targetSize The size of the image to be returned. The size can be larger or smaller than the original view. - * @param flipVertically If true, the image is flipped along the x-axis. - * @returns The contents of the viewport within the specified rectangle as a bitmap image, or undefined if the image could not be read. - * @note By default the image is returned with the coordinate (0,0) referring to the bottom-most pixel. Pass `true` for `flipVertically` to flip it along the x-axis. - * @deprecated Use readImageBuffer. - */ - public readImage(rect: ViewRect = new ViewRect(0, 0, -1, -1), targetSize: Point2d = Point2d.createZero(), flipVertically: boolean = false): ImageBuffer | undefined { - // eslint-disable-next-line deprecation/deprecation - return this.target.readImage(rect, targetSize, flipVertically); - } - - /** Capture the image currently rendered in this viewport, or a subset thereof. - * @param args Describes the region to capture and optional resizing. By default the entire image is captured with no resizing. - * @returns The image, or `undefined` if the specified capture rect is not fully contained in [[viewRect], a 2d context could not be obtained, or the resultant image consists entirely - * of 100% transparent background pixels. - */ - public readImageBuffer(args?: ReadImageBufferArgs): ImageBuffer | undefined { - return this.target.readImageBuffer(args); - } - - /** Reads the current image from this viewport into an HTMLCanvasElement with a Canvas2dRenderingContext such that additional 2d graphics can be drawn onto it. - * @see [[readImageBuffer]] to obtain the image as an array of RGBA pixels. - */ - public readImageToCanvas(): HTMLCanvasElement { - return this.target.readImageToCanvas(); - } - - /** Get the point at the specified x and y location in the pixel buffer in npc coordinates. - * @see [[getPixelDataWorldPoint]] to obtain the point in [[CoordSystem.World]]. - */ - public getPixelDataNpcPoint(pixels: Pixel.Buffer, x: number, y: number, out?: Point3d): Point3d | undefined { - const z = pixels.getPixel(x, y).distanceFraction; - if (z <= 0.0) - return undefined; - - const viewSpace = this._viewingSpace; - - const result = undefined !== out ? out : new Point3d(); - const viewRect = this.viewRect.clone(); - viewRect.left = this.cssPixelsToDevicePixels(viewRect.left); - viewRect.right = this.cssPixelsToDevicePixels(viewRect.right); - viewRect.bottom = this.cssPixelsToDevicePixels(viewRect.bottom); - viewRect.top = this.cssPixelsToDevicePixels(viewRect.top); - result.x = (x + 0.5 - viewRect.left) / viewRect.width; - result.y = 1.0 - (y + 0.5 - viewRect.top) / viewRect.height; - if (viewSpace.frustFraction < 1.0) - result.z = z * viewSpace.frustFraction / (1.0 + z * (viewSpace.frustFraction - 1.0)); // correct to npc if camera on. - else - result.z = z; - - return result; - } - - /** Get the point at the specified x and y location in the pixel buffer in world coordinates. - * @see [[getPixelDataNpcPoint]] to obtain the point in [[CoordSystem.Npc]]. - */ - public getPixelDataWorldPoint(args: GetPixelDataWorldPointArgs): Point3d | undefined { - const { pixels, x, y, out, preserveModelDisplayTransforms } = args; - const npc = this.getPixelDataNpcPoint(pixels, x, y, out); - if (undefined !== npc) { - this.npcToWorld(npc, npc); - - // If this is a plan projection model, invert the elevation applied to its display transform. - // Likewise, if it is a hit on a model with a display transform, reverse the display transform. - if (!preserveModelDisplayTransforms) { - const modelId = pixels.getPixel(x, y).featureTable?.modelId; - if (undefined !== modelId) { - npc.z -= this.view.getModelElevation(modelId); - this.view.transformPointByModelDisplayTransform(modelId, npc, true); - } - } - } - - return npc; - } - - /** Query which [Feature]($common)s are currently visible within the viewport. - * @param options Specifies how to query. - * @param callback Callback to invoke with the results. - * @note This function may be slow, especially if the features are being queried from screen pixels. Avoid calling it repeatedly in rapid succession. - * @beta - */ - public queryVisibleFeatures(options: QueryVisibleFeaturesOptions, callback: QueryVisibleFeaturesCallback): void { - return queryVisibleFeatures(this, options, callback); - } - - /** @internal */ - public collectStatistics(stats: RenderMemory.Statistics): void { - const trees = new DisclosedTileTreeSet(); - this.discloseTileTrees(trees); - for (const tree of trees) - tree.collectStatistics(stats); - - this.view.collectNonTileTreeStatistics(stats); - } - - /** Intended strictly as a temporary solution for interactive editing applications, until official support for such apps is implemented. - * Invalidates tile trees for all specified models (or all viewed models, if none specified), causing subsequent requests for tiles to make new requests to back-end for updated tiles. - * @internal - */ - public refreshForModifiedModels(modelIds: Id64Arg | undefined): void { - if (this.view.refreshForModifiedModels(modelIds)) - this.invalidateScene(); - } - - /** A multiplier applied to the size in pixels of a [[Tile]] during tile selection for this viewport. Defaults to [[TileAdmin.defaultTileSizeModifier]] but can be overridden per-viewport. - * A value greater than 1.0 causes lower-resolution tiles to be selected; a value less than 1.0 causes higher-resolution tiles to be selected. - * This can allow an application to sacrifice quality for performance or vice-versa. - * @alpha - */ - public get tileSizeModifier(): number { - return undefined !== this._tileSizeModifier ? this._tileSizeModifier : IModelApp.tileAdmin.defaultTileSizeModifier; - } - - /** Controls this Viewport's [[tileSizeModifier]]. - * @param modifier If defined, overrides [[TileAdmin.defaultTileSizeModifier]]; otherwise, resets it to that default. Must be greater than zero. - * @alpha - */ - public setTileSizeModifier(modifier: number | undefined) { - if (modifier === this._tileSizeModifier) - return; - - if (undefined !== modifier && (Number.isNaN(modifier) || modifier <= 0)) - return; - - this._tileSizeModifier = modifier; - this.invalidateScene(); - } - - /** The device pixel ratio used by this Viewport. This value is *not* necessarily equal to `window.devicePixelRatio`. - * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio - */ - public get devicePixelRatio(): number { - return this.target.devicePixelRatio; - } - - /** Convert a number in CSS pixels to device pixels using this Viewport's device pixel ratio. - * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio - * @param num The number in CSS pixels to scale - * @returns The resulting number in device pixels - */ - public cssPixelsToDevicePixels(cssPixels: number): number { - return this.target.cssPixelsToDevicePixels(cssPixels); - } - - /** @see [[ViewState.setModelDisplayTransformProvider]] - * @internal - */ - public setModelDisplayTransformProvider(provider: ModelDisplayTransformProvider): void { - this.view.modelDisplayTransformProvider = provider; - } - - /** An ordered list of names of screen-space post-processing effects to be applied to the image rendered by the Viewport. - * The effects are applied to the image in the order in which they appear in the list. Any names not corresponding to a registered effect are ignored. - * This may have no effect if the Viewport's [[RenderTarget]] does not support screen-space effects. - * @see [[RenderSystem.createScreenSpaceEffectBuilder]] to create and register new effects. - * @public - */ - public get screenSpaceEffects(): Iterable { - return this.target.screenSpaceEffects; - } - public set screenSpaceEffects(effects: Iterable) { - this.target.screenSpaceEffects = effects; - this.requestRedraw(); - } - - /** Append a screen-space effect to the list of effects applied to this Viewport. - * @see [[Viewport.screenSpaceEffects]]. - * @public - */ - public addScreenSpaceEffect(effectName: string): void { - this.screenSpaceEffects = [...this.screenSpaceEffects, effectName]; - } - - /** Remove all screen-space effects from this Viewport. - * @see [[Viewport.screenSpaceEffects]]. - * @public - */ - public removeScreenSpaceEffects(): void { - this.screenSpaceEffects = []; - } - - /** Add an event listener to be invoked whenever the [AnalysisStyle]($common) associated with this viewport changes. - * The analysis style may change for any of several reasons: - * - When the viewport's associated [DisplayStyleSettings.analysisStyle]($common). - * - When the viewport's associated [[ViewState.displayStyle]] changes. - * - When the viewport's associated [[ViewState]] changes via [[changeView]]. - * @param listener Callback accepting the new analysis style, or undefined if there is no analysis style. - * @returns A function that can be invoked to remove the event listener. - */ - public addOnAnalysisStyleChangedListener(listener: (newStyle: AnalysisStyle | undefined) => void): () => void { - const addSettingsListener = (style: DisplayStyleState) => style.settings.onAnalysisStyleChanged.addListener(listener); - let removeSettingsListener = addSettingsListener(this.displayStyle); - - const addStyleListener = (view: ViewState) => view.onDisplayStyleChanged.addListener((style) => { - listener(style.settings.analysisStyle); - removeSettingsListener(); - removeSettingsListener = addSettingsListener(view.displayStyle); - }); - - const removeStyleListener = addStyleListener(this.view); - - const removeViewListener = this.onChangeView.addListener((vp) => { - listener(vp.view.displayStyle.settings.analysisStyle); - removeStyleListener(); - addStyleListener(vp.view); - }); - - return () => { - removeSettingsListener(); - removeStyleListener(); - removeViewListener(); - }; - } - - /** TileUser implementation @internal */ - public get tileUserId(): number { - return this.viewportId; - } - - /** TileUser implementation @internal */ - public onRequestStateChanged(): void { - this.invalidateScene(); - } -} - -/** An interactive Viewport that exists within an HTMLDivElement. ScreenViewports can receive HTML events. - * To render the contents of a ScreenViewport, it must be added to the [[ViewManager]] via ViewManager.addViewport(). - * Every frame, the ViewManager will update the Viewport's state and re-render its contents if anything has changed. - * To halt this loop, use ViewManager.dropViewport() to remove the viewport from the ViewManager. - * - * A ScreenViewport internally owns significant WebGL resources which must be explicitly disposed of when the viewport is no longer needed. - * This is achieved by invoking the viewport's dispose() method. ViewManager.dropViewport() invokes dispose() on the viewport by default. - * - * The lifetime of a ScreenViewport typically follows a pattern: - * ``` - * 1. Application creates the viewport via ScreenViewport.create() - * 2. The viewport is added to the render loop via ViewManager.addViewport() - * 3. When the application is finished with the viewport, it removes it from the render loop and disposes of it via ViewManager.dropViewport(). - * ``` - * - * In some cases it may be useful to temporarily suspend a viewport's render loop. In this case the lifetime of the viewport proceeds as follows: - * ``` - * 1. Application creates the viewport via ScreenViewport.create() - * 2. The viewport is added to the render loop via ViewManager.addViewport() - * 3. At some point the render loop is suspended via ViewManager.dropViewport(viewport, false), indicating the viewport should not be disposed. - * 4. Optionally, resume rendering by returning to step 2. - * 5. When the application is finished with the viewport: - * 5a. If it is currently registered with the ViewManager, it is dropped and disposed of via ViewManager.dropViewport() - * 5b. Otherwise, it is disposed of by invoking its dispose() method directly. - * ``` - * @public - */ -export class ScreenViewport extends Viewport { - /** Settings that may be adjusted to control the way animations are applied to a [[ScreenViewport]] by methods like - * [[changeView]] and [[synchWithView]. - */ - public static animation = { - /** Duration of animations of viewing operations. */ - time: { - fast: BeDuration.fromSeconds(.5), - normal: BeDuration.fromSeconds(1.0), - slow: BeDuration.fromSeconds(1.25), - /** Duration used when zooming with the mouse wheel. */ - wheel: BeDuration.fromSeconds(.5), - }, - /** The easing function to use for view animations. */ - easing: Easing.Cubic.Out, - /** Pertains to view transitions that move far distances, but maintain the same view direction. - * In that case we zoom out, move the camera, and zoom back in rather than transitioning linearly to - * provide context for the starting and ending positions. These settings control how and when that happens. - */ - zoomOut: { - /** Whether to allow zooming out. If you don't want it, set this to false. */ - enable: true, - /** The interpolation function used for camera height and position over the zoomOut operation. */ - interpolation: Interpolation.Bezier, - /** Array of fractional height the camera rises over the animation. Height is interpolated over the array during the duration of the zoom operation. - * At 1.0 it will be high enough that both are visible if the camera were centered between then. - * Must start and end at 0. - */ - heights: [0, 1.5, 2.0, 1.8, 1.5, 1.2, 1, 0], - /** Array of fractional positions of the camera from starting to ending location when zooming. - * Position is interpolated from the array using the interpolation function over the duration of the zoom operation (see tween.ts) - * Must start at 0 and end at 1. - */ - positions: [0, 0, .1, .3, .5, .8, 1], - /** Zoom out/in only if the beginning and ending view's range, each expanded by this factor, overlap. */ - margin: 2.5, - /** Multiply the duration of the animation by this factor when performing a zoom out. */ - durationFactor: 1.5, - }, - }; - - private _evController?: EventController; - private _viewCmdTargetCenter?: Point3d; - /** The number of entries in the view undo/redo buffer. */ - public maxUndoSteps = 20; - private readonly _forwardStack: ViewPose[] = []; - private readonly _backStack: ViewPose[] = []; - private _currentBaseline?: ViewPose; - private _lastPose?: ViewPose; // the pose the last time this view was rendered - private _webglCanvas?: HTMLCanvasElement; - private _logo!: HTMLImageElement; - private readonly _decorationCache = new DecorationsCache(); - - /** The parent HTMLDivElement of the canvas. */ - public readonly parentDiv: HTMLDivElement; - /** The div created to hold all viewport elements. */ - public readonly vpDiv: HTMLDivElement; - /** The canvas to display the view contents. */ - public readonly canvas: HTMLCanvasElement; - /** The HTMLDivElement used for HTML decorations. May be referenced from the DOM by class "overlay-decorators". - * @internal - */ - public readonly decorationDiv: HTMLDivElement; - /** The HTMLDivElement used for toolTips. May be referenced from the DOM by class "overlay-tooltip". */ - public readonly toolTipDiv: HTMLDivElement; - - /** Create a new ScreenViewport that shows a View of an iModel into an HTMLDivElement. This method will create a new HTMLCanvasElement as a child of the supplied parentDiv. - * It also creates two new child HTMLDivElements: one of class "overlay-decorators" for HTML overlay decorators, and one of class - * "overlay-tooltip" for ToolTips. All the new child HTMLElements are the same size as the parentDiv. - * @param parentDiv The HTMLDivElement to contain the ScreenViewport. The element must have non-zero width and height. - * @param view The ViewState for the ScreenViewport. - * @note After creating a new ScreenViewport, you must call [[ViewManager.addViewport]] for it to become "live". You must also ensure you dispose of it properly. - * @throws Error if `parentDiv` has zero width or height. - */ - public static create(parentDiv: HTMLDivElement, view: ViewState): ScreenViewport { - if (0 === parentDiv.clientWidth || 0 === parentDiv.clientHeight) - throw new Error("viewport cannot be created from a div with zero width or height"); - - const canvas = document.createElement("canvas"); - const vp = new this(canvas, parentDiv, IModelApp.renderSystem.createTarget(canvas)); - vp.changeView(view); - return vp; - } - - /** @internal */ - public override dispose(): void { - super.dispose(); - this._decorationCache.clear(); - } - - /** @internal */ - public override invalidateScene(): void { - super.invalidateScene(); - - // When the scene is invalidated, so are all cached decorations - they will be regenerated. - this._decorationCache.clear(); - } - - /** Forces removal of a specific decorator's cached decorations from this viewport, if they exist. - * This will force those decorations to be regenerated. - * @see [[ViewportDecorator.useCachedDecorations]]. - */ - public invalidateCachedDecorations(decorator: ViewportDecorator) { - this._decorationCache.delete(decorator); - - // Always invalidate decorations. Decorator may have no cached decorations currently, but wants them created. - this.invalidateDecorations(); - } - - /** @internal */ - public static markAllChildrenForRemoval(el: HTMLDivElement) { - for (const child of el.children) - child[ELEMENT_MARKED_FOR_REMOVAL] = true; - } - - /** @internal */ - public static removeMarkedChildren(el: HTMLDivElement) { - for (const child of [...el.children]) // spread to duplicate the HTMLCollection which is invalidated by removals - if (child[ELEMENT_MARKED_FOR_REMOVAL]) - el.removeChild(child); - } - - /** Remove all of the children of an HTMLDivElement. - * @internal - */ - public static removeAllChildren(el: HTMLDivElement) { - while (el.lastChild) - el.removeChild(el.lastChild); - } - - /** set Div style to absolute, {0,0,100%,100%} - * @internal - */ - public static setToParentSize(div: HTMLElement) { - const style = div.style; - style.position = "absolute"; - style.top = style.left = "0"; - style.height = style.width = "100%"; - } - - /** add a child element to this.vpDiv and set its size and position the same as the parent. */ - private addChildDiv(parent: HTMLElement, element: HTMLElement, zIndex: number) { - ScreenViewport.setToParentSize(element); - element.style.zIndex = zIndex.toString(); - parent.appendChild(element); - } - - /** @internal */ - public addNewDiv(className: string, overflowHidden: boolean, z: number): HTMLDivElement { - const div = document.createElement("div"); - div.className = className; - div.style.pointerEvents = "none"; - div.style.overflow = overflowHidden ? "hidden" : "visible"; - this.addChildDiv(this.vpDiv, div, z); - return div; - } - - /** The HTMLImageElement of the iTwin.js logo displayed in this ScreenViewport - * @beta - */ - public get logo() { return this._logo; } - - /** @internal */ - protected addLogo() { - const logo = this._logo = IModelApp.makeHTMLElement("img", { parent: this.vpDiv, className: "imodeljs-icon" }); - logo.src = `${IModelApp.publicPath}images/imodeljs-icon.svg`; - logo.alt = ""; - - const showLogos = (ev: Event) => { - const aboutBox = IModelApp.makeModalDiv({ autoClose: true, width: 460, closeBox: true, rootDiv: this.vpDiv.ownerDocument.body }).modal; - aboutBox.className += " imodeljs-about"; // only added so the CSS knows this is the about dialog - const logos = IModelApp.makeHTMLElement("table", { parent: aboutBox, className: "logo-cards" }); - if (undefined !== IModelApp.applicationLogoCard) - logos.appendChild(IModelApp.applicationLogoCard()); - logos.appendChild(IModelApp.makeIModelJsLogoCard()); - this.forEachTileTreeRef((ref) => ref.addLogoCards(logos, this)); - ev.stopPropagation(); - }; - logo.onclick = showLogos; - logo.addEventListener("touchstart", showLogos); - logo.onmousemove = logo.onmousedown = logo.onmouseup = (ev) => ev.stopPropagation(); - } - - /** @internal */ - protected constructor(canvas: HTMLCanvasElement, parentDiv: HTMLDivElement, target: RenderTarget) { - super(target); - this.canvas = canvas; - this.parentDiv = parentDiv; - - // first remove all children of the parent Div - ScreenViewport.removeAllChildren(parentDiv); - - const div = this.vpDiv = IModelApp.makeHTMLElement("div", { className: "imodeljs-vp" }); - this.addChildDiv(this.parentDiv, div, 0); - - this.addChildDiv(this.vpDiv, canvas, 10); - this.target.updateViewRect(); - - // SEE: decorationDiv doc comment - // eslint-disable-next-line deprecation/deprecation - this.decorationDiv = this.addNewDiv("overlay-decorators", true, 30); - this.toolTipDiv = this.addNewDiv("overlay-tooltip", true, 40); - this.setCursor(); - this.addLogo(); - } - - /** Open the toolTip window in this ScreenViewport with the supplied message and location. The tooltip will be a child of [[ScreenViewport.toolTipDiv]]. - * @param message The message to display - * @param location The position of the toolTip, in view coordinates. If undefined, use center of view. - * @param options the ToolTip options - * @note There is only one ToolTip window, so calling this method more than once will move the toolTip and show the second message. - */ - public openToolTip(message: HTMLElement | string, location?: XAndY, options?: ToolTipOptions) { - IModelApp.notifications.openToolTip(this.toolTipDiv, message, location, options); - } - - /** @internal */ - public mousePosFromEvent(ev: MouseEvent): XAndY { - const rect = this.getClientRect(); - return { x: ev.clientX - rect.left, y: ev.clientY - rect.top }; - } - - /** @internal */ - public mouseMovementFromEvent(ev: MouseEvent): XAndY { - return { x: ev.movementX, y: ev.movementY }; - } - - /** Set the event controller for this Viewport. Destroys previous controller, if one was defined. */ - public setEventController(controller?: EventController) { - if (this._evController) - this._evController.destroy(); - - this._evController = controller; - } - - /** Find a point on geometry visible in this Viewport, within a radius of supplied pick point. - * @param pickPoint Point to search about, in world coordinates - * @param radius Radius, in pixels, of the circular area to search. - * @param allowNonLocatable If true, include geometry with non-locatable flag set. - * @param out Optional Point3d to hold the result. If undefined, a new Point3d is returned. - * @returns The point, in world coordinates, on the element closest to `pickPoint`, or undefined if no elements within `radius`. - */ - public pickNearestVisibleGeometry(pickPoint: Point3d, radius?: number, allowNonLocatable = true, out?: Point3d): Point3d | undefined { - const depthResult = this.pickDepthPoint(pickPoint, radius, { excludeNonLocatable: !allowNonLocatable }); - let isValidDepth = false; - switch (depthResult.source) { - case DepthPointSource.Geometry: - case DepthPointSource.Model: - case DepthPointSource.Map: - isValidDepth = true; - break; - case DepthPointSource.BackgroundMap: - case DepthPointSource.GroundPlane: - case DepthPointSource.Grid: - case DepthPointSource.ACS: - const npcPt = this.worldToNpc(depthResult.plane.getOriginRef()); - isValidDepth = !(npcPt.z < 0.0 || npcPt.z > 1.0); - break; - } - if (!isValidDepth) - return undefined; - const result = undefined !== out ? out : new Point3d(); - result.setFrom(depthResult.plane.getOriginRef()); - return result; - } - - /** @internal */ - public picker = new ElementPicker(); // Picker used in pickDepthPoint below so it hangs around and can be queried later. - - /** Find a point on geometry visible in this Viewport, within a radius of supplied pick point. - * If no geometry is selected, return the point projected to the most appropriate reference plane. - * @param pickPoint Point to search about, in world coordinates - * @param radius Radius, in pixels, of the circular area to search. - * @param options Optional settings to control what can be selected. - * @returns A plane with origin from closest geometry point or reference plane projection and the source of the depth point. - * @note The result plane normal is valid when the source is not geometry or a reality model. - */ - public pickDepthPoint(pickPoint: Point3d, radius?: number, options?: DepthPointOptions): { plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource, sourceId?: string } { - if (!this.view.is3d()) - return { plane: Plane3dByOriginAndUnitNormal.createXYPlane(pickPoint), source: DepthPointSource.ACS }; - - if (undefined === radius) - radius = this.pixelsFromInches(ToolSettings.viewToolPickRadiusInches); - - this.picker.empty(); - const locateOpts = new LocateOptions(); - locateOpts.allowNonLocatable = (undefined === options || !options.excludeNonLocatable); - locateOpts.allowDecorations = (undefined === options || !options.excludeDecorations); - locateOpts.allowExternalIModels = (undefined === options || !options.excludeExternalIModels); - locateOpts.preserveModelDisplayTransforms = true; - - if (0 !== this.picker.doPick(this, pickPoint, radius, locateOpts)) { - const hitDetail = this.picker.getHit(0)!; - const hitPoint = hitDetail.getPoint(); - if (hitDetail.isModelHit) - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Model, sourceId: hitDetail.sourceId }; - else if (hitDetail.isMapHit) - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Map, sourceId: hitDetail.sourceId }; - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getZVector())!, source: DepthPointSource.Geometry, sourceId: hitDetail.sourceId }; - } - - const eyePoint = this.worldToViewMap.transform1.columnZ(); - const direction = Vector3d.createFrom(eyePoint); - const aa = Geometry.conditionalDivideFraction(1, eyePoint.w); - if (aa !== undefined) { - const xyzEye = direction.scale(aa); - direction.setFrom(pickPoint.vectorTo(xyzEye)); - } - - direction.scaleToLength(-1.0, direction); - const boresiteIntersectRay = Ray3d.create(pickPoint, direction); - const projectedPt = Point3d.createZero(); - - const backgroundMapGeometry = this.backgroundMapGeometry; - if (undefined !== backgroundMapGeometry) { - const intersect = backgroundMapGeometry.getRayIntersection(boresiteIntersectRay, false); - - if (undefined !== intersect) { - const npcPt = this.worldToNpc(intersect.origin); - if (npcPt.z < 1) // Only if in front of eye. - return { plane: Plane3dByOriginAndUnitNormal.create(intersect.origin, intersect.direction)!, source: DepthPointSource.BackgroundMap }; - } - } - // returns true if there's an intersection that isn't behind the front plane - const boresiteIntersect = (plane: Plane3dByOriginAndUnitNormal) => { - const dist = boresiteIntersectRay.intersectionWithPlane(plane, projectedPt); - if (undefined === dist) - return false; - const npcPt = this.worldToNpc(projectedPt); - return npcPt.z < 1.0; - }; - - if (this.view.getDisplayStyle3d().environment.displayGround) { - const groundPlane = Plane3dByOriginAndUnitNormal.create(Point3d.create(0, 0, this.view.getGroundElevation()), Vector3d.unitZ()); - if (undefined !== groundPlane && boresiteIntersect(groundPlane)) - return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, groundPlane.getNormalRef())!, source: DepthPointSource.GroundPlane }; - } - - const acsPlane = Plane3dByOriginAndUnitNormal.create(this.getAuxCoordOrigin(), this.getAuxCoordRotation().getRow(2)); - if (undefined !== acsPlane && boresiteIntersect(acsPlane)) - return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, acsPlane.getNormalRef())!, source: (this.isGridOn && GridOrientationType.AuxCoord === this.view.getGridOrientation() ? DepthPointSource.Grid : DepthPointSource.ACS) }; - - const targetPointNpc = this.worldToNpc(this.view.getTargetPoint()); - if (targetPointNpc.z < 0.0 || targetPointNpc.z > 1.0) - targetPointNpc.z = 0.5; - - this.worldToNpc(pickPoint, projectedPt); projectedPt.z = targetPointNpc.z; this.npcToWorld(projectedPt, projectedPt); - return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, this.view.getZVector())!, source: DepthPointSource.TargetPoint }; - } - - /** @internal */ - public animateFrustumChange(options?: ViewAnimationOptions) { - if (this._lastPose && this._currentBaseline) - this.setAnimator(new FrustumAnimator(options ? options : {}, this, this._lastPose, this.view.savePose())); - } - - /** Animate the view frustum from a starting frustum to the current view frustum. In other words, - * save a starting frustum (presumably what the user is currently looking at), then adjust the view to - * a different location and call synchWithView, then call this method. After the animation the viewport - * frustum will be restored to its current location. - * @internal - */ - public animateToCurrent(_start: Frustum, options?: ViewAnimationOptions) { - options = options ? options : {}; - this.animateFrustumChange(/* start, this.getFrustum(), */ options); - } - - /** Animate the view frustum to a destination location the earth from the current frustum. */ - public async animateFlyoverToGlobalLocation(destination: GlobalLocation) { - const animator = await GlobeAnimator.create(this, destination); - this.setAnimator(animator); - } - - /** @internal */ - public pickCanvasDecoration(pt: XAndY) { return this.target.pickOverlayDecoration(pt); } - - /** Get the DOMRect of the canvas for this Viewport. */ - public getClientRect(): DOMRect { return this.canvas.getBoundingClientRect(); } - - /** The ViewRect for this ScreenViewport. Left and top will be 0, right will be the width, and bottom will be the height. */ - public get viewRect(): ViewRect { this._viewRange.init(0, 0, this.canvas.clientWidth, this.canvas.clientHeight); return this._viewRange; } - - /** @internal */ - protected override addDecorations(decorations: Decorations): void { - // SEE: decorationDiv doc comment - // eslint-disable-next-line deprecation/deprecation - ScreenViewport.markAllChildrenForRemoval(this.decorationDiv); - const context = new DecorateContext(this, decorations, this._decorationCache); - try { - // It is an error to try to remove cached decorations while we are decorating. - // Some naughty decorators unwittingly do so by e.g. invalidating the scene in their decorate method. - this._decorationCache.prohibitRemoval = true; - - context.addFromDecorator(this.view); - this.forEachTiledGraphicsProviderTree((ref) => context.addFromDecorator(ref)); - - for (const decorator of IModelApp.viewManager.decorators) - context.addFromDecorator(decorator); - - // eslint-disable-next-line deprecation/deprecation - ScreenViewport.removeMarkedChildren(this.decorationDiv); - } finally { - this._decorationCache.prohibitRemoval = false; - } - } - - /** Change the cursor for this Viewport */ - public setCursor(cursor: string = "default"): void { - this.canvas.style.cursor = cursor; - } - - /** @internal */ - public override synchWithView(options?: ViewChangeOptions): void { - options = options ?? {}; - - if (this.view.is3d() && options?.globalAlignment) - this.view.alignToGlobe(options.globalAlignment.target, options.globalAlignment.transition); - - super.synchWithView(options); - - if (true !== options.noSaveInUndo) - this.saveViewUndo(); - if (true === options.animateFrustumChange) - this.animateFrustumChange(options); - } - - /** @internal */ - protected override validateRenderPlan() { - super.validateRenderPlan(); - this._lastPose = this.view.savePose(); - } - - /** Change the ViewState of this Viewport - * @param view a fully loaded (see discussion at [[ViewState.load]] ) ViewState - * @param opts options for how the view change operation should work - */ - public override changeView(view: ViewState, opts?: ViewChangeOptions) { - if (view === this.view) // nothing to do - return; - - this.setAnimator(undefined); // make sure we clear any active animators before we change views. - - opts = opts ?? { animationTime: ScreenViewport.animation.time.slow.milliseconds }; - - // determined whether we can animate this ViewState change - const doAnimate = this.view && this.view.hasSameCoordinates(view) && false !== opts.animateFrustumChange; - if (!doAnimate) - this.clearViewUndo(); // if we can animate, don't throw out view undo. - - super.changeView(view, opts); - this.saveViewUndo(); - - if (doAnimate) - this.animateFrustumChange(opts); - } - - /** @internal */ - public get viewCmdTargetCenter(): Point3d | undefined { return this._viewCmdTargetCenter; } - public set viewCmdTargetCenter(center: Point3d | undefined) { this._viewCmdTargetCenter = center ? center.clone() : undefined; } - /** True if an undoable viewing operation exists on the stack */ - public get isUndoPossible(): boolean { return 0 < this._backStack.length; } - - /** True if a redoable viewing operation exists on the stack */ - public get isRedoPossible(): boolean { return 0 < this._forwardStack.length; } - - /** Clear the undo buffers of this Viewport. This resets the undo stack. */ - public clearViewUndo(): void { - this._currentBaseline = undefined; - this._forwardStack.length = 0; - this._backStack.length = 0; - this._lastPose = undefined; - } - - /** Saves the current state of this viewport's [[ViewState]] in the undo stack, such that it can be restored by a call to [[ScreenViewport.doUndo]]. */ - public saveViewUndo(): void { - if (this._inViewChangedEvent) // echo from a view changed event. - return; - - // the first time we're called we need to establish the baseline - if (!this._currentBaseline) - this._currentBaseline = this.view.savePose(); - - if (this._currentBaseline.equalState(this.view)) - return; // nothing changed, we're done - - const backStack = this._backStack; - if (backStack.length >= this.maxUndoSteps) // don't save more than max - backStack.shift(); // remove the oldest entry - - /** Sometimes we get requests to save undo entries from rapid viewing operations (e.g. mouse wheel rolls). To avoid lots of - * little useless intermediate view undo steps that mean nothing, if we get a call to this within a minimum time (1/2 second by default) - * we don't add a new entry to the view undo buffer. - */ - const now = BeTimePoint.now(); - if (Viewport.undoDelay.isZero || backStack.length < 1 || backStack[backStack.length - 1].undoTime!.plus(Viewport.undoDelay).before(now)) { - this._currentBaseline.undoTime = now; // save time we put this entry in undo buffer - this._backStack.push(this._currentBaseline); // save previous state - this._forwardStack.length = 0; // not possible to do redo after this - } - - this._currentBaseline = this.view.savePose(); - } - - /** Reverses the most recent change to the Viewport from the undo stack. */ - public doUndo(animationTime?: BeDuration) { - if (0 === this._backStack.length || this._currentBaseline === undefined) - return; - - this._forwardStack.push(this._currentBaseline); - this._currentBaseline = this._backStack.pop()!; - this.view.applyPose(this._currentBaseline); - this.finishUndoRedo(animationTime); - this.onViewUndoRedo.raiseEvent(this, ViewUndoEvent.Undo); - } - - /** Re-applies the most recently un-done change to the Viewport from the redo stack. */ - public doRedo(animationTime?: BeDuration) { - if (0 === this._forwardStack.length || this._currentBaseline === undefined) - return; - - this._backStack.push(this._currentBaseline); - this._currentBaseline = this._forwardStack.pop()!; - this.view.applyPose(this._currentBaseline); - this.finishUndoRedo(animationTime); - this.onViewUndoRedo.raiseEvent(this, ViewUndoEvent.Redo); - } - - /** @internal */ - private finishUndoRedo(duration?: BeDuration): void { - this.updateChangeFlags(this.view); - this.setupFromView(); - if (undefined !== duration) - this.animateFrustumChange({ animationTime: duration.milliseconds }); - } - - /** Clear the view undo buffer and establish the current ViewState as the new baseline. */ - public resetUndo() { - this.clearViewUndo(); - this.saveViewUndo(); // Set up new baseline state - } - - /** Show the surface normal for geometry under the cursor when snapping. */ - private static drawLocateHitDetail(context: DecorateContext, aperture: number, hit: HitDetail): void { - if (!context.viewport.view.is3d()) - return; // Not valuable feedback in 2d... - - if (!(hit instanceof SnapDetail) || !hit.normal || hit.isPointAdjusted) - return; // AccuSnap will flash edge/segment geometry if not a surface hit or snap location has been adjusted... - - const builder = context.createGraphicBuilder(GraphicType.WorldOverlay); - const color = context.viewport.hilite.color.inverse().withTransparency(100); // Invert hilite color for good contrast - const colorFill = color.withTransparency(200); - - builder.setSymbology(color, colorFill, 1); - - const skew = context.viewport.view.getAspectRatioSkew(); - const radius = (2.5 * aperture) * context.viewport.getPixelSizeAtPoint(hit.snapPoint); - const rMatrix = Matrix3d.createRigidHeadsUp(hit.normal); - const ellipse = Arc3d.createScaledXYColumns(hit.snapPoint, rMatrix, radius, radius / skew, AngleSweep.create360()); - - builder.addArc(ellipse, true, true); - builder.addArc(ellipse, false, false); - - const lengthX = (0.6 * radius); - const lengthY = lengthX / skew; - const normal = Vector3d.create(); - - ellipse.vector0.normalize(normal); - const pt1 = hit.snapPoint.plusScaled(normal, lengthX); - const pt2 = hit.snapPoint.plusScaled(normal, -lengthX); - builder.addLineString([pt1, pt2]); - - ellipse.vector90.normalize(normal); - const pt3 = hit.snapPoint.plusScaled(normal, lengthY); - const pt4 = hit.snapPoint.plusScaled(normal, -lengthY); - builder.addLineString([pt3, pt4]); - - context.addDecorationFromBuilder(builder); - } - - /** @internal */ - public drawLocateCursor(context: DecorateContext, viewPt: Point3d, aperture: number, isLocateCircleOn: boolean, hit?: HitDetail): void { - if (hit) - ScreenViewport.drawLocateHitDetail(context, aperture, hit); - - if (isLocateCircleOn) { - // draw a filled and outlined circle to represent the size of the location aperture in the current view. - const radius = Math.floor(aperture * 0.5) + 0.5; - const position = viewPt.clone(); - position.x = Math.floor(position.x) + 0.5; - position.y = Math.floor(position.y) + 0.5; - const drawDecoration = (ctx: CanvasRenderingContext2D) => { - ctx.beginPath(); - ctx.strokeStyle = "rgba(255,255,255,.4)"; - ctx.fillStyle = "rgba(255,255,255,.2)"; - ctx.arc(0, 0, radius, 0, 2 * Math.PI); - ctx.fill(); - ctx.stroke(); - ctx.beginPath(); - ctx.strokeStyle = "rgba(0,0,0,.8)"; - ctx.lineWidth = 1; - ctx.arc(0, 0, radius + 1, 0, 2 * Math.PI); - ctx.stroke(); - }; - context.addCanvasDecoration({ position, drawDecoration }, true); - } - } - - /** By default, a Viewport's webgl content is rendered to an off-screen canvas owned by the RenderSystem, then the resultant image is copied to the 2d rendering context - * belonging to the Viewport's own canvas. However, on non-chromium-based browsers this copying incurs a significant performance penalty. So, when only one Viewport - * needs to be drawn, we can switch to rendering the webgl content directly to the screen to improve performance in those browsers. - * ViewManager takes care of toggling this behavior. - * @internal - */ - public get rendersToScreen(): boolean { return undefined !== this._webglCanvas; } - public set rendersToScreen(toScreen: boolean) { - if (toScreen === this.rendersToScreen) - return; - - // Returns a webgl canvas if we're rendering webgl directly to the screen. - const webglCanvas = this.target.setRenderToScreen(toScreen); - if (undefined === webglCanvas) { - assert(undefined !== this._webglCanvas); // see getter... - this.vpDiv.removeChild(this._webglCanvas); - this._webglCanvas = undefined; - } else { - assert(undefined === this._webglCanvas); // see getter... - this._webglCanvas = webglCanvas; - - this.addChildDiv(this.vpDiv, webglCanvas, 5); - - /** We really want this WebGL canvas' zIndex to be lower than this.canvas, but if we do that, browsers can decide to - * not update the WebGL canvas contents once it is re-added to the parent div after dropping other viewports. - * The offending element is the 2d canvas sitting on top of the WebGL canvas. We need to clear the 2d canvas' contents - * in order to ensure browsers allow the underlying WebGL canvas to update. If a decorator is present, the 2d canvas - * is cleared during the frame render process by virtue of updating the decorator. For the non-decorator case, and for - * iOS, we must make sure we still clear the 2d canvas, done here. iOS appears to need this clear even when decorators - * clear the canvas later in the frame render process. - */ - _clear2dCanvas(this.canvas); - } - - this.target.updateViewRect(); - this.invalidateRenderPlan(); - } -} - -function _clear2dCanvas(canvas: HTMLCanvasElement) { - const ctx = canvas.getContext("2d", { alpha: true })!; - ctx.save(); - ctx.setTransform(1, 0, 0, 1, 0, 0); // revert any previous devicePixelRatio scale for clearRect() call below. - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.restore(); -} - -/** Options supplied when creating an [[OffScreenViewport]]. - * @see [[OffScreenViewport.create]]. - * @public - */ -export interface OffScreenViewportOptions { - /** The view to be drawn in the viewport. */ - view: ViewState; - /** The dimensions of the viewport. */ - viewRect: ViewRect; - /** If true, the viewport's aspect ratio will remain fixed. */ - lockAspectRatio?: boolean; -} - -/** A viewport that draws to an offscreen buffer instead of to the screen. An offscreen viewport is never added to the [[ViewManager]], therefore does not participate in - * the render loop. Its dimensions are specified directly instead of being derived from an HTMLCanvasElement, and its renderFrame function must be manually invoked. - * Offscreen viewports can be useful for, e.g., producing an image from the contents of a view (see [[Viewport.readImageBuffer]] and [[Viewport.readImageToCanvas]]) - * without drawing to the screen. - * @public - */ -export class OffScreenViewport extends Viewport { - protected _isAspectRatioLocked = false; - /** @internal see AttachToViewportArgs.drawingToSheetTransform. */ - private _drawingToSheetTransform?: Transform; - /** @internal see AttachToViewportArgs.drawingToSheetTransform. */ - public get drawingToSheetTransform(): Transform | undefined { - return this._drawingToSheetTransform; - } - public set drawingToSheetTransform(transform: Transform | undefined) { - this.detachFromView(); - this._drawingToSheetTransform = transform; - this.attachToView(); - } - - public static create(options: OffScreenViewportOptions): OffScreenViewport { - return this.createViewport(options.view, IModelApp.renderSystem.createOffscreenTarget(options.viewRect), options.lockAspectRatio); - } - - /** @internal because RenderTarget is internal */ - public static createViewport(view: ViewState, target: RenderTarget, lockAspectRatio = false): OffScreenViewport { - const vp = new this(target); - vp._isAspectRatioLocked = lockAspectRatio; - vp.changeView(view); - vp._decorationsValid = true; - return vp; - } - - /** @internal */ - public override get isAspectRatioLocked(): boolean { - return this._isAspectRatioLocked; - } - - /** @internal */ - public override get viewRect(): ViewRect { - return this.target.viewRect; - } - - /** Change the dimensions of the viewport. */ - public setRect(rect: ViewRect): void { - this.target.setViewRect(rect, false); - this.changeView(this.view); - } -} +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Views + */ + +import { + asInstanceOf, assert, BeDuration, BeEvent, BeTimePoint, Constructor, dispose, Id64, Id64Arg, Id64Set, Id64String, IDisposable, isInstanceOf, + StopWatch, +} from "@itwin/core-bentley"; +import { + Angle, AngleSweep, Arc3d, Geometry, LowAndHighXY, LowAndHighXYZ, Map4d, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point4d, Range1d, + Range3d, Ray3d, Transform, Vector3d, XAndY, XYAndZ, XYZ, +} from "@itwin/core-geometry"; +import { + AnalysisStyle, BackgroundMapProps, BackgroundMapProviderProps, BackgroundMapSettings, Camera, ClipStyle, ColorDef, DisplayStyleSettingsProps, Easing, + ElementProps, FeatureAppearance, Frustum, GlobeMode, GridOrientationType, Hilite, ImageBuffer, Interpolation, + isPlacement2dProps, LightSettings, MapLayerSettings, Npc, NpcCenter, Placement, Placement2d, Placement3d, PlacementProps, + SolarShadowSettings, SubCategoryAppearance, SubCategoryOverride, ViewFlags, +} from "@itwin/core-common"; +import { AuxCoordSystemState } from "./AuxCoordSys"; +import { BackgroundMapGeometry } from "./BackgroundMapGeometry"; +import { ChangeFlag, ChangeFlags, MutableChangeFlags } from "./ChangeFlags"; +import { CoordSystem } from "./CoordSystem"; +import { DecorationsCache } from "./DecorationsCache"; +import { DisplayStyleState } from "./DisplayStyleState"; +import { ElementPicker, LocateOptions } from "./ElementLocateManager"; +import { FeatureOverrideProvider } from "./FeatureOverrideProvider"; +import { FrustumAnimator } from "./FrustumAnimator"; +import { GlobeAnimator } from "./GlobeAnimator"; +import { HitDetail, SnapDetail } from "./HitDetail"; +import { IModelApp } from "./IModelApp"; +import { IModelConnection } from "./IModelConnection"; +import { linePlaneIntersect } from "./LinePlaneIntersect"; +import { ToolTipOptions } from "./NotificationManager"; +import { PerModelCategoryVisibility } from "./PerModelCategoryVisibility"; +import { Decorations } from "./render/Decorations"; +import { FeatureSymbology } from "./render/FeatureSymbology"; +import { FrameStats, FrameStatsCollector } from "./render/FrameStats"; +import { GraphicType } from "./render/GraphicBuilder"; +import { Pixel } from "./render/Pixel"; +import { GraphicList } from "./render/RenderGraphic"; +import { RenderMemory } from "./render/RenderMemory"; +import { createRenderPlanFromViewport } from "./render/RenderPlan"; +import { RenderTarget } from "./render/RenderTarget"; +import { StandardView, StandardViewId } from "./StandardView"; +import { SubCategoriesCache } from "./SubCategoriesCache"; +import { + DisclosedTileTreeSet, MapFeatureInfo, MapLayerFeatureInfo, MapLayerImageryProvider, MapTiledGraphicsProvider, MapTileTreeReference, TileBoundingBoxes, TiledGraphicsProvider, TileTreeReference, TileUser, +} from "./tile/internal"; +import { EventController } from "./tools/EventController"; +import { ToolSettings } from "./tools/ToolSettings"; +import { Animator, MarginOptions, OnViewExtentsError, ViewAnimationOptions, ViewChangeOptions } from "./ViewAnimation"; +import { DecorateContext, SceneContext } from "./ViewContext"; +import { GlobalLocation } from "./ViewGlobalLocation"; +import { ViewingSpace } from "./ViewingSpace"; +import { ViewPose } from "./ViewPose"; +import { ViewRect } from "./ViewRect"; +import { ModelDisplayTransformProvider, ViewState } from "./ViewState"; +import { ViewStatus } from "./ViewStatus"; +import { queryVisibleFeatures, QueryVisibleFeaturesCallback, QueryVisibleFeaturesOptions } from "./render/VisibleFeature"; +import { FlashSettings } from "./FlashSettings"; + +// cSpell:Ignore rect's ovrs subcat subcats unmounting UI's + +/** Interface for drawing [[Decorations]] into, or on top of, a [[ScreenViewport]]. + * @public + */ +export interface ViewportDecorator { + /** Override to enable cached decorations for this decorator. + * By default, a decorator is asked to recreate its decorations from scratch via its [[decorate]] method whenever the viewport's decorations are invalidated. + * Decorations become invalidated for a variety of reasons, including when the scene changes and when the mouse moves. + * Most decorators care only about when the scene changes, and may create decorations that are too expensive to recreate on every mouse motion. + * If `useCachedDecorations` is true, then the viewport will cache the most-recently-created decorations for this decorator, and only invoke its [[decorate]] method if it has no cached decorations for it. + * The cached decorations are discarded: + * - Whenever the scene changes; and + * - When the decorator explicitly requests it via [[Viewport.invalidateCachedDecorations]] or [[ViewManager.invalidateCachedDecorationsAllViews]]. + * The decorator should invoke the latter when the criteria governing its decorations change. + */ + readonly useCachedDecorations?: true; + + /** Implement this method to add [[Decorations]] into the supplied DecorateContext. + * @see [[useCachedDecorations]] to avoid unnecessarily recreating decorations. + */ + decorate(context: DecorateContext): void; +} + +/** Source of depth point returned by [[Viewport.pickDepthPoint]]. + * @public + */ +export enum DepthPointSource { + /** Depth point from geometry within specified radius of pick point */ + Geometry, // eslint-disable-line @typescript-eslint/no-shadow + /** Depth point from reality model within specified radius of pick point */ + Model, + /** Depth point from ray projection to background map plane */ + BackgroundMap, + /** Depth point from ray projection to ground plane */ + GroundPlane, + /** Depth point from ray projection to grid plane */ + Grid, + /** Depth point from ray projection to acs plane */ + ACS, + /** Depth point from plane passing through view target point */ + TargetPoint, + /** Depth point from map/terrain within specified radius of pick point */ + Map, +} + +/** Options to control behavior of [[Viewport.pickDepthPoint]]. + * @public + */ +export interface DepthPointOptions { + /** If true, geometry with the "non-locatable" flag set will not be selected. */ + excludeNonLocatable?: boolean; + /** If true, geometry from pickable decorations will not be selected. */ + excludeDecorations?: boolean; + /** If true, geometry from an IModelConnection other than the one associated with the Viewport will not be selected. */ + excludeExternalIModels?: boolean; +} + +/** The minimum and maximum values for the z-depth of a rectangle of screen space. + * Values are in [[CoordSystem.Npc]] so they will be between 0 and 1.0. + * @public + */ +export interface DepthRangeNpc { + /** The value closest to the back. */ + minimum: number; + /** The value closest to the front. */ + maximum: number; +} + +/** Options to allow changing the view rotation with zoomTo methods. + * @public + */ +export interface ZoomToOptions { + /** Set view rotation from standard view identifier. */ + standardViewId?: StandardViewId; + /** Set view rotation relative to placement of first element or props entry. */ + placementRelativeId?: StandardViewId; + /** Set view rotation from Matrix3d. */ + viewRotation?: Matrix3d; +} + +/** Options for changing the viewed Model of a 2d view via [[Viewport.changeViewedModel2d]] + * @public + */ +export interface ChangeViewedModel2dOptions { + /** If true, perform a "fit view" operation after changing to the new 2d model. */ + doFit?: boolean; +} + +/** Describes an undo or redo event for a [[Viewport]]. + * @see [[Viewport.onViewUndoRedo]]. + * @public + */ +export enum ViewUndoEvent { Undo = 0, Redo = 1 } + +/** @internal */ +export const ELEMENT_MARKED_FOR_REMOVAL = Symbol.for("@bentley/imodeljs/Viewport/__element_marked_for_removal__"); + +declare global { + interface Element { + [ELEMENT_MARKED_FOR_REMOVAL]?: boolean; + } +} + +/** Payload for the [[Viewport.onFlashedIdChanged]] event indicating Ids of the currently- and/or previously-flashed objects. + * @public + */ +export type OnFlashedIdChangedEventArgs = { + readonly current: Id64String; + readonly previous: Id64String; +} | { + readonly current: Id64String; + readonly previous: undefined; +} | { + readonly previous: Id64String; + readonly current: undefined; +}; + +/** Arguments to [[Viewport.getPixelDataWorldPoint]]. + * @public + */ +export interface GetPixelDataWorldPointArgs { + /** The buffer containing the pixel data. @see [[Viewport.readPixels]]. */ + pixels: Pixel.Buffer; + /** The x coordinate of the pixel of interest, in view coordinates. */ + x: number; + /** The y coordinate of the pixel of interest, in view coordinates. */ + y: number; + /** If true, then the world point of a pixel associated with a model will preserve any transforms applied to the model at display time, + * such as those supplied by a [[ModelDisplayTransformProvider]] or [PlanProjectionSettings.elevation]($common). + * Otherwise, the world point will be multiplied by the inverse of any such transforms to correlate it with the model's true coordinate space. + */ + preserveModelDisplayTransforms?: boolean; + /** If supplied, this point will be modified to store the returned point, instead of allocating a new point. */ + out?: Point3d; +} + +/** Arguments supplied to [[Viewport.readImageBuffer]]. + * @public + */ +export interface ReadImageBufferArgs { + /** The region of the viewport's [[ViewRect]] to capture. It must be fully contained within [[Viewport.viewRect]]. + * If unspecified, the entirety of the viewport's view rect is captured. + */ + rect?: ViewRect; + /** Optional dimensions to which to resize the captured image. If the aspect ratio of these dimensions does not match that of the captured image, + * horizontal or vertical bars will be added to the resized image using the viewport's background color. + * If unspecified, the image will not be resized. + */ + size?: XAndY; + /** The image captured by WebGL appears "upside-down" and must be flipped to appear right-side-up; if true, this flipping will not be performed. + * This provides a performance optimization for uncommon cases in which an upside-down image is actually preferred. + */ + upsideDown?: boolean; +} + +/** A Viewport renders the contents of one or more [GeometricModel]($backend)s onto an `HTMLCanvasElement`. + * + * It holds a [[ViewState]] object that defines its viewing parameters; the ViewState in turn defines the [[DisplayStyleState]], + * [[CategorySelectorState]], and - for [[SpatialViewState]]s - the [[ModelSelectorState]]. While a ViewState is being displayed by a Viewport, + * it is considered to be "attached" to that viewport; it remains attached until the Viewport is disposed of or becomes attached to a different ViewState. + * While the ViewState is attached to a Viewport, any changes made to the ViewState or its display style or category/model selectors will be automatically + * reflected in the Viewport. A ViewState can be attached to no more than one Viewport at a time. + * + * As changes to ViewState are made, Viewports also hold a stack of *previous copies* of it, to allow + * for undo/redo (i.e. *View Previous* and *View Next*) of viewing tools. + * + * Changes to a Viewport's state can be monitored by attaching an event listener to a variety of specific events. Most such events are + * triggered only once per frame, just before the Viewport's contents are rendered. For example, if the following sequence of events occurs: + * + * * First frame is rendered + * * ViewFlags are modified + * * ViewFlags are modified again + * * Second frame is rendered + * + * The [[Viewport.onDisplayStyleChanged]] event will be invoked exactly once, when the second frame is rendered. + * + * @see [[ViewManager]] + * @public + */ +export abstract class Viewport implements IDisposable, TileUser { + /** Event called whenever this viewport is synchronized with its [[ViewState]]. + * @note This event is invoked *very* frequently. To avoid negatively impacting performance, consider using one of the more specific Viewport events; + * otherwise, avoid performing excessive computations in response to this event. + * @see [[onViewportChanged]] for receiving events at more regular intervals with more specific information about what changed. + * @see [[onChangeView]] for an event raised specifically when a different [[ViewState]] becomes associated with the viewport. + */ + public readonly onViewChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called after reversing the most recent change to the Viewport from the undo stack or reapplying the + * most recently undone change to the Viewport from the redo stack. + */ + public readonly onViewUndoRedo = new BeEvent<(vp: Viewport, event: ViewUndoEvent) => void>(); + /** Event called on the next frame after this viewport's set of always-drawn elements changes. */ + public readonly onAlwaysDrawnChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's set of never-drawn elements changes. */ + public readonly onNeverDrawnChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's [[DisplayStyleState]] or its members change. + * Aspects of the display style include [ViewFlags]($common), [SubCategoryOverride]($common)s, and [[Environment]] settings. + */ + public readonly onDisplayStyleChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's set of displayed categories changes. */ + public readonly onViewedCategoriesChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's set of [[PerModelCategoryVisibility.Overrides]] changes. */ + public readonly onViewedCategoriesPerModelChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's set of displayed models changes. */ + public readonly onViewedModelsChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's [[FeatureOverrideProvider]] changes, + * or the internal state of the provider changes such that the overrides needed to be recomputed. + */ + public readonly onFeatureOverrideProviderChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after this viewport's [[FeatureSymbology.Overrides]] change. */ + public readonly onFeatureOverridesChanged = new BeEvent<(vp: Viewport) => void>(); + /** Event called on the next frame after any of the viewport's [[ChangeFlags]] changes. */ + public readonly onViewportChanged = new BeEvent<(vp: Viewport, changed: ChangeFlags) => void>(); + /** Event invoked immediately when [[changeView]] is called to replace the current [[ViewState]] with a different one. */ + public readonly onChangeView = new BeEvent<(vp: Viewport, previousViewState: ViewState) => void>(); + /** Event invoked immediately when the viewport is disposed. + * @see [[Viewport.dispose]]. + */ + public readonly onDisposed = new BeEvent<(vp: Viewport) => void>(); + /** Event invoked after [[renderFrame]] detects that the dimensions of the viewport's [[ViewRect]] have changed. + */ + public readonly onResized = new BeEvent<(vp: Viewport) => void>(); + /** Event dispatched immediately after [[flashedId]] changes, supplying the Ids of the previously and/or currently-flashed objects. + * @note Attempting to assign to [[flashedId]] from within the event callback will produce an exception. + */ + public readonly onFlashedIdChanged = new BeEvent<(vp: Viewport, args: OnFlashedIdChangedEventArgs) => void>(); + + /** This is initialized by a call to [[changeView]] sometime shortly after the constructor is invoked. + * During that time it can be undefined. DO NOT assign directly to this member - use `setView()`. + */ + private _view!: ViewState; + /** A function executed by `setView()` when `this._view` changes. */ + private readonly _detachFromView: VoidFunction[] = []; + private readonly _detachFromDisplayStyle: VoidFunction[] = []; + + private readonly _viewportId: number; + private _doContinuousRendering = false; + /** @internal */ + protected _inViewChangedEvent = false; + /** @internal */ + protected _decorationsValid = false; + /** @internal */ + protected _sceneValid = false; + /** @internal */ + public get sceneValid() { return this._sceneValid; } + /** @internal */ + protected _renderPlanValid = false; + /** @internal */ + public get renderPlanValid() { return this._renderPlanValid; } + /** @internal */ + public setRenderPlanValid() { this._renderPlanValid = true; } + /** @internal */ + protected _controllerValid = false; + /** @internal */ + public get controllerValid() { return this._controllerValid; } + private _redrawPending = false; + private _analysisFractionValid = false; + /** @internal */ + public get analysisFractionValid() { return this._analysisFractionValid; } + private _timePointValid = false; + /** @internal */ + public get timePointValid() { return this._timePointValid; } + + /** Strictly for tests. @internal */ + public setAllValid(): void { + this._sceneValid = this._decorationsValid = this._renderPlanValid = this._controllerValid = this._redrawPending + = this._analysisFractionValid = this._timePointValid = true; + } + + /** Mark the current set of decorations invalid, so that they will be recreated on the next render frame. + * This can be useful, for example, if an external event causes one or more current decorations to become invalid and you wish to force + * them to be recreated to show the changes. + * @note On the next frame, the `decorate` method of all [[ViewManager.decorators]] will be called. There is no way (or need) to + * invalidate individual decorations. + */ + public invalidateDecorations(): void { + this._decorationsValid = false; + IModelApp.requestNextAnimation(); + } + + /** Mark the viewport's scene as invalid, so that the next call to [[renderFrame]] will recreate it. + * This method is not typically invoked directly - the scene is automatically invalidated in response to events such as moving the viewing frustum, + * changing the set of viewed models, new tiles being loaded, etc. + */ + public invalidateScene(): void { + this._sceneValid = false; + this._timePointValid = false; + this.invalidateDecorations(); + } + + /** @internal */ + public invalidateRenderPlan(): void { + this._renderPlanValid = false; + this.invalidateScene(); + } + + /** @internal */ + public invalidateController(): void { + this._controllerValid = this._analysisFractionValid = false; + this.invalidateRenderPlan(); + } + + /** @internal */ + public setValidScene() { + this._sceneValid = true; + } + + /** Request that the Viewport redraw its contents on the next frame. This is useful when some state outside of the Viewport's control but affecting its display has changed. + * For example, if the parameters affecting a screen-space effect applied to this Viewport are modified, the Viewport's contents should be redrawn to reflect the change. + * @note This does not necessarily cause the viewport to recreate its scene, decorations, or anything else - it only guarantees that the contents will be repainted. + */ + public requestRedraw(): void { + this._redrawPending = true; + IModelApp.requestNextAnimation(); + } + + private _animator?: Animator; + /** @internal */ + protected _changeFlags = new MutableChangeFlags(); + private _selectionSetDirty = true; + private readonly _perModelCategoryVisibility: PerModelCategoryVisibility.Overrides; + private _tileSizeModifier?: number; + + /** @internal */ + public readonly subcategories = new SubCategoriesCache.Queue(); + + /** Time the current flash started. */ + private _flashUpdateTime?: BeTimePoint; + /** Current flash intensity from [0..this.flashSettings.maxIntensity] */ + private _flashIntensity = 0; + /** Id of the currently flashed element. */ + private _flashedElem?: string; + /** Id of last flashed element. */ + private _lastFlashedElem?: string; + /** The Id of the most recently flashed element, if any. */ + public get lastFlashedElementId(): Id64String | undefined { + return this._lastFlashedElem; + } + + private _wantViewAttachments = true; + /** For debug purposes, controls whether or not view attachments are displayed in sheet views. + * @internal + */ + public get wantViewAttachments() { return this._wantViewAttachments; } + public set wantViewAttachments(want: boolean) { + if (want !== this._wantViewAttachments) { + this._wantViewAttachments = want; + this.invalidateScene(); + } + } + + private _wantViewAttachmentBoundaries = false; + /** For debug purposes, controls whether or not the boundary of each view attachment is displayed in a sheet view. + * @internal + */ + public get wantViewAttachmentBoundaries() { return this._wantViewAttachmentBoundaries; } + public set wantViewAttachmentBoundaries(want: boolean) { + if (want !== this._wantViewAttachmentBoundaries) { + this._wantViewAttachmentBoundaries = want; + this.invalidateScene(); + } + } + + private _wantViewAttachmentClipShapes = false; + /** For debug purposes, controls whether or not graphics representing the clipping shapes of each view attachment are displayed in a sheet view. + * @internal + */ + public get wantViewAttachmentClipShapes() { return this._wantViewAttachmentClipShapes; } + public set wantViewAttachmentClipShapes(want: boolean) { + if (want !== this._wantViewAttachmentClipShapes) { + this._wantViewAttachmentClipShapes = want; + this.invalidateScene(); + } + } + + /** Don't allow entries in the view undo buffer unless they're separated by more than this amount of time. */ + public static undoDelay = BeDuration.fromSeconds(.5); + + private _debugBoundingBoxes: TileBoundingBoxes = TileBoundingBoxes.None; + private _freezeScene = false; + private _viewingSpace!: ViewingSpace; + private _target?: RenderTarget; + private _fadeOutActive = false; + private _neverDrawn?: Id64Set; + private _alwaysDrawn?: Id64Set; + private _alwaysDrawnExclusive: boolean = false; + private readonly _featureOverrideProviders: FeatureOverrideProvider[] = []; + private readonly _tiledGraphicsProviders = new Set(); + private _mapTiledGraphicsProvider?: MapTiledGraphicsProvider; + private _hilite = new Hilite.Settings(); + private _emphasis = new Hilite.Settings(ColorDef.black, 0, 0, Hilite.Silhouette.Thick); + private _flash = new FlashSettings(); + + /** @see [DisplayStyle3dSettings.lights]($common) */ + public get lightSettings(): LightSettings | undefined { + return this.displayStyle.is3d() ? this.displayStyle.settings.lights : undefined; + } + public setLightSettings(settings: LightSettings) { + if (this.displayStyle.is3d()) + this.displayStyle.settings.lights = settings; + } + + /** @see [DisplayStyle3dSettings.solarShadows]($common) */ + public get solarShadowSettings(): SolarShadowSettings | undefined { + return this.view.displayStyle.is3d() ? this.view.displayStyle.settings.solarShadows : undefined; + } + public setSolarShadowSettings(settings: SolarShadowSettings) { + if (this.view.displayStyle.is3d()) + this.view.displayStyle.solarShadows = settings; + } + + /** @public */ + public get viewingSpace(): ViewingSpace { return this._viewingSpace; } + + /** This viewport's rotation matrix. */ + public get rotation(): Matrix3d { return this._viewingSpace.rotation; } + /** The vector between the opposite corners of this viewport's extents. */ + public get viewDelta(): Vector3d { return this._viewingSpace.viewDelta; } + /** Provides conversions between world and view coordinates. */ + public get worldToViewMap(): Map4d { return this._viewingSpace.worldToViewMap; } + /** Provides conversions between world and Npc (non-dimensional perspective) coordinates. */ + public get worldToNpcMap(): Map4d { return this._viewingSpace.worldToNpcMap; } + /** @internal */ + public get frustFraction(): number { return this._viewingSpace.frustFraction; } + + /** @see [DisplayStyleSettings.analysisFraction]($common). */ + public get analysisFraction(): number { + return this.displayStyle.settings.analysisFraction; + } + public set analysisFraction(fraction: number) { + this.displayStyle.settings.analysisFraction = fraction; + } + + /** @see [DisplayStyleSettings.timePoint]($common) */ + public get timePoint(): number | undefined { + return this.displayStyle.settings.timePoint; + } + public set timePoint(time: number | undefined) { + this.displayStyle.settings.timePoint = time; + } + + /** @internal */ + protected readonly _viewRange: ViewRect = new ViewRect(); + + /** Get the rectangle of this Viewport in [[CoordSystem.View]] coordinates. */ + public abstract get viewRect(): ViewRect; + /** @internal */ + public get isAspectRatioLocked(): boolean { return false; } + + /** @internal */ + public get target(): RenderTarget { + assert(undefined !== this._target, "Accessing RenderTarget of a disposed Viewport"); + return this._target; + } + + /** Returns true if this Viewport's [[dispose]] method has been invoked. It is an error to attempt to interact with a disposed Viewport. + * Typically a [[ScreenViewport]] becomes disposed as a result of a call to [[ViewManager.dropViewport]], often indirectly through the unmounting of a nine-zone UI's [[ViewportComponent]] when, e.g., switching front-stages. + * @public + */ + public get isDisposed(): boolean { + return undefined === this._target; + } + + /** The settings that control how elements are hilited in this Viewport. */ + public get hilite(): Hilite.Settings { return this._hilite; } + public set hilite(hilite: Hilite.Settings) { + this._hilite = hilite; + this.invalidateRenderPlan(); + } + + /** The settings that control how emphasized elements are displayed in this Viewport. The default settings apply a thick black silhouette to the emphasized elements. + * @see [FeatureAppearance.emphasized]($common). + */ + public get emphasisSettings(): Hilite.Settings { return this._emphasis; } + public set emphasisSettings(settings: Hilite.Settings) { + this._emphasis = settings; + this.invalidateRenderPlan(); + } + + /** The settings that control how elements are flashed in this viewport. */ + public get flashSettings(): FlashSettings { + return this._flash; + } + public set flashSettings(settings: FlashSettings) { + this._flash = settings; + this.invalidateRenderPlan(); + } + + /** Determine whether the Grid display is currently enabled in this Viewport. + * @return true if the grid display is on. + */ + public get isGridOn(): boolean { return this.viewFlags.grid; } + + /** Flags controlling aspects of how the contents of this viewport are rendered. + * @see [DisplayStyleSettings.viewFlags]($common). + */ + public get viewFlags(): ViewFlags { return this.view.viewFlags; } + public set viewFlags(viewFlags: ViewFlags) { + this.view.displayStyle.viewFlags = viewFlags; + } + + /** @see [[ViewState.displayStyle]] */ + public get displayStyle(): DisplayStyleState { return this.view.displayStyle; } + public set displayStyle(style: DisplayStyleState) { + this.view.displayStyle = style; + } + + /** Selectively override aspects of this viewport's display style. + * @see [DisplayStyleSettings.applyOverrides]($common) + */ + public overrideDisplayStyle(overrides: DisplayStyleSettingsProps): void { + this.displayStyle.settings.applyOverrides(overrides); + } + + /** @see [DisplayStyleSettings.clipStyle]($common) */ + public get clipStyle(): ClipStyle { return this.displayStyle.settings.clipStyle; } + public set clipStyle(style: ClipStyle) { + this.displayStyle.settings.clipStyle = style; + } + + /** Sets the number of [MSAA]($docs/learning/display/MSAA.md) samples for this viewport. + * The number of samples is a power of two. Values of 1 or less indicates anti-aliasing should be disabled. Non-power-of-two values are rounded + * down to the nearest power of two. The maximum number of samples supported depends upon the client's graphics hardware capabilities. Higher values produce + * a higher-quality image but also may also reduce framerate. + * @see [[ViewManager.setAntialiasingAllViews]] to adjust the number of samples for all viewports. + */ + public get antialiasSamples(): number { + return undefined !== this._target ? this._target.antialiasSamples : 1; + } + public set antialiasSamples(numSamples: number) { + if (undefined !== this._target) { + this._target.antialiasSamples = numSamples; + this.invalidateRenderPlan(); + } + } + + /** return true if viewing globe (globeMode is 3D and eye location is far above globe + * @alpha + */ + public get viewingGlobe() { + const view = this.view; + if (!view.is3d()) + return false; + + return this.displayStyle.globeMode === GlobeMode.Ellipsoid && view.isGlobalView; + } + + /** Remove any [[SubCategoryOverride]] for the specified subcategory. + * @param id The Id of the subcategory. + * @see [[overrideSubCategory]] + */ + public dropSubCategoryOverride(id: Id64String): void { + this.view.displayStyle.dropSubCategoryOverride(id); + } + + /** Override the symbology of geometry belonging to a specific subcategory when rendered within this viewport. + * @param id The Id of the subcategory. + * @param ovr The symbology overrides to apply to all geometry belonging to the specified subcategory. + * @see [[dropSubCategoryOverride]] + */ + public overrideSubCategory(id: Id64String, ovr: SubCategoryOverride): void { + this.view.displayStyle.overrideSubCategory(id, ovr); + } + + /** Query the symbology overrides applied to geometry belonging to a specific subcategory when rendered within this viewport. + * @param id The Id of the subcategory. + * @return The symbology overrides applied to all geometry belonging to the specified subcategory, or undefined if no such overrides exist. + * @see [[overrideSubCategory]] + */ + public getSubCategoryOverride(id: Id64String): SubCategoryOverride | undefined { + return this.view.displayStyle.getSubCategoryOverride(id); + } + + /** Query the symbology with which geometry belonging to a specific subcategory is rendered within this viewport. + * Every [[SubCategory]] defines a base symbology independent of any [[Viewport]]. + * If a [[SubCategoryOverride]] has been applied to the subcategory within the context of this [[Viewport]], it will be applied to the subcategory's base symbology. + * @param id The Id of the subcategory. + * @return The symbology of the subcategory within this viewport, including any overrides. + * @see [[overrideSubCategory]] + */ + public getSubCategoryAppearance(id: Id64String): SubCategoryAppearance { + const app = this.iModel.subcategories.getSubCategoryAppearance(id); + if (undefined === app) + return SubCategoryAppearance.defaults; + + const ovr = this.getSubCategoryOverride(id); + return undefined !== ovr ? ovr.override(app) : app; + } + + /** Determine whether geometry belonging to a specific SubCategory is visible in this viewport, assuming the containing Category is displayed. + * @param id The Id of the subcategory + * @returns true if the subcategory is visible in this viewport. + * @note Because this function does not know the Id of the containing Category, it does not check if the Category is enabled for display. The caller should check that separately if he knows the Id of the Category. + */ + public isSubCategoryVisible(id: Id64String): boolean { return this.view.isSubCategoryVisible(id); } + + /** Override the appearance of a model when rendered within this viewport. + * @param id The Id of the model. + * @param ovr The symbology overrides to apply to all geometry belonging to the specified subcategory. + * @see [DisplayStyleSettings.overrideModelAppearance]($common) + */ + public overrideModelAppearance(id: Id64String, ovr: FeatureAppearance): void { + this.view.displayStyle.settings.overrideModelAppearance(id, ovr); + } + + /** Remove any model appearance override for the specified model. + * @param id The Id of the model. + * @see [DisplayStyleSettings.dropModelAppearanceOverride]($common) + */ + public dropModelAppearanceOverride(id: Id64String): void { + this.view.displayStyle.settings.dropModelAppearanceOverride(id); + } + + /** Some changes may or may not require us to invalidate the scene. + * Specifically, when shadows are enabled or we are displaying view attachments, the following changes may affect the visibility or transparency of elements or features: + * - Viewed categories and subcategories; + * - Always/never drawn elements + * - Symbology overrides. + */ + private maybeInvalidateScene(): void { + // When shadows are being displayed and the set of displayed categories changes, we must invalidate the scene so that shadows will be regenerated. + // Same occurs when changing feature symbology overrides (e.g., always/never-drawn element sets, transparency override) + if (!this._sceneValid) + return; + + if (this.view.displayStyle.wantShadows || this.view.isSheetView()) + this.invalidateScene(); + } + + /** Enable or disable display of elements belonging to a set of categories specified by Id. + * Visibility of individual subcategories belonging to a category can be controlled separately through the use of [[SubCategoryOverride]]s. + * By default, enabling display of a category does not affect display of subcategories thereof which have been overridden to be invisible. + * @param categories The Id(s) of the categories to which the change should be applied. No other categories will be affected. + * @param display Whether or not elements on the specified categories should be displayed in the viewport. + * @param enableAllSubCategories Specifies that when enabling display for a category, all of its subcategories should also be displayed even if they are overridden to be invisible. + */ + public changeCategoryDisplay(categories: Id64Arg, display: boolean, enableAllSubCategories: boolean = false): void { + if (!display) { + this.view.categorySelector.dropCategories(categories); + return; + } + + this.view.categorySelector.addCategories(categories); + const categoryIds = Id64.toIdSet(categories); + + this.updateSubCategories(categoryIds, enableAllSubCategories); + } + + private updateSubCategories(categoryIds: Id64Arg, enableAllSubCategories: boolean): void { + this.subcategories.push(this.iModel.subcategories, categoryIds, () => { + if (enableAllSubCategories) + this.enableAllSubCategories(categoryIds); + + this._changeFlags.setViewedCategories(); + }); + } + + private enableAllSubCategories(categoryIds: Id64Arg): void { + for (const categoryId of Id64.iterable(categoryIds)) { + const subCategoryIds = this.iModel.subcategories.getSubCategories(categoryId); + if (undefined !== subCategoryIds) { + for (const subCategoryId of subCategoryIds) + this.changeSubCategoryDisplay(subCategoryId, true); + } + } + } + + /** @internal */ + public getSubCategories(categoryId: Id64String): Id64Set | undefined { return this.iModel.subcategories.getSubCategories(categoryId); } + + /** Change the visibility of geometry belonging to the specified subcategory when displayed in this viewport. + * @param subCategoryId The Id of the subcategory + * @param display: True to make geometry belonging to the subcategory visible within this viewport, false to make it invisible. + */ + public changeSubCategoryDisplay(subCategoryId: Id64String, display: boolean): void { + const app = this.iModel.subcategories.getSubCategoryAppearance(subCategoryId); + if (undefined === app) + return; // category not enabled or subcategory not found + + const curOvr = this.getSubCategoryOverride(subCategoryId); + const isAlreadyVisible = undefined !== curOvr && undefined !== curOvr.invisible ? !curOvr.invisible : !app.invisible; + if (isAlreadyVisible === display) + return; + + // Preserve existing overrides - just flip the visibility flag. + const json = undefined !== curOvr ? curOvr.toJSON() : {}; + json.invisible = !display; + this.overrideSubCategory(subCategoryId, SubCategoryOverride.fromJSON(json)); // will set the ChangeFlag appropriately + this.maybeInvalidateScene(); + } + + /** The settings controlling how a background map is displayed within a view. + * @see [[ViewFlags.backgroundMap]] for toggling display of the map on or off. + * @see [DisplayStyleSettings.backgroundMap]($common) + */ + public get backgroundMapSettings(): BackgroundMapSettings { return this.displayStyle.backgroundMapSettings; } + public set backgroundMapSettings(settings: BackgroundMapSettings) { + this.displayStyle.backgroundMapSettings = settings; + } + + /** @see [[DisplayStyleState.changeBackgroundMapProps]] */ + public changeBackgroundMapProps(props: BackgroundMapProps): void { + this.displayStyle.changeBackgroundMapProps(props); + } + + /** @see [[DisplayStyleState.changeBackgroundMapProvider]] */ + public changeBackgroundMapProvider(props: BackgroundMapProviderProps): void { + this.displayStyle.changeBackgroundMapProvider(props); + } + + /** @internal */ + public get backgroundMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundMap; } + + /** @internal */ + public get overlayMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.overlayMap; } + + /** @internal */ + public get backgroundDrapeMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundDrapeMap; } + + /** @internal */ + public getMapLayerImageryProvider(index: number, isOverlay: boolean): MapLayerImageryProvider | undefined { return this._mapTiledGraphicsProvider?.getMapLayerImageryProvider(index, isOverlay); } + + /** Returns true if this Viewport is currently displaying the model with the specified Id. */ + public viewsModel(modelId: Id64String): boolean { return this.view.viewsModel(modelId); } + + /** Attempt to change the 2d Model this Viewport is displaying, if its ViewState is a ViewState2d. + * @param baseModelId The Id of the new 2d Model to be displayed. + * @param options options that determine how the new view is displayed + * @note This function *only works* if the viewport is viewing a [[ViewState2d]], otherwise it does nothing. Also note that + * the Model of baseModelId should be the same type (Drawing or Sheet) as the current view. + * @note this method clones the current ViewState2d and sets its baseModelId to the supplied value. The DisplayStyle and CategorySelector remain unchanged. + */ + public async changeViewedModel2d(baseModelId: Id64String, options?: ChangeViewedModel2dOptions & ViewChangeOptions & MarginOptions): Promise { + if (!this.view.is2d()) + return; + + // Clone the current ViewState, change its baseModelId, and ensure the new model is loaded. + const newView = this.view.clone(); // start by cloning the current ViewState + await newView.changeViewedModel(baseModelId); + + this.changeView(newView, options); // switch this viewport to use new ViewState2d + + if (options && options.doFit) { // optionally fit view to the extents of the new model + const range = await this.iModel.models.queryModelRanges([baseModelId]); + this.zoomToVolume(Range3d.fromJSON(range[0]), options); + } + } + + /** Attempt to replace the set of models currently viewed by this viewport, if it is displaying a SpatialView + * @param modelIds The Ids of the models to be displayed. + * @returns false if this Viewport is not viewing a [[SpatialViewState]] + * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. + * @note This function *does not load* any models. If any of the supplied `modelIds` refers to a model that has not been loaded, no graphics will be loaded+displayed in the viewport for that model. + * @see [[replaceViewedModels]] for a similar function that also ensures the requested models are loaded. + */ + public changeViewedModels(modelIds: Id64Arg): boolean { + if (!this.view.isSpatialView()) + return false; + + this.view.modelSelector.models.clear(); + this.view.modelSelector.addModels(modelIds); + return true; + } + + /** Attempt to replace the set of models currently viewed by this viewport, if it is displaying a SpatialView + * @param modelIds The Ids of the models to be displayed. + * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. + * @note If any of the requested models is not yet loaded this function will asynchronously load them before updating the set of displayed models. + */ + public async replaceViewedModels(modelIds: Id64Arg): Promise { + if (this.view.isSpatialView()) { + this.view.modelSelector.models.clear(); + return this.addViewedModels(modelIds); + } + } + + /** Add or remove a set of models from those models currently displayed in this viewport. + * @param modelIds The Ids of the models to add or remove. + * @param display Whether or not to display the specified models in the viewport. + * @returns false if this Viewport is not viewing a [[SpatialViewState]] + * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. + * @note This function *does not load* any models. If `display` is `true` and any of the supplied `models` refers to a model that has not been loaded, no graphics will be loaded+displayed in the viewport for that model. + * @see [[addViewedModels]] for a similar function that also ensures the requested models are loaded. + */ + public changeModelDisplay(models: Id64Arg, display: boolean): boolean { + if (!this.view.isSpatialView()) + return false; + + if (display) + this.view.modelSelector.addModels(models); + else + this.view.modelSelector.dropModels(models); + + return true; + } + + /** Adds a set of models to the set of those currently displayed in this viewport. + * @param modelIds The Ids of the models to add or remove. + * @param display Whether or not to display the specified models in the viewport. + * @note This function *only works* if the viewport is viewing a [[SpatialViewState]], otherwise it does nothing. + * @note If any of the requested models is not yet loaded this function will asynchronously load them before updating the set of displayed models. + */ + public async addViewedModels(models: Id64Arg): Promise { + // NB: We want the model selector to update immediately, to avoid callers repeatedly requesting we load+display the same models while we are already loading them. + // This will also trigger scene invalidation and changed events. + if (!this.changeModelDisplay(models, true)) + return; // means it's a 2d model - this function can do nothing useful in 2d. + + const unloaded = this.iModel.models.filterLoaded(models); + if (undefined === unloaded) + return; + + // Need to redraw once models are available. Don't want to trigger events again. + await this.iModel.models.load(models); + this.invalidateScene(); + assert(this.view.isSpatialView()); + this.view.markModelSelectorChanged(); + } + + /** Determines what type (if any) of debug graphics will be displayed to visualize [[Tile]] volumes. Chiefly for debugging. + * @see [[TileBoundingBoxes]] + */ + public get debugBoundingBoxes(): TileBoundingBoxes { return this._debugBoundingBoxes; } + public set debugBoundingBoxes(boxes: TileBoundingBoxes) { + if (boxes !== this.debugBoundingBoxes) { + this._debugBoundingBoxes = boxes; + this.invalidateScene(); + } + } + /** When true, the scene will never be recreated. Chiefly for debugging purposes. + * @internal + */ + public get freezeScene(): boolean { return this._freezeScene; } + public set freezeScene(freeze: boolean) { + if (freeze !== this._freezeScene) { + this._freezeScene = freeze; + if (!freeze) + this.invalidateScene(); + } + } + + /** The iModel of this Viewport */ + public get iModel(): IModelConnection { return this.view.iModel; } + /** @internal */ + public get isPointAdjustmentRequired(): boolean { return this.view.is3d(); } + /** @internal */ + public get isSnapAdjustmentRequired(): boolean { return IModelApp.toolAdmin.acsPlaneSnapLock && this.view.is3d(); } + /** @internal */ + public get isContextRotationRequired(): boolean { return IModelApp.toolAdmin.acsContextLock; } + + /** Enables or disables "fade-out" mode. When this mode is enabled, transparent graphics are rendered with a flat alpha weight, + * causing them to appear de-emphasized. This is typically used in contexts in which a handful of elements are to be emphasized in the view, + * while the rest of the graphics are drawn transparently. + */ + public get isFadeOutActive(): boolean { return this._fadeOutActive; } + public set isFadeOutActive(active: boolean) { + if (active !== this._fadeOutActive) { + this._fadeOutActive = active; + this.invalidateRenderPlan(); + } + } + /** @internal */ + public async getToolTip(hit: HitDetail): Promise { + const promises = new Array>(); + if (this.displayStyle) { + this.displayStyle.forEachTileTreeRef(async (tree) => { + promises.push(tree.getToolTip(hit).catch(() => undefined)); + }); + } + this.forEachMapTreeRef(async (tree) => promises.push(tree.getToolTip(hit))); + + const results = await Promise.all(promises); + for (const result of results) + if (result !== undefined) + return result; + + return ""; + } + + /** @alpha */ + public async getMapFeatureInfo(hit: HitDetail): Promise { + const promises = new Array>(); + + // Execute 'getMapFeatureInfo' on every tree, and make sure to handle exception for each call, + // so that we get still get results even though a tree has failed. + this.forEachMapTreeRef(async (tree) => promises.push(tree.getMapFeatureInfo(hit).catch(() => undefined))); + const featureInfo: MapFeatureInfo = {}; + + const worldPoint = hit.hitPoint.clone(); + const backgroundMapGeometry = hit.viewport.displayStyle.getBackgroundMapGeometry(); + if (undefined !== backgroundMapGeometry) { + featureInfo.hitPoint = await backgroundMapGeometry.dbToCartographicFromGcs(worldPoint); + } + + const results = await Promise.all(promises); + for (const result of results) + if (result !== undefined) { + + if (featureInfo.layerInfo === undefined) { + featureInfo.layerInfo = []; + } + + featureInfo.layerInfo.push(...result); + } + return featureInfo; + } + + /** If this event has one or more listeners, collection of timing statistics related to rendering frames is enabled. Frame statistics will be received by the listeners whenever a frame is finished rendering. + * @note The timing data collected using this event only collects the amount of time spent on the CPU. Due to performance considerations, time spent on the GPU is not collected. Therefore, these statistics are not a direct mapping to user experience. + * @note In order to avoid interfering with the rendering loop, take care to avoid performing any intensive tasks in your event listeners. + * @see [[FrameStats]] + * @alpha + */ + public readonly onFrameStats = new BeEvent<(frameStats: Readonly) => void>(); + + private _frameStatsCollector = new FrameStatsCollector(this.onFrameStats); + + /** @internal */ + protected constructor(target: RenderTarget) { + this._target = target; + target.assignFrameStatsCollector(this._frameStatsCollector); + this._viewportId = TileUser.generateId(); + this._perModelCategoryVisibility = PerModelCategoryVisibility.createOverrides(this); + IModelApp.tileAdmin.registerUser(this); + } + + public dispose(): void { + if (this.isDisposed) + return; + + this._target = dispose(this._target); + this.subcategories.dispose(); + IModelApp.tileAdmin.forgetUser(this); + this.onDisposed.raiseEvent(this); + this.detachFromView(); + } + + private setView(view: ViewState): void { + if (view === this._view) + return; + + if (this._mapTiledGraphicsProvider) + this._mapTiledGraphicsProvider.setView(view); + this.detachFromView(); + this._view = view; + this.attachToView(); + } + + /** @internal Invoked when the viewport becomes associated with a new ViewState to register event listeners with the view + * and allow the ViewState to set up internal state that is only relevant when associated with a Viewport. + * Also invoked after changing OffScreenViewport.drawingToSheetTransform. + * @internal + */ + protected attachToView(): void { + this.registerDisplayStyleListeners(this.view.displayStyle); + this.registerViewListeners(); + this.view.attachToViewport(this); + this._mapTiledGraphicsProvider = new MapTiledGraphicsProvider(this.viewportId, this.displayStyle); + } + + private registerViewListeners(): void { + const view = this.view; + const removals = this._detachFromView; + + // When we detach from the view, also unregister display style listeners. + removals.push(() => this.detachFromDisplayStyle()); + + removals.push(view.onModelDisplayTransformProviderChanged.addListener(() => this.invalidateScene())); + removals.push(view.details.onClipVectorChanged.addListener(() => this.invalidateRenderPlan())); + + removals.push(view.onViewedCategoriesChanged.addListener(() => { + this._changeFlags.setViewedCategories(); + this.maybeInvalidateScene(); + })); + + removals.push(view.onDisplayStyleChanged.addListener((newStyle) => { + this._changeFlags.setDisplayStyle(); + this.setFeatureOverrideProviderChanged(); + this.invalidateRenderPlan(); + + this.detachFromDisplayStyle(); + this._mapTiledGraphicsProvider = new MapTiledGraphicsProvider(this.viewportId, newStyle); + this.registerDisplayStyleListeners(newStyle); + })); + + if (view.isSpatialView()) { + removals.push(view.onViewedModelsChanged.addListener(() => { + this._changeFlags.setViewedModels(); + this.invalidateScene(); + })); + + removals.push(view.details.onModelClipGroupsChanged.addListener(() => { + this.invalidateScene(); + })); + // If a map elevation request is required (only in cases where terrain is not geodetic) + // then the completion of the request will require synching with the view so that the + // frustum depth is recalculated correctly. Register this for removal when the view is detached. + removals.push(this.iModel.onMapElevationLoaded.addListener((_iModel: IModelConnection) => { + this.synchWithView(); + })); + } + } + + private registerDisplayStyleListeners(style: DisplayStyleState): void { + const settings = style.settings; + const removals = this._detachFromDisplayStyle; + + const displayStyleChanged = () => { + this.invalidateRenderPlan(); + this._changeFlags.setDisplayStyle(); + }; + + const styleAndOverridesChanged = () => { + displayStyleChanged(); + this.setFeatureOverrideProviderChanged(); + }; + + removals.push(settings.onSubCategoryOverridesChanged.addListener(styleAndOverridesChanged)); + removals.push(settings.onModelAppearanceOverrideChanged.addListener(styleAndOverridesChanged)); + removals.push(settings.onBackgroundColorChanged.addListener(displayStyleChanged)); + removals.push(settings.onMonochromeColorChanged.addListener(displayStyleChanged)); + removals.push(settings.onMonochromeModeChanged.addListener(displayStyleChanged)); + removals.push(settings.onClipStyleChanged.addListener(styleAndOverridesChanged)); + removals.push(settings.onPlanarClipMaskChanged.addListener(displayStyleChanged)); + removals.push(settings.onWhiteOnWhiteReversalChanged.addListener(displayStyleChanged)); + removals.push(settings.contextRealityModels.onPlanarClipMaskChanged.addListener(displayStyleChanged)); + removals.push(settings.contextRealityModels.onAppearanceOverridesChanged.addListener(displayStyleChanged)); + removals.push(settings.contextRealityModels.onChanged.addListener(displayStyleChanged)); + + removals.push(style.onOSMBuildingDisplayChanged.addListener(() => { + displayStyleChanged(); + this.synchWithView({ noSaveInUndo: true }); // May change frustum depth. + })); + + const analysisChanged = () => { + this._changeFlags.setDisplayStyle(); + this._analysisFractionValid = false; + IModelApp.requestNextAnimation(); + }; + const analysisStyleChanged = () => { + this.invalidateRenderPlan(); + analysisChanged(); + }; + removals.push(settings.onAnalysisFractionChanged.addListener(analysisChanged)); + removals.push(settings.onAnalysisStyleChanged.addListener(analysisStyleChanged)); + + const scheduleChanged = () => { + this._timePointValid = false; + this._changeFlags.setDisplayStyle(); + this.setFeatureOverrideProviderChanged(); + IModelApp.requestNextAnimation(); + }; + + removals.push(style.onScheduleScriptReferenceChanged.addListener(scheduleChanged)); + removals.push(settings.onTimePointChanged.addListener(scheduleChanged)); + + removals.push(settings.onViewFlagsChanged.addListener((vf) => { + if (vf.backgroundMap !== this.viewFlags.backgroundMap) + this.invalidateController(); + else + this.invalidateRenderPlan(); + + this._changeFlags.setDisplayStyle(); + })); + + // ###TODO detach/attach reality model + // ###TODO reality model appearance overrides + // ###TODO OSM Building display + + const mapChanged = () => { + this.invalidateController(); + this._changeFlags.setDisplayStyle(); + }; + + removals.push(settings.onBackgroundMapChanged.addListener(mapChanged)); + removals.push(settings.onMapImageryChanged.addListener(mapChanged)); + + removals.push(settings.onExcludedElementsChanged.addListener(() => { + this._changeFlags.setDisplayStyle(); + this.maybeInvalidateScene(); + this.setFeatureOverrideProviderChanged(); + })); + + if (settings.is3d()) { + removals.push(settings.onLightsChanged.addListener(displayStyleChanged)); + removals.push(settings.onSolarShadowsChanged.addListener(displayStyleChanged)); + removals.push(settings.onThematicChanged.addListener(displayStyleChanged)); + removals.push(settings.onHiddenLineSettingsChanged.addListener(displayStyleChanged)); + removals.push(settings.onAmbientOcclusionSettingsChanged.addListener(displayStyleChanged)); + removals.push(settings.onEnvironmentChanged.addListener(displayStyleChanged)); + removals.push(settings.onPlanProjectionSettingsChanged.addListener(displayStyleChanged)); + } + } + + /** @internal Invoked when the viewport becomes associated with a new ViewState to unregister event listeners for + * the previous ViewState and allow the previous ViewState to clean up any internal state that is only relevant while + * associated with a Viewport. + * Also invoked after changing OffScreenViewport.drawingToSheetTransform. + * @internal + */ + protected detachFromView(): void { + this._detachFromView.forEach((f) => f()); + this._detachFromView.length = 0; + + if (this._view) + this._view.detachFromViewport(); + + } + + private detachFromDisplayStyle(): void { + this._detachFromDisplayStyle.forEach((f) => f()); + this._detachFromDisplayStyle.length = 0; + + if (this._mapTiledGraphicsProvider) { + this._mapTiledGraphicsProvider.detachFromDisplayStyle(); + this._mapTiledGraphicsProvider = undefined; + } + } + + /** Enables or disables continuous rendering. Ideally, during each render frame a Viewport will do as little work as possible. + * To make that possible, the viewport keeps track of what has changed about its internal state from one frame to the next. + * For example, if the view frustum has not changed since the previous frame, it is likely that the viewport does not need to be + * re-rendered at all. + * + * In some circumstances, it is desirable to bypass the logic that limits the amount of work performed each frame. A primary example + * is a viewport that has some animations applied to it, or when diagnostic information like frames-per-second is being monitored. + * + * @note An application which enables continuous rendering should disable it as soon as it is no longer needed. + */ + public get continuousRendering(): boolean { return this._doContinuousRendering; } + public set continuousRendering(contRend: boolean) { + if (contRend !== this._doContinuousRendering) { + this._doContinuousRendering = contRend; + if (contRend) + IModelApp.requestNextAnimation(); + } + } + /** This gives each Viewport a unique Id, which can be used for comparing and sorting Viewport objects inside collections. + * @internal + */ + /** A unique integer Id for this viewport that can be used for comparing and sorting Viewport objects inside collections like [SortedArray]($core-bentley)s. */ + public get viewportId(): number { + return this._viewportId; + } + + /** The ViewState for this Viewport */ + public get view(): ViewState { + return this._view; + } + + /** @internal */ + public get pixelsPerInch() { + // ###TODO? This is apparently unobtainable information in a browser... + return 96; + } + + /** @internal */ + public get backgroundMapGeometry(): BackgroundMapGeometry | undefined { return this.view.displayStyle.getBackgroundMapGeometry(); } + + /** Ids of a set of elements which should not be rendered within this view. + * @note Do not modify this set directly - use [[setNeverDrawn]] or [[clearNeverDrawn]] instead. + * @note This set takes precedence over the [[alwaysDrawn]] set - if an element is present in both sets, it is never drawn. + */ + public get neverDrawn(): Id64Set | undefined { return this._neverDrawn; } + + /** Ids of a set of elements which should always be rendered within this view, regardless of category and subcategory visibility. + * If the [[isAlwaysDrawnExclusive]] flag is also set, *only* those elements in this set will be drawn. + * @note Do not modify this set directly - use [[setAlwaysDrawn]] or [[clearAlwaysDrawn]] instead. + * @note The [[neverDrawn]] set takes precedence - if an element is present in both sets, it is never drawn. + */ + public get alwaysDrawn(): Id64Set | undefined { return this._alwaysDrawn; } + + /** Clear the set of always-drawn elements. + * @see [[alwaysDrawn]] + */ + public clearAlwaysDrawn(): void { + if ((undefined !== this.alwaysDrawn && 0 < this.alwaysDrawn.size) || this._alwaysDrawnExclusive) { + if (undefined !== this.alwaysDrawn) + this.alwaysDrawn.clear(); + + this._alwaysDrawnExclusive = false; + this._changeFlags.setAlwaysDrawn(); + this.maybeInvalidateScene(); + } + } + + /** Clear the set of never-drawn elements. + * @see [[neverDrawn]] + */ + public clearNeverDrawn(): void { + if (undefined !== this.neverDrawn && 0 < this.neverDrawn.size) { + this.neverDrawn.clear(); + this._changeFlags.setNeverDrawn(); + this.maybeInvalidateScene(); + } + } + + /** Specify the Ids of a set of elements which should never be rendered within this view. + * @see [[neverDrawn]]. + */ + public setNeverDrawn(ids: Id64Set): void { + this._neverDrawn = ids; + this._changeFlags.setNeverDrawn(); + this.maybeInvalidateScene(); + } + + /** Specify the Ids of a set of elements which should always be rendered within this view, regardless of category and subcategory visibility. + * @param ids The Ids of the elements to always draw. + * @param exclusive If true, *only* the specified elements will be drawn. + * @see [[alwaysDrawn]] + * @see [[isAlwaysDrawnExclusive]] + */ + public setAlwaysDrawn(ids: Id64Set, exclusive: boolean = false): void { + this._alwaysDrawn = ids; + this._alwaysDrawnExclusive = exclusive; + this._changeFlags.setAlwaysDrawn(); + this.maybeInvalidateScene(); + } + + /** Returns true if the set of elements in the [[alwaysDrawn]] set are the *only* elements rendered within this view. */ + public get isAlwaysDrawnExclusive(): boolean { return this._alwaysDrawnExclusive; } + + /** Allows visibility of categories within this viewport to be overridden on a per-model basis. */ + public get perModelCategoryVisibility(): PerModelCategoryVisibility.Overrides { return this._perModelCategoryVisibility; } + + /** Adds visibility overrides for any subcategories whose visibility differs from that defined by the view's + * category selector in the context of specific models. + * @internal + */ + public addModelSubCategoryVisibilityOverrides(fs: FeatureSymbology.Overrides, ovrs: Id64.Uint32Map): void { + this._perModelCategoryVisibility.addOverrides(fs, ovrs); + } + + /** Add a [[FeatureOverrideProvider]] to customize the appearance of [[Feature]]s within the viewport. + * The provider will be invoked whenever the overrides are determined to need updating. + * The overrides can be explicitly marked as needing a refresh by calling [[Viewport.setFeatureOverrideProviderChanged]]. This is typically called when + * the internal state of the provider changes such that the computed overrides must also change. + * @note A Viewport can have any number of FeatureOverrideProviders. No attempt is made to resolve conflicts between two different providers overriding the same Feature. + * @param provider The provider to register. + * @returns true if the provider was registered, or false if the provider was already registered. + * @see [[dropFeatureOverrideProvider]] to remove the provider. + * @see [[findFeatureOverrideProvider]] to find an existing provider. + * @see [[FeatureSymbology.Overrides]]. + */ + public addFeatureOverrideProvider(provider: FeatureOverrideProvider): boolean { + if (this._featureOverrideProviders.includes(provider)) + return false; + + this._featureOverrideProviders.push(provider); + this.setFeatureOverrideProviderChanged(); + return true; + } + + /** Removes the specified FeatureOverrideProvider from the viewport. + * @param provider The provider to drop. + * @returns true if the provider was dropped, or false if it was not registered. + * @see [[addFeatureOverrideProvider]]. + */ + public dropFeatureOverrideProvider(provider: FeatureOverrideProvider): boolean { + const index = this._featureOverrideProviders.indexOf(provider); + if (-1 === index) + return false; + + this._featureOverrideProviders.splice(index, 1); + this.setFeatureOverrideProviderChanged(); + return true; + } + + /** Locate the first registered FeatureOverrideProvider matching the supplied criterion. + * @param predicate A function that will be invoked for each provider currently registered with the viewport, returning true to accept the provider. + * @returns The first registered provider that matches the predicate, or undefined if no providers match the predicate. + * @see [[findFeatureOverrideProviderOfType]] to locate a provider of a specific class. + * @see [[addFeatureOverrideProvider]] to register a provider. + */ + public findFeatureOverrideProvider(predicate: (provider: FeatureOverrideProvider) => boolean): FeatureOverrideProvider | undefined { + for (const provider of this._featureOverrideProviders) + if (predicate(provider)) + return provider; + + return undefined; + } + + /** The list of [[FeatureOverrideProvider]]s registered with this viewport. + * @see [[addFeatureOverrideProvider]] to register a new provider. + * @see [[dropFeatureOverrideProvider]] to unregister a provider. + * @see [[findFeatureOverrideProvider]] or [[findFeatureOverrideProviderOfType]] to find a registered provider. + */ + public get featureOverrideProviders(): Iterable { + return this._featureOverrideProviders; + } + + /** Locate the first registered FeatureOverrideProvider of the specified class. For example, to locate a registered [[EmphasizeElements]] provider: + * ```ts + * const provider: EmphasizeElements = viewport.findFeatureOverrideProviderOfType(EmphasizeElements); + * ``` + * @see [[findFeatureOverrideProvider]] to locate a registered provider matching any arbitrary criterion. + */ + public findFeatureOverrideProviderOfType(type: Constructor): T | undefined { + const provider = this.findFeatureOverrideProvider((x) => isInstanceOf(x, type)); + return asInstanceOf(provider, type); + } + + /** @internal */ + public addFeatureOverrides(ovrs: FeatureSymbology.Overrides): void { + for (const provider of this._featureOverrideProviders) + provider.addFeatureOverrides(ovrs, this); + } + + /** Notifies this viewport that the internal state of its [[FeatureOverrideProvider]] has changed such that its + * [[FeatureSymbology.Overrides]] should be recomputed. + */ + public setFeatureOverrideProviderChanged(): void { + this._changeFlags.setFeatureOverrideProvider(); + this.maybeInvalidateScene(); + } + + /** The [[TiledGraphicsProvider]]s currently registered with this viewport. + * @see [[addTiledGraphicsProvider]]. + */ + public get tiledGraphicsProviders(): Iterable { + return this._tiledGraphicsProviders; + } + + /** @internal */ + public forEachTiledGraphicsProvider(func: (provider: TiledGraphicsProvider) => void): void { + for (const provider of this._tiledGraphicsProviders) + func(provider); + } + + /** @internal */ + protected forEachTiledGraphicsProviderTree(func: (ref: TileTreeReference) => void): void { + for (const provider of this._tiledGraphicsProviders) + provider.forEachTileTreeRef(this, (ref) => func(ref)); + } + + /** @internal */ + public forEachMapTreeRef(func: (ref: TileTreeReference) => void): void { + if (this._mapTiledGraphicsProvider) + this._mapTiledGraphicsProvider.forEachTileTreeRef(this, (ref) => func(ref)); + } + + /** @internal */ + public forEachTileTreeRef(func: (ref: TileTreeReference) => void): void { + this.view.forEachTileTreeRef(func); + this.forEachTiledGraphicsProviderTree(func); + this.forEachMapTreeRef(func); + } + + /** + * Returns true if all [[TileTree]]s required by this viewport have been loaded. + */ + public get areAllTileTreesLoaded(): boolean { + if (!this.view.areAllTileTreesLoaded) + return false; + + if (this._mapTiledGraphicsProvider && !TiledGraphicsProvider.isLoadingComplete(this._mapTiledGraphicsProvider, this)) + return false; + + for (const provider of this._tiledGraphicsProviders) + if (!TiledGraphicsProvider.isLoadingComplete(provider, this)) + return false; + + return true; + } + + /** Disclose *all* TileTrees currently in use by this Viewport. This set may include trees not reported by [[forEachTileTreeRef]] - e.g., those used by view attachments, map-draped terrain, etc. + * @internal + */ + public discloseTileTrees(trees: DisclosedTileTreeSet): void { + this.forEachTiledGraphicsProviderTree((ref) => trees.disclose(ref)); + this.forEachMapTreeRef((ref) => trees.disclose(ref)); + trees.disclose(this.view); + } + + /** Register a provider of tile graphics to be drawn in this viewport. + * @see [[dropTiledGraphicsProvider]] + */ + public addTiledGraphicsProvider(provider: TiledGraphicsProvider): void { + this._tiledGraphicsProviders.add(provider); + this.invalidateScene(); + } + + /** Remove a previously-registered provider of tile graphics. + * @see [[addTiledGraphicsProvider]] + */ + public dropTiledGraphicsProvider(provider: TiledGraphicsProvider): void { + this._tiledGraphicsProviders.delete(provider); + this.invalidateScene(); + } + + /** Returns true if the specified provider has been registered with this viewport via [[addTiledGraphicsProvider]]. */ + public hasTiledGraphicsProvider(provider: TiledGraphicsProvider): boolean { + return this._tiledGraphicsProviders.has(provider); + } + + /** @internal */ + public mapLayerFromHit(hit: HitDetail): MapLayerSettings | undefined { + return undefined === hit.modelId ? undefined : this.mapLayerFromIds(hit.modelId, hit.sourceId); + } + + /** @internal */ + public mapLayerFromIds(mapTreeId: Id64String, layerTreeId: Id64String): MapLayerSettings | undefined { + return this._mapTiledGraphicsProvider?.mapLayerFromIds(mapTreeId, layerTreeId); + } + + /** @internal */ + public getTerrainHeightRange(): Range1d { + const heightRange = Range1d.createNull(); + this.forEachTileTreeRef((ref) => ref.getTerrainHeight(heightRange)); + return heightRange; + } + /** @internal */ + public setViewedCategoriesPerModelChanged(): void { + this._changeFlags.setViewedCategoriesPerModel(); + } + + /** @internal */ + public markSelectionSetDirty() { this._selectionSetDirty = true; } + + /** True if this is a 3d view with the camera turned on. */ + public get isCameraOn(): boolean { + return this.view.is3d() && this.view.isCameraOn; + } + + /** @internal */ + public changeDynamics(dynamics: GraphicList | undefined): void { + this.target.changeDynamics(dynamics); + this.invalidateDecorations(); + } + + private _assigningFlashedId = false; + + /** The Id of the currently-flashed object. + * The "flashed" visual effect is typically applied to the object in the viewport currently under the mouse cursor, to indicate + * it is ready to be interacted with by a tool. [[ToolAdmin]] is responsible for updating it when the mouse cursor moves. + * The object is usually an [Element]($backend) but could also be a [Model]($backend) or pickable decoration produced by a [[Decorator]]. + * The setter ignores any string that is not a well-formed [Id64String]($core-bentley). Passing [Id64.invalid]($core-bentley) to the + * setter is equivalent to passing `undefined` - both mean "nothing is flashed". + * @throws Error if an attempt is made to change this property from within an [[onFlashedIdChanged]] event callback. + * @see [[onFlashedIdChanged]] to be notified when the flashed object changes. + * @see [[flashSettings]] to customize the visual effect. + */ + public get flashedId(): Id64String | undefined { + return this._flashedElem; + } + public set flashedId(id: Id64String | undefined) { + if (this._assigningFlashedId) + throw new Error("Cannot assign to Viewport.flashedId from within an onFlashedIdChanged event callback."); + + if (id === Id64.invalid) + id = undefined; + + const previous = this._flashedElem; + if (id === previous || (undefined !== id && !Id64.isId64(id))) + return; + + this._lastFlashedElem = this._flashedElem; + this._flashedElem = id; + + this._assigningFlashedId = true; + try { + // The comparison `id !== previous` above ensures the following assertion, but the compiler doesn't recognize it. + assert(undefined !== id || undefined !== previous); + this.onFlashedIdChanged.raiseEvent(this, { current: id!, previous }); + } finally { + this._assigningFlashedId = false; + } + } + + public get auxCoordSystem(): AuxCoordSystemState { return this.view.auxiliaryCoordinateSystem; } + public getAuxCoordRotation(result?: Matrix3d) { return this.auxCoordSystem.getRotation(result); } + public getAuxCoordOrigin(result?: Point3d) { return this.auxCoordSystem.getOrigin(result); } + + /** The number of outstanding requests for tiles to be displayed in this viewport. + * @see Viewport.numSelectedTiles + */ + public get numRequestedTiles(): number { return IModelApp.tileAdmin.getNumRequestsForUser(this); } + + /** The number of tiles selected for display in the view as of the most recently-drawn frame. + * The tiles selected may not meet the desired level-of-detail for the view, instead being temporarily drawn while + * tiles of more appropriate level-of-detail are loaded asynchronously. + * @see Viewport.numRequestedTiles + * @see Viewport.numReadyTiles + */ + public get numSelectedTiles(): number { + const tiles = IModelApp.tileAdmin.getTilesForUser(this); + return undefined !== tiles ? tiles.selected.size + tiles.external.selected : 0; + } + + /** The number of tiles which were ready and met the desired level-of-detail for display in the view as of the most recently-drawn frame. + * These tiles may *not* have been selected because some other (probably sibling) tiles were *not* ready for display. + * This is a useful metric for determining how "complete" the view is - e.g., one indicator of progress toward view completion can be expressed as: + * ` (numReadyTiles) / (numReadyTiles + numRequestedTiles)` + * @see Viewport.numSelectedTiles + * @see Viewport.numRequestedTiles + */ + public get numReadyTiles(): number { + const tiles = IModelApp.tileAdmin.getTilesForUser(this); + return undefined !== tiles ? tiles.ready.size + tiles.external.ready : 0; + } + + /** @internal */ + public toViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.toViewOrientation(from, to); } + /** @internal */ + public fromViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.fromViewOrientation(from, to); } + + /** Change the ViewState of this Viewport + * @param view a fully loaded (see discussion at [[ViewState.load]] ) ViewState + * @param _opts options for how the view change operation should work + */ + public changeView(view: ViewState, _opts?: ViewChangeOptions) { + const prevView = this.view; + + this.updateChangeFlags(view); + this.doSetupFromView(view); + this.invalidateController(); + this.target.reset(); + + if (undefined !== prevView && prevView !== view) { + this.onChangeView.raiseEvent(this, prevView); + this._changeFlags.setViewState(); + } + } + + /** Determine whether the supplied point is visible in the viewport rectangle. + * @param point the point to test + * @param coordSys the coordinate system of the specified point + * @param borderPaddingFactor optional border for testing with inset view rectangle. + */ + public isPointVisibleXY(point: Point3d, coordSys: CoordSystem = CoordSystem.World, borderPaddingFactor: number = 0.0): boolean { + let testPtView = point; + switch (coordSys) { + case CoordSystem.Npc: + testPtView = this.npcToView(point); + break; + case CoordSystem.World: + testPtView = this.worldToView(point); + break; + } + + const frustum = this.getFrustum(CoordSystem.View); + const screenRangeX = frustum.points[Npc._000].distance(frustum.points[Npc._100]); + const screenRangeY = frustum.points[Npc._000].distance(frustum.points[Npc._010]); + const xBorder = screenRangeX * borderPaddingFactor; + const yBorder = screenRangeY * borderPaddingFactor; + + return (!(testPtView.x < xBorder || testPtView.x > (screenRangeX - xBorder) || testPtView.y < yBorder || testPtView.y > (screenRangeY - yBorder))); + } + + /** Computes the range of npc depth values for a region of the screen + * @param rect the rectangle to test. If undefined, test entire view + * @param result optional DepthRangeNpc to store the result + * @returns the minimum and maximum depth values within the region, or undefined. + */ + public determineVisibleDepthRange(rect?: ViewRect, result?: DepthRangeNpc): DepthRangeNpc | undefined { + if (result) { // Null result if given + result.minimum = 1; + result.maximum = 0; + } + + // Default to a (0, 0, 0) to (1, 1, 1) range if no range was provided + rect = (rect && rect.isValid) ? rect : this.viewRect; + + // Determine the screen rectangle in which to query visible depth min + max + const readRect = rect.computeOverlap(this.viewRect); + if (undefined === readRect) + return undefined; + + let retVal: DepthRangeNpc | undefined; + this.readPixels(readRect, Pixel.Selector.GeometryAndDistance, (pixels) => { + if (!pixels) + return; + + readRect.left = this.cssPixelsToDevicePixels(readRect.left); + readRect.right = this.cssPixelsToDevicePixels(readRect.right); + readRect.bottom = this.cssPixelsToDevicePixels(readRect.bottom); + readRect.top = this.cssPixelsToDevicePixels(readRect.top); + + let maximum = 0; + let minimum = 1; + const frac = this._viewingSpace.frustFraction; + for (let x = readRect.left; x < readRect.right; ++x) { + for (let y = readRect.top; y < readRect.bottom; ++y) { + let npcZ = pixels.getPixel(x, y).distanceFraction; + if (npcZ <= 0.0) + continue; + + if (frac < 1.0) + npcZ *= frac / (1.0 + npcZ * (frac - 1.0)); + + minimum = Math.min(minimum, npcZ); + maximum = Math.max(maximum, npcZ); + } + } + + if (maximum <= 0) + return; + + if (undefined === result) { + result = { minimum, maximum }; + } else { + result.minimum = minimum; + result.maximum = maximum; + } + + retVal = result; + }); + + return retVal; + } + + /** Turn the camera off it is currently on. + * @see [[turnCameraOn]] to turn the camera on. + */ + public turnCameraOff(): void { + if (this.view.is3d() && this.view.isCameraOn) { + this.view.turnCameraOff(); + this.setupFromView(); + } + } + + /** Turn the camera on if it is currently off. If the camera is already on, adjust it to use the supplied lens angle. + * @param lensAngle The lens angle for the camera. If undefined, use view.camera.lens. + * @note This method will fail if the ViewState is not 3d. + * @see [[turnCameraOff]] to turn the camera off. + */ + public turnCameraOn(lensAngle?: Angle): ViewStatus { + const view = this.view; + if (!view.is3d() || !view.supportsCamera()) + return ViewStatus.InvalidViewport; + + if (!lensAngle) + lensAngle = view.camera.lens; + + Camera.validateLensAngle(lensAngle); + + let status; + if (view.isCameraOn) { + status = view.lookAt({ eyePoint: view.getEyePoint(), targetPoint: view.getTargetPoint(), upVector: view.getYVector(), lensAngle }); + } else { + // We need to figure out a new camera target. To do that, we need to know where the geometry is in the view. + // We use the depth of the center of the view for that. + let depthRange = this.determineVisibleDepthRange(); + if (undefined === depthRange || Geometry.isAlmostEqualNumber(depthRange.minimum, depthRange.maximum)) + depthRange = { minimum: 0, maximum: 1 }; + + const middle = depthRange.minimum + ((depthRange.maximum - depthRange.minimum) / 2.0); + const corners = [ + new Point3d(0.0, 0.0, middle), // lower left, at target depth + new Point3d(1.0, 1.0, middle), // upper right at target depth + new Point3d(0.0, 0.0, depthRange.maximum), // lower left, at closest npc + new Point3d(1.0, 1.0, depthRange.maximum), // upper right at closest + ]; + + this.npcToWorldArray(corners); + + const eyePoint = corners[2].interpolate(0.5, corners[3]); // middle of closest plane + const targetPoint = corners[0].interpolate(0.5, corners[1]); // middle of halfway plane + const backDistance = eyePoint.distance(targetPoint) * 2.0; + const frontDistance = view.minimumFrontDistance(); + status = view.lookAt({ eyePoint, targetPoint, upVector: view.getYVector(), lensAngle, frontDistance, backDistance }); + } + + if (ViewStatus.Success === status) + this.setupFromView(); + + return status; + } + + /** Orient this viewport to one of the [[StandardView]] rotations. */ + public setStandardRotation(id: StandardViewId): void { + this.view.setStandardRotation(id); + this.setupFromView(); + } + + private doSetupFromView(view: ViewState) { + if (this._inViewChangedEvent) + return ViewStatus.Success; // ignore echos + + if (!this.isAspectRatioLocked) + view.fixAspectRatio(this.viewRect.aspect); + + this.setView(view); + + const viewSpace = ViewingSpace.createFromViewport(this); + if (undefined === viewSpace) + return ViewStatus.InvalidViewport; + + this._viewingSpace = viewSpace; + + this.invalidateRenderPlan(); + this._controllerValid = true; + + this._inViewChangedEvent = true; + this.onViewChanged.raiseEvent(this); + this._inViewChangedEvent = false; + return ViewStatus.Success; + } + + /** Establish the parameters of this Viewport from the current information in its ViewState */ + public setupFromView(pose?: ViewPose): ViewStatus { + if (undefined !== pose) + this.view.applyPose(pose); + return this.doSetupFromView(this.view); + } + + /** Call [[setupFromView]] on this Viewport and then apply optional behavior. + * @param options _options for behavior of view change. If undefined, all options have their default values (see [[ViewChangeOptions]] for details.) + */ + public synchWithView(_options?: ViewChangeOptions): void { this.setupFromView(); } + + /** Convert an array of points from CoordSystem.View to CoordSystem.Npc */ + public viewToNpcArray(pts: Point3d[]): void { this._viewingSpace.viewToNpcArray(pts); } + /** Convert an array of points from CoordSystem.Npc to CoordSystem.View */ + public npcToViewArray(pts: Point3d[]): void { this._viewingSpace.npcToViewArray(pts); } + /** Convert a point from CoordSystem.View to CoordSystem.Npc + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public viewToNpc(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.viewToNpc(pt, out); } + /** Convert a point from CoordSystem.Npc to CoordSystem.View + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public npcToView(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.npcToView(pt, out); } + /** Convert an array of points from CoordSystem.World to CoordSystem.Npc */ + public worldToNpcArray(pts: Point3d[]): void { this._viewingSpace.worldToNpcArray(pts); } + /** Convert an array of points from CoordSystem.Npc to CoordSystem.World */ + public npcToWorldArray(pts: Point3d[]): void { this._viewingSpace.npcToWorldArray(pts); } + /** Convert an array of points from CoordSystem.World to CoordSystem.View */ + public worldToViewArray(pts: Point3d[]): void { this._viewingSpace.worldToViewArray(pts); } + /** Convert an array of points from CoordSystem.World to CoordSystem.View, as Point4ds */ + public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { this._viewingSpace.worldToView4dArray(worldPts, viewPts); } + /** Convert an array of points from CoordSystem.View to CoordSystem.World */ + public viewToWorldArray(pts: Point3d[]) { this._viewingSpace.viewToWorldArray(pts); } + /** Convert an array of points from CoordSystem.View as Point4ds to CoordSystem.World */ + public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { this._viewingSpace.view4dToWorldArray(viewPts, worldPts); } + /** Convert a point from CoordSystem.World to CoordSystem.Npc + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToNpc(pt, out); } + /** Convert a point from CoordSystem.Npc to CoordSystem.World + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.npcToWorld(pt, out); } + /** Convert a point from CoordSystem.World to CoordSystem.View + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public worldToView(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToView(input, out); } + /** Convert a point from CoordSystem.World to CoordSystem.View as Point4d + * @param input the point to convert + * @param out optional location for result. If undefined, a new Point4d is created. + */ + public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { return this._viewingSpace.worldToView4d(input, out); } + /** Convert a point from CoordSystem.View to CoordSystem.World + * @param pt the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.viewToWorld(input, out); } + /** Convert a point from CoordSystem.View as a Point4d to CoordSystem.View + * @param input the point to convert + * @param out optional location for result. If undefined, a new Point3d is created. + */ + public view4dToWorld(input: Point4d, out?: Point3d): Point3d { return this._viewingSpace.view4dToWorld(input, out); } + + /** Converts inches to pixels based on screen DPI. + * @Note this information may not be accurate in some browsers. + * @param inches the number of inches to convert + * @returns the corresponding number of pixels + */ + public pixelsFromInches(inches: number): number { return inches * this.pixelsPerInch; } + + /** Get an 8-point Frustum corresponding to the 8 corners of the Viewport in the specified coordinate system. + * + * There are two sets of corners that may be of interest. + * The "adjusted" box is the one that is computed by examining the "viewed extents" and moving + * the front and back planes to enclose everything in the view. + * The "unadjusted" box is the one that is stored in the ViewState. + * @param sys Coordinate system for points + * @param adjustedBox If true, retrieve the adjusted box. Otherwise retrieve the box that came from the view definition. + * @param box optional Frustum for return value + * @return the view frustum + * @note The "adjusted" box may be either larger or smaller than the "unadjusted" box. + */ + public getFrustum(sys: CoordSystem = CoordSystem.World, adjustedBox: boolean = true, box?: Frustum): Frustum { return this._viewingSpace.getFrustum(sys, adjustedBox, box); } + + /** Get a copy of the current (unadjusted) frustum of this viewport, in world coordinates. */ + public getWorldFrustum(box?: Frustum): Frustum { return this.getFrustum(CoordSystem.World, false, box); } + + /** Scroll the view by a given number of pixels. + * @param screenDist distance to scroll, in pixels + */ + public scroll(screenDist: XAndY, options?: ViewChangeOptions) { + const view = this.view; + if (!view) + return; + + const distXYZ = new Point3d(screenDist.x, screenDist.y, 0); + if (view.is3d() && view.isCameraOn) { + const frust = this.getFrustum(CoordSystem.View, false)!; + frust.translate(distXYZ); + this.viewToWorldArray(frust.points); + view.setupFromFrustum(frust); + view.centerEyePoint(); + } else { + const pts = [new Point3d(), distXYZ]; + this.viewToWorldArray(pts); + const dist = pts[1].minus(pts[0]); + view.setOrigin(view.getOrigin().plus(dist)); + } + + this.synchWithView(options); + } + + /** Zoom the view by a scale factor, placing the new center at the given point (world coordinates). + * @param newCenter The new center point of the view, in world coordinates. If undefined, use current center. + * @param factor the zoom factor. + * @param options options for behavior of view change + */ + public zoom(newCenter: Point3d | undefined, factor: number, options?: ViewChangeOptions & MarginOptions & OnViewExtentsError): ViewStatus { + const view = this.view; + if (undefined === view) + return ViewStatus.InvalidViewport; + + if (view.is3d() && view.isCameraOn) { + const centerNpc = newCenter ? this.worldToNpc(newCenter) : NpcCenter.clone(); + const scaleTransform = Transform.createFixedPointAndMatrix(centerNpc, Matrix3d.createScale(factor, factor, 1.0)); + + const offset = centerNpc.minus(NpcCenter); // offset by difference of old/new center + offset.z = 0.0; // z center stays the same. + + const offsetTransform = Transform.createTranslationXYZ(offset.x, offset.y, offset.z); + const product = offsetTransform.multiplyTransformTransform(scaleTransform); + + const frust = new Frustum(); + product.multiplyPoint3dArrayInPlace(frust.points); + + this.npcToWorldArray(frust.points); + view.setupFromFrustum(frust); + view.centerEyePoint(); + } else { + // for non-camera views, do the zooming by adjusting the origin and delta directly so there can be no + // chance of the rotation changing due to numerical precision errors calculating it from the frustum corners. + const delta = view.getExtents().scale(factor); + + const rot = view.getRotation(); + const center = rot.multiplyVector(newCenter ? newCenter : view.getCenter()); + + // fix for min/max delta + const stat = view.adjustViewDelta(delta, center, rot, this.viewRect.aspect, options); + if (ViewStatus.Success !== stat) + return stat; + + if (!view.allow3dManipulations()) + center.z = 0.0; + + view.setOrigin(rot.multiplyTransposeVector(delta.scale(.5).vectorTo(center))); + view.setExtents(delta); + } + + this.synchWithView(options); + return ViewStatus.Success; + } + + /** @see [[zoomToPlacements]]. */ + public zoomToPlacementProps(placementProps: PlacementProps[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { + const placements = placementProps.map((props) => isPlacement2dProps(props) ? Placement2d.fromJSON(props) : Placement3d.fromJSON(props)); + this.zoomToPlacements(placements, options); + } + + /** Zoom the view in or out to a fit to the tightest volume enclosing a given set of placements, optionally also changing the view rotation. + * @param placements The array of placements. The view will zoom to fit the union of the placements. + * @param options Options controlling how the view change works and whether to change view rotation. + * @note any invalid placements are ignored. If no valid placements are supplied, this function does nothing. + * @see [[zoomToElements]] to zoom to a set of elements. + * @see [[IModelConnection.Elements.getPlacements]] to obtain the placements for a set of elements. + */ + public zoomToPlacements(placements: Placement[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { + placements = placements.filter((x) => x.isValid); + if (placements.length === 0) + return; + + const view = this.view; + if (undefined !== options) { + if (undefined !== options.standardViewId) { + view.setStandardRotation(options.standardViewId); + } else if (undefined !== options.placementRelativeId) { + const viewRotation = StandardView.getStandardRotation(options.placementRelativeId).clone(); + viewRotation.multiplyMatrixMatrixTranspose(placements[0].transform.matrix, viewRotation); + view.setRotation(viewRotation); + } else if (undefined !== options.viewRotation) { + view.setRotation(options.viewRotation); + } + } + + const viewTransform = Transform.createOriginAndMatrix(undefined, view.getRotation()); + const frust = new Frustum(); + const viewRange = new Range3d(); + for (const placement of placements) + viewRange.extendArray(placement.getWorldCorners(frust).points, viewTransform); + + const ignoreError: ViewChangeOptions & MarginOptions & OnViewExtentsError = { + ...options, + onExtentsError: () => ViewStatus.Success, + }; + + view.lookAtViewAlignedVolume(viewRange, this.viewRect.aspect, ignoreError); + this.synchWithView(options); + } + + /** Zoom the view to a show the tightest box around a given set of ElementProps. Optionally, change view rotation. + * @param props element props. Will zoom to the union of the placements. + * @param options options that control how the view change works and whether to change view rotation. + * @note Do not query for ElementProps just to zoom to their placements - [[zoomToElements]] is much more efficient because it queries only for the placement properties. + */ + public zoomToElementProps(elementProps: ElementProps[], options?: ViewChangeOptions & MarginOptions & ZoomToOptions): void { + if (elementProps.length === 0) + return; + + const placementProps: PlacementProps[] = []; + for (const props of elementProps) { + const placement = (props as any).placement; + if (placement !== undefined && this.view.viewsModel(props.model)) + placementProps.push(placement); + } + + this.zoomToPlacementProps(placementProps, options); + } + + /** Zoom the view to a show the tightest box around a given set of elements. Optionally, change view rotation. + * @param ids the element id(s) to include. Will zoom to the union of the placements. + * @param options options that control how the view change works and whether to change view rotation. + */ + public async zoomToElements(ids: Id64Arg, options?: ViewChangeOptions & MarginOptions & ZoomToOptions): Promise { + const placements = await this.iModel.elements.getPlacements(ids, { type: this.view.is3d() ? "3d" : "2d" }); + this.zoomToPlacements(placements, options); + } + + /** Zoom the view to a volume of space in world coordinates. + * @param volume The low and high corners, in world coordinates. + * @param options options that control how the view change works + */ + public zoomToVolume(volume: LowAndHighXYZ | LowAndHighXY, options?: ViewChangeOptions & MarginOptions) { + this.view.lookAtVolume(volume, this.viewRect.aspect, options); + this.synchWithView(options); + } + + /** Shortcut to call view.setupFromFrustum and then [[setupFromView]] + * @param inFrustum the new viewing frustum + * @returns true if both steps were successful + */ + public setupViewFromFrustum(inFrustum: Frustum): boolean { + const validSize = this.view.setupFromFrustum(inFrustum); + // note: always call setupFromView, even if setupFromFrustum failed + return (ViewStatus.Success === this.setupFromView() && ViewStatus.Success === validSize); + } + + /** Compute the range of all geometry to be displayed in this viewport. */ + public computeViewRange(): Range3d { + const fitRange = this.view.computeFitRange(); + this.forEachTiledGraphicsProviderTree((ref) => { + ref.unionFitRange(fitRange); + }); + return fitRange; + } + + /** Set or clear the animator for this Viewport. + * @param animator The new animator for this Viewport, or undefined to remove current animator. + * @note current animator's `interrupt` method will be called (if it has not completed yet) + * @public + */ + public setAnimator(animator?: Animator) { + this._animator?.interrupt(); + this._animator = animator; + + // Immediately invoke the animator to set up the initial frustum. + // This is important for TwoWayViewportSync; otherwise, the synced viewport will have its frustum set to the final frustum, + // producing a flicker to that frustum during the first frame of animation. + this.animate(); + } + + /** Used strictly by TwoWayViewportSync to change the reactive viewport's view to a clone of the active viewport's ViewState. + * Does *not* trigger "ViewState changed" events. + * @internal + */ + public applyViewState(val: ViewState) { + this.updateChangeFlags(val); + this.setView(val); + this._viewingSpace.view = val; + this.synchWithView({ noSaveInUndo: true }); + } + + /** Invoked from finishUndoRedo, applyViewState, and changeView to potentially recompute change flags based on differences between current and new ViewState. */ + protected updateChangeFlags(newView: ViewState): void { + // Before the first call to changeView, this.view is undefined because we have no frustum. Our API pretends it is never undefined. + const oldView = undefined !== this.viewingSpace ? this.view : undefined; + + if (undefined === oldView || oldView === newView) + return; + + const flags = this._changeFlags; + if (!flags.displayStyle && !oldView.displayStyle.equalState(newView.displayStyle)) + flags.setDisplayStyle(); + + if (!flags.viewedCategories && !oldView.categorySelector.equalState(newView.categorySelector)) + flags.setViewedCategories(); + + if (!flags.neverDrawn) { + if (oldView.displayStyle.settings.compressedExcludedElementIds !== newView.displayStyle.settings.compressedExcludedElementIds) + flags.setNeverDrawn(); + } + + if (flags.viewedModels) + return; + + if (oldView.is2d() && newView.is2d()) { + if (oldView.baseModelId !== newView.baseModelId) + flags.setViewedModels(); + } else if (oldView.isSpatialView() && newView.isSpatialView()) { + if (!oldView.modelSelector.equalState(newView.modelSelector)) + flags.setViewedModels(); + } else { + // switched between 2d and 3d view. + flags.setViewedModels(); + } + } + + private static roundGrid(num: number, units: number): number { + const sign = ((num * units) < 0.0) ? -1.0 : 1.0; + num = (num * sign) / units + 0.5; + return units * sign * Math.floor(num); + } + + private getGridOrientation(origin: Point3d, rMatrix: Matrix3d) { + if (this.view.isSpatialView()) + origin.setFrom(this.iModel.globalOrigin); + + switch (this.view.getGridOrientation()) { + case GridOrientationType.View: { + const center = this.view.getCenter(); + this.toViewOrientation(center); + this.toViewOrientation(origin); + origin.z = center.z; + this.fromViewOrientation(origin); + break; + } + + case GridOrientationType.WorldXY: + break; + + case GridOrientationType.WorldYZ: { + Matrix3d.createRows(rMatrix.getRow(1), rMatrix.getRow(2), rMatrix.getRow(0), rMatrix); + break; + } + + case GridOrientationType.WorldXZ: { + Matrix3d.createRows(rMatrix.getRow(0), rMatrix.getRow(2), rMatrix.getRow(1), rMatrix); + break; + } + } + } + + private pointToStandardGrid(point: Point3d, rMatrix: Matrix3d, origin: Point3d): void { + const planeNormal = rMatrix.getRow(2); + + let eyeVec: Vector3d; + if (this.view.is3d() && this.view.isCameraOn) + eyeVec = this.view.camera.eye.vectorTo(point); + else + eyeVec = this._viewingSpace.rotation.getRow(2); + + eyeVec.normalizeInPlace(); + linePlaneIntersect(point, point, eyeVec, origin, planeNormal, false); + + // // get origin and point in view coordinate system + const pointView = point.clone(); + const originView = origin.clone(); + this.toViewOrientation(pointView); + this.toViewOrientation(originView); + + // subtract off the origin + pointView.y -= originView.y; + pointView.x -= originView.x; + + // round off the remainder to the grid distances + const gridSpacing = this.view.getGridSpacing(); + pointView.x = Viewport.roundGrid(pointView.x, gridSpacing.x); + pointView.y = Viewport.roundGrid(pointView.y, gridSpacing.y); + + // add the origin back in + pointView.x += originView.x; + pointView.y += originView.y; + + // go back to root coordinate system + this.fromViewOrientation(pointView); + point.setFrom(pointView); + } + + /** @internal */ + public pointToGrid(point: Point3d): void { + if (GridOrientationType.AuxCoord === this.view.getGridOrientation()) { + this.pointToStandardGrid(point, this.getAuxCoordRotation(), this.getAuxCoordOrigin()); + return; + } + + const origin = new Point3d(); + const rMatrix = Matrix3d.createIdentity(); + this.getGridOrientation(origin, rMatrix); + this.pointToStandardGrid(point, rMatrix, origin); + } + + /** Get the width of a pixel (a unit vector in the x direction in view coordinates) at a given point in world coordinates, returning the result in meters (world units). + * + * This is most useful to determine how large something is in a view. In particular, in a perspective view + * the result of this method will be a larger number for points closer to the back of the view Frustum (that is, + * one pixel of the view represents more spatial area at the back of the Frustum than the front.) + * @param point The point to test, in World coordinates. If undefined, the center of the view in NPC space is used. + * @returns The width of a view pixel at the supplied world point, in meters. + * @note A "pixel" refers to a logical (CSS) pixel, not a device pixel. + */ + public getPixelSizeAtPoint(point?: Point3d): number { + if (point === undefined) + point = this.npcToWorld(NpcCenter); // if undefined, use center of view + + const worldPts: Point3d[] = []; + const viewPts: Point4d[] = []; + viewPts[0] = this.worldToView4d(point); + viewPts[1] = viewPts[0].clone(); + viewPts[1].x += viewPts[1].w; // form a vector one pixel wide in x direction. + this.view4dToWorldArray(viewPts, worldPts); + + return worldPts[0].distance(worldPts[1]); + } + + private get _wantInvertBlackAndWhite(): boolean { + const bgColor = this.view.backgroundColor.colors; + return ((bgColor.r + bgColor.g + bgColor.b) > (255 * 3) / 2); + } + + /** Get a color that will contrast to the current background color of this Viewport. Either Black or White depending on which will have the most contrast. */ + public getContrastToBackgroundColor(): ColorDef { + return this._wantInvertBlackAndWhite ? ColorDef.black : ColorDef.white; // should we use black or white? + } + + private processFlash(): boolean { + let needsFlashUpdate = false; + + if (this.flashedId !== this._lastFlashedElem) { + this._flashIntensity = 0.0; + this._flashUpdateTime = BeTimePoint.now(); + this._lastFlashedElem = this.flashedId; // flashing has begun; this is now the previous flash + needsFlashUpdate = this.flashedId === undefined; // notify render thread that flash has been turned off (signified by undefined elem) + } + + if (this.flashedId !== undefined && this._flashIntensity < this.flashSettings.maxIntensity) { + assert(undefined !== this._flashUpdateTime); + + const flashDuration = this.flashSettings.duration; + const flashElapsed = BeTimePoint.now().milliseconds - this._flashUpdateTime.milliseconds; + this._flashIntensity = Math.min(flashElapsed, flashDuration.milliseconds) / flashDuration.milliseconds; + this._flashIntensity = Math.min(this._flashIntensity, this.flashSettings.maxIntensity); + + needsFlashUpdate = true; + } + + return needsFlashUpdate; + } + + /** Create a context appropriate for producing the scene to be rendered by this viewport, e.g., by [[createScene]]. */ + public createSceneContext(): SceneContext { + return new SceneContext(this); + } + + /** Populate the context with the scene to be rendered by this viewport. + * @note This method is not typically invoked directly - [[renderFrame]] invokes it as needed to recreate the scene. + */ + public createScene(context: SceneContext): void { + this.view.createScene(context); + if (this._mapTiledGraphicsProvider) + TiledGraphicsProvider.addToScene(this._mapTiledGraphicsProvider, context); + + for (const provider of this._tiledGraphicsProviders) + TiledGraphicsProvider.addToScene(provider, context); + } + + /** Called when the visible contents of the viewport are redrawn. + * @note Due to the frequency of this event, avoid performing expensive work inside event listeners. + */ + public readonly onRender = new BeEvent<(vp: Viewport) => void>(); + + /** @internal */ + protected validateRenderPlan() { + this.target.changeRenderPlan(createRenderPlanFromViewport(this)); + this._renderPlanValid = true; + } + + private animate(): void { + if (this._animator?.animate()) + this._animator = undefined; // animation completed. + } + + /** Renders the contents of this viewport. This method performs only as much work as necessary based on what has changed since + * the last frame. If nothing has changed since the last frame, nothing is rendered. + * @note This method should almost never be invoked directly - it is invoked on your behalf by [[ViewManager]]'s render loop. + */ + public renderFrame(): void { + this._frameStatsCollector.beginFrame(); + + const changeFlags = this._changeFlags; + if (changeFlags.hasChanges) + this._changeFlags = new MutableChangeFlags(ChangeFlag.None); + + const view = this.view; + const target = this.target; + + // Start timer for tile loading time + const timer = new StopWatch(undefined, true); + this._frameStatsCollector.beginTime("totalSceneTime"); + + this._frameStatsCollector.beginTime("animationTime"); + // if any animation is active, perform it now + this.animate(); + this._frameStatsCollector.endTime("animationTime"); + + let isRedrawNeeded = this._redrawPending || this._doContinuousRendering; + this._redrawPending = false; + + const resized = target.updateViewRect(); + if (resized) { + target.onResized(); + this.invalidateController(); + } + + if (!this._controllerValid) + this.setupFromView(); + + if (this._selectionSetDirty) { + target.setHiliteSet(view.iModel.hilited); + this._selectionSetDirty = false; + isRedrawNeeded = true; + } + + let overridesNeeded = changeFlags.areFeatureOverridesDirty; + + if (!this._analysisFractionValid) { + this._analysisFractionValid = isRedrawNeeded = true; + target.analysisFraction = this.displayStyle.settings.analysisFraction; + } + + if (!this._timePointValid) { + isRedrawNeeded = true; + const scheduleScript = view.displayStyle.scheduleState; + if (scheduleScript) { + target.animationBranches = scheduleScript.getAnimationBranches(this.timePoint ?? scheduleScript.duration.low); + if (scheduleScript.containsFeatureOverrides) + overridesNeeded = true; + + if (scheduleScript.script.containsTransform && !this._freezeScene) + this.invalidateScene(); + } + + this._timePointValid = true; + } + + if (overridesNeeded) { + const ovr = new FeatureSymbology.Overrides(this); + target.overrideFeatureSymbology(ovr); + isRedrawNeeded = true; + } + + if (!this._sceneValid) { + if (!this._freezeScene) { + this._frameStatsCollector.beginTime("createChangeSceneTime"); + IModelApp.tileAdmin.clearTilesForUser(this); + IModelApp.tileAdmin.clearUsageForUser(this); + + const context = this.createSceneContext(); + this.createScene(context); + + context.requestMissingTiles(); + target.changeScene(context.scene); + isRedrawNeeded = true; + this._frameStatsCollector.endTime("createChangeSceneTime"); + } + + this._sceneValid = true; + } + + if (!this._renderPlanValid) { + this._frameStatsCollector.beginTime("validateRenderPlanTime"); + this.validateRenderPlan(); + this._frameStatsCollector.endTime("validateRenderPlanTime"); + isRedrawNeeded = true; + } + + if (!this._decorationsValid) { + this._frameStatsCollector.beginTime("decorationsTime"); + const decorations = new Decorations(); + this.addDecorations(decorations); + target.changeDecorations(decorations); + this._decorationsValid = true; + isRedrawNeeded = true; + this._frameStatsCollector.endTime("decorationsTime"); + } + + let requestNextAnimation = false; + if (this.processFlash()) { + target.setFlashed(undefined !== this.flashedId ? this.flashedId : Id64.invalid, this._flashIntensity); + isRedrawNeeded = true; + requestNextAnimation = undefined !== this.flashedId; + } + + this._frameStatsCollector.beginTime("onBeforeRenderTime"); + target.onBeforeRender(this, (redraw: boolean) => { + isRedrawNeeded = isRedrawNeeded || redraw; + }); + this._frameStatsCollector.endTime("onBeforeRenderTime"); + + this._frameStatsCollector.endTime("totalSceneTime"); + timer.stop(); + if (isRedrawNeeded) { + target.drawFrame(timer.elapsed.milliseconds); + this.onRender.raiseEvent(this); + } + this._frameStatsCollector.endFrame(isRedrawNeeded); + + // Dispatch change events after timer has stopped and update has finished. + if (resized) + this.onResized.raiseEvent(this); + + if (changeFlags.hasChanges) { + this.onViewportChanged.raiseEvent(this, changeFlags); + + if (changeFlags.displayStyle) + this.onDisplayStyleChanged.raiseEvent(this); + + if (changeFlags.viewedModels) + this.onViewedModelsChanged.raiseEvent(this); + + if (changeFlags.areFeatureOverridesDirty) { + this.onFeatureOverridesChanged.raiseEvent(this); + + if (changeFlags.alwaysDrawn) + this.onAlwaysDrawnChanged.raiseEvent(this); + + if (changeFlags.neverDrawn) + this.onNeverDrawnChanged.raiseEvent(this); + + if (changeFlags.viewedCategories) + this.onViewedCategoriesChanged.raiseEvent(this); + + if (changeFlags.viewedCategoriesPerModel) + this.onViewedCategoriesPerModelChanged.raiseEvent(this); + + if (changeFlags.featureOverrideProvider) + this.onFeatureOverrideProviderChanged.raiseEvent(this); + } + } + + if (requestNextAnimation || undefined !== this._animator || this.continuousRendering) + IModelApp.requestNextAnimation(); + } + + /** @internal */ + protected addDecorations(_decorations: Decorations): void { } + + /** Read selected data about each pixel within a rectangular region of this Viewport. + * @param rect The area of the viewport's contents to read. The origin specifies the upper-left corner. Must lie entirely within the viewport's dimensions. This input viewport is specified using CSS pixels not device pixels. + * @param selector Specifies which aspect(s) of data to read. + * @param receiver A function accepting a [[Pixel.Buffer]] object from which the selected data can be retrieved, or receiving undefined if the viewport is not active, the rect is out of bounds, or some other error. The pixels received will be device pixels, not CSS pixels. See [[Viewport.devicePixelRatio]] and [[Viewport.cssPixelsToDevicePixels]]. + * @param excludeNonLocatable If true, geometry with the "non-locatable" flag set will not be drawn. + * @note The [[Pixel.Buffer]] supplied to the `receiver` function becomes invalid once that function exits. Do not store a reference to it. + */ + public readPixels(rect: ViewRect, selector: Pixel.Selector, receiver: Pixel.Receiver, excludeNonLocatable = false): void { + const viewRect = this.viewRect; + if (!rect.isContained(viewRect)) + receiver(undefined); + else + this.target.readPixels(rect, selector, receiver, excludeNonLocatable); + } + + /** @internal */ + public isPixelSelectable(pixel: Pixel.Data) { + if (undefined === pixel.featureTable || undefined === pixel.elementId) + return false; + + if (pixel.featureTable.modelId === pixel.elementId) + return false; // Reality Models not selectable + + return undefined === this.mapLayerFromIds(pixel.featureTable.modelId, pixel.elementId); // Maps no selectable. + } + + /** Read the current image from this viewport from the rendering system. If a view rectangle outside the actual view is specified, the entire view is captured. + * @param rect The area of the view to read. The origin of a viewRect must specify the upper left corner. + * @param targetSize The size of the image to be returned. The size can be larger or smaller than the original view. + * @param flipVertically If true, the image is flipped along the x-axis. + * @returns The contents of the viewport within the specified rectangle as a bitmap image, or undefined if the image could not be read. + * @note By default the image is returned with the coordinate (0,0) referring to the bottom-most pixel. Pass `true` for `flipVertically` to flip it along the x-axis. + * @deprecated Use readImageBuffer. + */ + public readImage(rect: ViewRect = new ViewRect(0, 0, -1, -1), targetSize: Point2d = Point2d.createZero(), flipVertically: boolean = false): ImageBuffer | undefined { + // eslint-disable-next-line deprecation/deprecation + return this.target.readImage(rect, targetSize, flipVertically); + } + + /** Capture the image currently rendered in this viewport, or a subset thereof. + * @param args Describes the region to capture and optional resizing. By default the entire image is captured with no resizing. + * @returns The image, or `undefined` if the specified capture rect is not fully contained in [[viewRect], a 2d context could not be obtained, or the resultant image consists entirely + * of 100% transparent background pixels. + */ + public readImageBuffer(args?: ReadImageBufferArgs): ImageBuffer | undefined { + return this.target.readImageBuffer(args); + } + + /** Reads the current image from this viewport into an HTMLCanvasElement with a Canvas2dRenderingContext such that additional 2d graphics can be drawn onto it. + * @see [[readImageBuffer]] to obtain the image as an array of RGBA pixels. + */ + public readImageToCanvas(): HTMLCanvasElement { + return this.target.readImageToCanvas(); + } + + /** Get the point at the specified x and y location in the pixel buffer in npc coordinates. + * @see [[getPixelDataWorldPoint]] to obtain the point in [[CoordSystem.World]]. + */ + public getPixelDataNpcPoint(pixels: Pixel.Buffer, x: number, y: number, out?: Point3d): Point3d | undefined { + const z = pixels.getPixel(x, y).distanceFraction; + if (z <= 0.0) + return undefined; + + const viewSpace = this._viewingSpace; + + const result = undefined !== out ? out : new Point3d(); + const viewRect = this.viewRect.clone(); + viewRect.left = this.cssPixelsToDevicePixels(viewRect.left); + viewRect.right = this.cssPixelsToDevicePixels(viewRect.right); + viewRect.bottom = this.cssPixelsToDevicePixels(viewRect.bottom); + viewRect.top = this.cssPixelsToDevicePixels(viewRect.top); + result.x = (x + 0.5 - viewRect.left) / viewRect.width; + result.y = 1.0 - (y + 0.5 - viewRect.top) / viewRect.height; + if (viewSpace.frustFraction < 1.0) + result.z = z * viewSpace.frustFraction / (1.0 + z * (viewSpace.frustFraction - 1.0)); // correct to npc if camera on. + else + result.z = z; + + return result; + } + + /** Get the point at the specified x and y location in the pixel buffer in world coordinates. + * @see [[getPixelDataNpcPoint]] to obtain the point in [[CoordSystem.Npc]]. + */ + public getPixelDataWorldPoint(args: GetPixelDataWorldPointArgs): Point3d | undefined { + const { pixels, x, y, out, preserveModelDisplayTransforms } = args; + const npc = this.getPixelDataNpcPoint(pixels, x, y, out); + if (undefined !== npc) { + this.npcToWorld(npc, npc); + + // If this is a plan projection model, invert the elevation applied to its display transform. + // Likewise, if it is a hit on a model with a display transform, reverse the display transform. + if (!preserveModelDisplayTransforms) { + const modelId = pixels.getPixel(x, y).featureTable?.modelId; + if (undefined !== modelId) { + npc.z -= this.view.getModelElevation(modelId); + this.view.transformPointByModelDisplayTransform(modelId, npc, true); + } + } + } + + return npc; + } + + /** Query which [Feature]($common)s are currently visible within the viewport. + * @param options Specifies how to query. + * @param callback Callback to invoke with the results. + * @note This function may be slow, especially if the features are being queried from screen pixels. Avoid calling it repeatedly in rapid succession. + * @beta + */ + public queryVisibleFeatures(options: QueryVisibleFeaturesOptions, callback: QueryVisibleFeaturesCallback): void { + return queryVisibleFeatures(this, options, callback); + } + + /** @internal */ + public collectStatistics(stats: RenderMemory.Statistics): void { + const trees = new DisclosedTileTreeSet(); + this.discloseTileTrees(trees); + for (const tree of trees) + tree.collectStatistics(stats); + + this.view.collectNonTileTreeStatistics(stats); + } + + /** Intended strictly as a temporary solution for interactive editing applications, until official support for such apps is implemented. + * Invalidates tile trees for all specified models (or all viewed models, if none specified), causing subsequent requests for tiles to make new requests to back-end for updated tiles. + * @internal + */ + public refreshForModifiedModels(modelIds: Id64Arg | undefined): void { + if (this.view.refreshForModifiedModels(modelIds)) + this.invalidateScene(); + } + + /** A multiplier applied to the size in pixels of a [[Tile]] during tile selection for this viewport. Defaults to [[TileAdmin.defaultTileSizeModifier]] but can be overridden per-viewport. + * A value greater than 1.0 causes lower-resolution tiles to be selected; a value less than 1.0 causes higher-resolution tiles to be selected. + * This can allow an application to sacrifice quality for performance or vice-versa. + * @alpha + */ + public get tileSizeModifier(): number { + return undefined !== this._tileSizeModifier ? this._tileSizeModifier : IModelApp.tileAdmin.defaultTileSizeModifier; + } + + /** Controls this Viewport's [[tileSizeModifier]]. + * @param modifier If defined, overrides [[TileAdmin.defaultTileSizeModifier]]; otherwise, resets it to that default. Must be greater than zero. + * @alpha + */ + public setTileSizeModifier(modifier: number | undefined) { + if (modifier === this._tileSizeModifier) + return; + + if (undefined !== modifier && (Number.isNaN(modifier) || modifier <= 0)) + return; + + this._tileSizeModifier = modifier; + this.invalidateScene(); + } + + /** The device pixel ratio used by this Viewport. This value is *not* necessarily equal to `window.devicePixelRatio`. + * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio + */ + public get devicePixelRatio(): number { + return this.target.devicePixelRatio; + } + + /** Convert a number in CSS pixels to device pixels using this Viewport's device pixel ratio. + * See: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio + * @param num The number in CSS pixels to scale + * @returns The resulting number in device pixels + */ + public cssPixelsToDevicePixels(cssPixels: number): number { + return this.target.cssPixelsToDevicePixels(cssPixels); + } + + /** @see [[ViewState.setModelDisplayTransformProvider]] + * @internal + */ + public setModelDisplayTransformProvider(provider: ModelDisplayTransformProvider): void { + this.view.modelDisplayTransformProvider = provider; + } + + /** An ordered list of names of screen-space post-processing effects to be applied to the image rendered by the Viewport. + * The effects are applied to the image in the order in which they appear in the list. Any names not corresponding to a registered effect are ignored. + * This may have no effect if the Viewport's [[RenderTarget]] does not support screen-space effects. + * @see [[RenderSystem.createScreenSpaceEffectBuilder]] to create and register new effects. + * @public + */ + public get screenSpaceEffects(): Iterable { + return this.target.screenSpaceEffects; + } + public set screenSpaceEffects(effects: Iterable) { + this.target.screenSpaceEffects = effects; + this.requestRedraw(); + } + + /** Append a screen-space effect to the list of effects applied to this Viewport. + * @see [[Viewport.screenSpaceEffects]]. + * @public + */ + public addScreenSpaceEffect(effectName: string): void { + this.screenSpaceEffects = [...this.screenSpaceEffects, effectName]; + } + + /** Remove all screen-space effects from this Viewport. + * @see [[Viewport.screenSpaceEffects]]. + * @public + */ + public removeScreenSpaceEffects(): void { + this.screenSpaceEffects = []; + } + + /** Add an event listener to be invoked whenever the [AnalysisStyle]($common) associated with this viewport changes. + * The analysis style may change for any of several reasons: + * - When the viewport's associated [DisplayStyleSettings.analysisStyle]($common). + * - When the viewport's associated [[ViewState.displayStyle]] changes. + * - When the viewport's associated [[ViewState]] changes via [[changeView]]. + * @param listener Callback accepting the new analysis style, or undefined if there is no analysis style. + * @returns A function that can be invoked to remove the event listener. + */ + public addOnAnalysisStyleChangedListener(listener: (newStyle: AnalysisStyle | undefined) => void): () => void { + const addSettingsListener = (style: DisplayStyleState) => style.settings.onAnalysisStyleChanged.addListener(listener); + let removeSettingsListener = addSettingsListener(this.displayStyle); + + const addStyleListener = (view: ViewState) => view.onDisplayStyleChanged.addListener((style) => { + listener(style.settings.analysisStyle); + removeSettingsListener(); + removeSettingsListener = addSettingsListener(view.displayStyle); + }); + + const removeStyleListener = addStyleListener(this.view); + + const removeViewListener = this.onChangeView.addListener((vp) => { + listener(vp.view.displayStyle.settings.analysisStyle); + removeStyleListener(); + addStyleListener(vp.view); + }); + + return () => { + removeSettingsListener(); + removeStyleListener(); + removeViewListener(); + }; + } + + /** TileUser implementation @internal */ + public get tileUserId(): number { + return this.viewportId; + } + + /** TileUser implementation @internal */ + public onRequestStateChanged(): void { + this.invalidateScene(); + } +} + +/** An interactive Viewport that exists within an HTMLDivElement. ScreenViewports can receive HTML events. + * To render the contents of a ScreenViewport, it must be added to the [[ViewManager]] via ViewManager.addViewport(). + * Every frame, the ViewManager will update the Viewport's state and re-render its contents if anything has changed. + * To halt this loop, use ViewManager.dropViewport() to remove the viewport from the ViewManager. + * + * A ScreenViewport internally owns significant WebGL resources which must be explicitly disposed of when the viewport is no longer needed. + * This is achieved by invoking the viewport's dispose() method. ViewManager.dropViewport() invokes dispose() on the viewport by default. + * + * The lifetime of a ScreenViewport typically follows a pattern: + * ``` + * 1. Application creates the viewport via ScreenViewport.create() + * 2. The viewport is added to the render loop via ViewManager.addViewport() + * 3. When the application is finished with the viewport, it removes it from the render loop and disposes of it via ViewManager.dropViewport(). + * ``` + * + * In some cases it may be useful to temporarily suspend a viewport's render loop. In this case the lifetime of the viewport proceeds as follows: + * ``` + * 1. Application creates the viewport via ScreenViewport.create() + * 2. The viewport is added to the render loop via ViewManager.addViewport() + * 3. At some point the render loop is suspended via ViewManager.dropViewport(viewport, false), indicating the viewport should not be disposed. + * 4. Optionally, resume rendering by returning to step 2. + * 5. When the application is finished with the viewport: + * 5a. If it is currently registered with the ViewManager, it is dropped and disposed of via ViewManager.dropViewport() + * 5b. Otherwise, it is disposed of by invoking its dispose() method directly. + * ``` + * @public + */ +export class ScreenViewport extends Viewport { + /** Settings that may be adjusted to control the way animations are applied to a [[ScreenViewport]] by methods like + * [[changeView]] and [[synchWithView]. + */ + public static animation = { + /** Duration of animations of viewing operations. */ + time: { + fast: BeDuration.fromSeconds(.5), + normal: BeDuration.fromSeconds(1.0), + slow: BeDuration.fromSeconds(1.25), + /** Duration used when zooming with the mouse wheel. */ + wheel: BeDuration.fromSeconds(.5), + }, + /** The easing function to use for view animations. */ + easing: Easing.Cubic.Out, + /** Pertains to view transitions that move far distances, but maintain the same view direction. + * In that case we zoom out, move the camera, and zoom back in rather than transitioning linearly to + * provide context for the starting and ending positions. These settings control how and when that happens. + */ + zoomOut: { + /** Whether to allow zooming out. If you don't want it, set this to false. */ + enable: true, + /** The interpolation function used for camera height and position over the zoomOut operation. */ + interpolation: Interpolation.Bezier, + /** Array of fractional height the camera rises over the animation. Height is interpolated over the array during the duration of the zoom operation. + * At 1.0 it will be high enough that both are visible if the camera were centered between then. + * Must start and end at 0. + */ + heights: [0, 1.5, 2.0, 1.8, 1.5, 1.2, 1, 0], + /** Array of fractional positions of the camera from starting to ending location when zooming. + * Position is interpolated from the array using the interpolation function over the duration of the zoom operation (see tween.ts) + * Must start at 0 and end at 1. + */ + positions: [0, 0, .1, .3, .5, .8, 1], + /** Zoom out/in only if the beginning and ending view's range, each expanded by this factor, overlap. */ + margin: 2.5, + /** Multiply the duration of the animation by this factor when performing a zoom out. */ + durationFactor: 1.5, + }, + }; + + private _evController?: EventController; + private _viewCmdTargetCenter?: Point3d; + /** The number of entries in the view undo/redo buffer. */ + public maxUndoSteps = 20; + private readonly _forwardStack: ViewPose[] = []; + private readonly _backStack: ViewPose[] = []; + private _currentBaseline?: ViewPose; + private _lastPose?: ViewPose; // the pose the last time this view was rendered + private _webglCanvas?: HTMLCanvasElement; + private _logo!: HTMLImageElement; + private readonly _decorationCache = new DecorationsCache(); + + /** The parent HTMLDivElement of the canvas. */ + public readonly parentDiv: HTMLDivElement; + /** The div created to hold all viewport elements. */ + public readonly vpDiv: HTMLDivElement; + /** The canvas to display the view contents. */ + public readonly canvas: HTMLCanvasElement; + /** The HTMLDivElement used for HTML decorations. May be referenced from the DOM by class "overlay-decorators". + * @internal + */ + public readonly decorationDiv: HTMLDivElement; + /** The HTMLDivElement used for toolTips. May be referenced from the DOM by class "overlay-tooltip". */ + public readonly toolTipDiv: HTMLDivElement; + + /** Create a new ScreenViewport that shows a View of an iModel into an HTMLDivElement. This method will create a new HTMLCanvasElement as a child of the supplied parentDiv. + * It also creates two new child HTMLDivElements: one of class "overlay-decorators" for HTML overlay decorators, and one of class + * "overlay-tooltip" for ToolTips. All the new child HTMLElements are the same size as the parentDiv. + * @param parentDiv The HTMLDivElement to contain the ScreenViewport. The element must have non-zero width and height. + * @param view The ViewState for the ScreenViewport. + * @note After creating a new ScreenViewport, you must call [[ViewManager.addViewport]] for it to become "live". You must also ensure you dispose of it properly. + * @throws Error if `parentDiv` has zero width or height. + */ + public static create(parentDiv: HTMLDivElement, view: ViewState): ScreenViewport { + if (0 === parentDiv.clientWidth || 0 === parentDiv.clientHeight) + throw new Error("viewport cannot be created from a div with zero width or height"); + + const canvas = document.createElement("canvas"); + const vp = new this(canvas, parentDiv, IModelApp.renderSystem.createTarget(canvas)); + vp.changeView(view); + return vp; + } + + /** @internal */ + public override dispose(): void { + super.dispose(); + this._decorationCache.clear(); + } + + /** @internal */ + public override invalidateScene(): void { + super.invalidateScene(); + + // When the scene is invalidated, so are all cached decorations - they will be regenerated. + this._decorationCache.clear(); + } + + /** Forces removal of a specific decorator's cached decorations from this viewport, if they exist. + * This will force those decorations to be regenerated. + * @see [[ViewportDecorator.useCachedDecorations]]. + */ + public invalidateCachedDecorations(decorator: ViewportDecorator) { + this._decorationCache.delete(decorator); + + // Always invalidate decorations. Decorator may have no cached decorations currently, but wants them created. + this.invalidateDecorations(); + } + + /** @internal */ + public static markAllChildrenForRemoval(el: HTMLDivElement) { + for (const child of el.children) + child[ELEMENT_MARKED_FOR_REMOVAL] = true; + } + + /** @internal */ + public static removeMarkedChildren(el: HTMLDivElement) { + for (const child of [...el.children]) // spread to duplicate the HTMLCollection which is invalidated by removals + if (child[ELEMENT_MARKED_FOR_REMOVAL]) + el.removeChild(child); + } + + /** Remove all of the children of an HTMLDivElement. + * @internal + */ + public static removeAllChildren(el: HTMLDivElement) { + while (el.lastChild) + el.removeChild(el.lastChild); + } + + /** set Div style to absolute, {0,0,100%,100%} + * @internal + */ + public static setToParentSize(div: HTMLElement) { + const style = div.style; + style.position = "absolute"; + style.top = style.left = "0"; + style.height = style.width = "100%"; + } + + /** add a child element to this.vpDiv and set its size and position the same as the parent. */ + private addChildDiv(parent: HTMLElement, element: HTMLElement, zIndex: number) { + ScreenViewport.setToParentSize(element); + element.style.zIndex = zIndex.toString(); + parent.appendChild(element); + } + + /** @internal */ + public addNewDiv(className: string, overflowHidden: boolean, z: number): HTMLDivElement { + const div = document.createElement("div"); + div.className = className; + div.style.pointerEvents = "none"; + div.style.overflow = overflowHidden ? "hidden" : "visible"; + this.addChildDiv(this.vpDiv, div, z); + return div; + } + + /** The HTMLImageElement of the iTwin.js logo displayed in this ScreenViewport + * @beta + */ + public get logo() { return this._logo; } + + /** @internal */ + protected addLogo() { + const logo = this._logo = IModelApp.makeHTMLElement("img", { parent: this.vpDiv, className: "imodeljs-icon" }); + logo.src = `${IModelApp.publicPath}images/imodeljs-icon.svg`; + logo.alt = ""; + + const showLogos = (ev: Event) => { + const aboutBox = IModelApp.makeModalDiv({ autoClose: true, width: 460, closeBox: true, rootDiv: this.vpDiv.ownerDocument.body }).modal; + aboutBox.className += " imodeljs-about"; // only added so the CSS knows this is the about dialog + const logos = IModelApp.makeHTMLElement("table", { parent: aboutBox, className: "logo-cards" }); + if (undefined !== IModelApp.applicationLogoCard) + logos.appendChild(IModelApp.applicationLogoCard()); + logos.appendChild(IModelApp.makeIModelJsLogoCard()); + this.forEachTileTreeRef((ref) => ref.addLogoCards(logos, this)); + ev.stopPropagation(); + }; + logo.onclick = showLogos; + logo.addEventListener("touchstart", showLogos); + logo.onmousemove = logo.onmousedown = logo.onmouseup = (ev) => ev.stopPropagation(); + } + + /** @internal */ + protected constructor(canvas: HTMLCanvasElement, parentDiv: HTMLDivElement, target: RenderTarget) { + super(target); + this.canvas = canvas; + this.parentDiv = parentDiv; + + // first remove all children of the parent Div + ScreenViewport.removeAllChildren(parentDiv); + + const div = this.vpDiv = IModelApp.makeHTMLElement("div", { className: "imodeljs-vp" }); + this.addChildDiv(this.parentDiv, div, 0); + + this.addChildDiv(this.vpDiv, canvas, 10); + this.target.updateViewRect(); + + // SEE: decorationDiv doc comment + // eslint-disable-next-line deprecation/deprecation + this.decorationDiv = this.addNewDiv("overlay-decorators", true, 30); + this.toolTipDiv = this.addNewDiv("overlay-tooltip", true, 40); + this.setCursor(); + this.addLogo(); + } + + /** Open the toolTip window in this ScreenViewport with the supplied message and location. The tooltip will be a child of [[ScreenViewport.toolTipDiv]]. + * @param message The message to display + * @param location The position of the toolTip, in view coordinates. If undefined, use center of view. + * @param options the ToolTip options + * @note There is only one ToolTip window, so calling this method more than once will move the toolTip and show the second message. + */ + public openToolTip(message: HTMLElement | string, location?: XAndY, options?: ToolTipOptions) { + IModelApp.notifications.openToolTip(this.toolTipDiv, message, location, options); + } + + /** @internal */ + public mousePosFromEvent(ev: MouseEvent): XAndY { + const rect = this.getClientRect(); + return { x: ev.clientX - rect.left, y: ev.clientY - rect.top }; + } + + /** @internal */ + public mouseMovementFromEvent(ev: MouseEvent): XAndY { + return { x: ev.movementX, y: ev.movementY }; + } + + /** Set the event controller for this Viewport. Destroys previous controller, if one was defined. */ + public setEventController(controller?: EventController) { + if (this._evController) + this._evController.destroy(); + + this._evController = controller; + } + + /** Find a point on geometry visible in this Viewport, within a radius of supplied pick point. + * @param pickPoint Point to search about, in world coordinates + * @param radius Radius, in pixels, of the circular area to search. + * @param allowNonLocatable If true, include geometry with non-locatable flag set. + * @param out Optional Point3d to hold the result. If undefined, a new Point3d is returned. + * @returns The point, in world coordinates, on the element closest to `pickPoint`, or undefined if no elements within `radius`. + */ + public pickNearestVisibleGeometry(pickPoint: Point3d, radius?: number, allowNonLocatable = true, out?: Point3d): Point3d | undefined { + const depthResult = this.pickDepthPoint(pickPoint, radius, { excludeNonLocatable: !allowNonLocatable }); + let isValidDepth = false; + switch (depthResult.source) { + case DepthPointSource.Geometry: + case DepthPointSource.Model: + case DepthPointSource.Map: + isValidDepth = true; + break; + case DepthPointSource.BackgroundMap: + case DepthPointSource.GroundPlane: + case DepthPointSource.Grid: + case DepthPointSource.ACS: + const npcPt = this.worldToNpc(depthResult.plane.getOriginRef()); + isValidDepth = !(npcPt.z < 0.0 || npcPt.z > 1.0); + break; + } + if (!isValidDepth) + return undefined; + const result = undefined !== out ? out : new Point3d(); + result.setFrom(depthResult.plane.getOriginRef()); + return result; + } + + /** @internal */ + public picker = new ElementPicker(); // Picker used in pickDepthPoint below so it hangs around and can be queried later. + + /** Find a point on geometry visible in this Viewport, within a radius of supplied pick point. + * If no geometry is selected, return the point projected to the most appropriate reference plane. + * @param pickPoint Point to search about, in world coordinates + * @param radius Radius, in pixels, of the circular area to search. + * @param options Optional settings to control what can be selected. + * @returns A plane with origin from closest geometry point or reference plane projection and the source of the depth point. + * @note The result plane normal is valid when the source is not geometry or a reality model. + */ + public pickDepthPoint(pickPoint: Point3d, radius?: number, options?: DepthPointOptions): { plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource, sourceId?: string } { + if (!this.view.is3d()) + return { plane: Plane3dByOriginAndUnitNormal.createXYPlane(pickPoint), source: DepthPointSource.ACS }; + + if (undefined === radius) + radius = this.pixelsFromInches(ToolSettings.viewToolPickRadiusInches); + + this.picker.empty(); + const locateOpts = new LocateOptions(); + locateOpts.allowNonLocatable = (undefined === options || !options.excludeNonLocatable); + locateOpts.allowDecorations = (undefined === options || !options.excludeDecorations); + locateOpts.allowExternalIModels = (undefined === options || !options.excludeExternalIModels); + locateOpts.preserveModelDisplayTransforms = true; + + if (0 !== this.picker.doPick(this, pickPoint, radius, locateOpts)) { + const hitDetail = this.picker.getHit(0)!; + const hitPoint = hitDetail.getPoint(); + if (hitDetail.isModelHit) + return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Model, sourceId: hitDetail.sourceId }; + else if (hitDetail.isMapHit) + return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Map, sourceId: hitDetail.sourceId }; + return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getZVector())!, source: DepthPointSource.Geometry, sourceId: hitDetail.sourceId }; + } + + const eyePoint = this.worldToViewMap.transform1.columnZ(); + const direction = Vector3d.createFrom(eyePoint); + const aa = Geometry.conditionalDivideFraction(1, eyePoint.w); + if (aa !== undefined) { + const xyzEye = direction.scale(aa); + direction.setFrom(pickPoint.vectorTo(xyzEye)); + } + + direction.scaleToLength(-1.0, direction); + const boresiteIntersectRay = Ray3d.create(pickPoint, direction); + const projectedPt = Point3d.createZero(); + + const backgroundMapGeometry = this.backgroundMapGeometry; + if (undefined !== backgroundMapGeometry) { + const intersect = backgroundMapGeometry.getRayIntersection(boresiteIntersectRay, false); + + if (undefined !== intersect) { + const npcPt = this.worldToNpc(intersect.origin); + if (npcPt.z < 1) // Only if in front of eye. + return { plane: Plane3dByOriginAndUnitNormal.create(intersect.origin, intersect.direction)!, source: DepthPointSource.BackgroundMap }; + } + } + // returns true if there's an intersection that isn't behind the front plane + const boresiteIntersect = (plane: Plane3dByOriginAndUnitNormal) => { + const dist = boresiteIntersectRay.intersectionWithPlane(plane, projectedPt); + if (undefined === dist) + return false; + const npcPt = this.worldToNpc(projectedPt); + return npcPt.z < 1.0; + }; + + if (this.view.getDisplayStyle3d().environment.displayGround) { + const groundPlane = Plane3dByOriginAndUnitNormal.create(Point3d.create(0, 0, this.view.getGroundElevation()), Vector3d.unitZ()); + if (undefined !== groundPlane && boresiteIntersect(groundPlane)) + return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, groundPlane.getNormalRef())!, source: DepthPointSource.GroundPlane }; + } + + const acsPlane = Plane3dByOriginAndUnitNormal.create(this.getAuxCoordOrigin(), this.getAuxCoordRotation().getRow(2)); + if (undefined !== acsPlane && boresiteIntersect(acsPlane)) + return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, acsPlane.getNormalRef())!, source: (this.isGridOn && GridOrientationType.AuxCoord === this.view.getGridOrientation() ? DepthPointSource.Grid : DepthPointSource.ACS) }; + + const targetPointNpc = this.worldToNpc(this.view.getTargetPoint()); + if (targetPointNpc.z < 0.0 || targetPointNpc.z > 1.0) + targetPointNpc.z = 0.5; + + this.worldToNpc(pickPoint, projectedPt); projectedPt.z = targetPointNpc.z; this.npcToWorld(projectedPt, projectedPt); + return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, this.view.getZVector())!, source: DepthPointSource.TargetPoint }; + } + + /** @internal */ + public animateFrustumChange(options?: ViewAnimationOptions) { + if (this._lastPose && this._currentBaseline) + this.setAnimator(new FrustumAnimator(options ? options : {}, this, this._lastPose, this.view.savePose())); + } + + /** Animate the view frustum from a starting frustum to the current view frustum. In other words, + * save a starting frustum (presumably what the user is currently looking at), then adjust the view to + * a different location and call synchWithView, then call this method. After the animation the viewport + * frustum will be restored to its current location. + * @internal + */ + public animateToCurrent(_start: Frustum, options?: ViewAnimationOptions) { + options = options ? options : {}; + this.animateFrustumChange(/* start, this.getFrustum(), */ options); + } + + /** Animate the view frustum to a destination location the earth from the current frustum. */ + public async animateFlyoverToGlobalLocation(destination: GlobalLocation) { + const animator = await GlobeAnimator.create(this, destination); + this.setAnimator(animator); + } + + /** @internal */ + public pickCanvasDecoration(pt: XAndY) { return this.target.pickOverlayDecoration(pt); } + + /** Get the DOMRect of the canvas for this Viewport. */ + public getClientRect(): DOMRect { return this.canvas.getBoundingClientRect(); } + + /** The ViewRect for this ScreenViewport. Left and top will be 0, right will be the width, and bottom will be the height. */ + public get viewRect(): ViewRect { this._viewRange.init(0, 0, this.canvas.clientWidth, this.canvas.clientHeight); return this._viewRange; } + + /** @internal */ + protected override addDecorations(decorations: Decorations): void { + // SEE: decorationDiv doc comment + // eslint-disable-next-line deprecation/deprecation + ScreenViewport.markAllChildrenForRemoval(this.decorationDiv); + const context = new DecorateContext(this, decorations, this._decorationCache); + try { + // It is an error to try to remove cached decorations while we are decorating. + // Some naughty decorators unwittingly do so by e.g. invalidating the scene in their decorate method. + this._decorationCache.prohibitRemoval = true; + + context.addFromDecorator(this.view); + this.forEachTiledGraphicsProviderTree((ref) => context.addFromDecorator(ref)); + + for (const decorator of IModelApp.viewManager.decorators) + context.addFromDecorator(decorator); + + // eslint-disable-next-line deprecation/deprecation + ScreenViewport.removeMarkedChildren(this.decorationDiv); + } finally { + this._decorationCache.prohibitRemoval = false; + } + } + + /** Change the cursor for this Viewport */ + public setCursor(cursor: string = "default"): void { + this.canvas.style.cursor = cursor; + } + + /** @internal */ + public override synchWithView(options?: ViewChangeOptions): void { + options = options ?? {}; + + if (this.view.is3d() && options?.globalAlignment) + this.view.alignToGlobe(options.globalAlignment.target, options.globalAlignment.transition); + + super.synchWithView(options); + + if (true !== options.noSaveInUndo) + this.saveViewUndo(); + if (true === options.animateFrustumChange) + this.animateFrustumChange(options); + } + + /** @internal */ + protected override validateRenderPlan() { + super.validateRenderPlan(); + this._lastPose = this.view.savePose(); + } + + /** Change the ViewState of this Viewport + * @param view a fully loaded (see discussion at [[ViewState.load]] ) ViewState + * @param opts options for how the view change operation should work + */ + public override changeView(view: ViewState, opts?: ViewChangeOptions) { + if (view === this.view) // nothing to do + return; + + this.setAnimator(undefined); // make sure we clear any active animators before we change views. + + opts = opts ?? { animationTime: ScreenViewport.animation.time.slow.milliseconds }; + + // determined whether we can animate this ViewState change + const doAnimate = this.view && this.view.hasSameCoordinates(view) && false !== opts.animateFrustumChange; + if (!doAnimate) + this.clearViewUndo(); // if we can animate, don't throw out view undo. + + super.changeView(view, opts); + this.saveViewUndo(); + + if (doAnimate) + this.animateFrustumChange(opts); + } + + /** @internal */ + public get viewCmdTargetCenter(): Point3d | undefined { return this._viewCmdTargetCenter; } + public set viewCmdTargetCenter(center: Point3d | undefined) { this._viewCmdTargetCenter = center ? center.clone() : undefined; } + /** True if an undoable viewing operation exists on the stack */ + public get isUndoPossible(): boolean { return 0 < this._backStack.length; } + + /** True if a redoable viewing operation exists on the stack */ + public get isRedoPossible(): boolean { return 0 < this._forwardStack.length; } + + /** Clear the undo buffers of this Viewport. This resets the undo stack. */ + public clearViewUndo(): void { + this._currentBaseline = undefined; + this._forwardStack.length = 0; + this._backStack.length = 0; + this._lastPose = undefined; + } + + /** Saves the current state of this viewport's [[ViewState]] in the undo stack, such that it can be restored by a call to [[ScreenViewport.doUndo]]. */ + public saveViewUndo(): void { + if (this._inViewChangedEvent) // echo from a view changed event. + return; + + // the first time we're called we need to establish the baseline + if (!this._currentBaseline) + this._currentBaseline = this.view.savePose(); + + if (this._currentBaseline.equalState(this.view)) + return; // nothing changed, we're done + + const backStack = this._backStack; + if (backStack.length >= this.maxUndoSteps) // don't save more than max + backStack.shift(); // remove the oldest entry + + /** Sometimes we get requests to save undo entries from rapid viewing operations (e.g. mouse wheel rolls). To avoid lots of + * little useless intermediate view undo steps that mean nothing, if we get a call to this within a minimum time (1/2 second by default) + * we don't add a new entry to the view undo buffer. + */ + const now = BeTimePoint.now(); + if (Viewport.undoDelay.isZero || backStack.length < 1 || backStack[backStack.length - 1].undoTime!.plus(Viewport.undoDelay).before(now)) { + this._currentBaseline.undoTime = now; // save time we put this entry in undo buffer + this._backStack.push(this._currentBaseline); // save previous state + this._forwardStack.length = 0; // not possible to do redo after this + } + + this._currentBaseline = this.view.savePose(); + } + + /** Reverses the most recent change to the Viewport from the undo stack. */ + public doUndo(animationTime?: BeDuration) { + if (0 === this._backStack.length || this._currentBaseline === undefined) + return; + + this._forwardStack.push(this._currentBaseline); + this._currentBaseline = this._backStack.pop()!; + this.view.applyPose(this._currentBaseline); + this.finishUndoRedo(animationTime); + this.onViewUndoRedo.raiseEvent(this, ViewUndoEvent.Undo); + } + + /** Re-applies the most recently un-done change to the Viewport from the redo stack. */ + public doRedo(animationTime?: BeDuration) { + if (0 === this._forwardStack.length || this._currentBaseline === undefined) + return; + + this._backStack.push(this._currentBaseline); + this._currentBaseline = this._forwardStack.pop()!; + this.view.applyPose(this._currentBaseline); + this.finishUndoRedo(animationTime); + this.onViewUndoRedo.raiseEvent(this, ViewUndoEvent.Redo); + } + + /** @internal */ + private finishUndoRedo(duration?: BeDuration): void { + this.updateChangeFlags(this.view); + this.setupFromView(); + if (undefined !== duration) + this.animateFrustumChange({ animationTime: duration.milliseconds }); + } + + /** Clear the view undo buffer and establish the current ViewState as the new baseline. */ + public resetUndo() { + this.clearViewUndo(); + this.saveViewUndo(); // Set up new baseline state + } + + /** Show the surface normal for geometry under the cursor when snapping. */ + private static drawLocateHitDetail(context: DecorateContext, aperture: number, hit: HitDetail): void { + if (!context.viewport.view.is3d()) + return; // Not valuable feedback in 2d... + + if (!(hit instanceof SnapDetail) || !hit.normal || hit.isPointAdjusted) + return; // AccuSnap will flash edge/segment geometry if not a surface hit or snap location has been adjusted... + + const builder = context.createGraphicBuilder(GraphicType.WorldOverlay); + const color = context.viewport.hilite.color.inverse().withTransparency(100); // Invert hilite color for good contrast + const colorFill = color.withTransparency(200); + + builder.setSymbology(color, colorFill, 1); + + const skew = context.viewport.view.getAspectRatioSkew(); + const radius = (2.5 * aperture) * context.viewport.getPixelSizeAtPoint(hit.snapPoint); + const rMatrix = Matrix3d.createRigidHeadsUp(hit.normal); + const ellipse = Arc3d.createScaledXYColumns(hit.snapPoint, rMatrix, radius, radius / skew, AngleSweep.create360()); + + builder.addArc(ellipse, true, true); + builder.addArc(ellipse, false, false); + + const lengthX = (0.6 * radius); + const lengthY = lengthX / skew; + const normal = Vector3d.create(); + + ellipse.vector0.normalize(normal); + const pt1 = hit.snapPoint.plusScaled(normal, lengthX); + const pt2 = hit.snapPoint.plusScaled(normal, -lengthX); + builder.addLineString([pt1, pt2]); + + ellipse.vector90.normalize(normal); + const pt3 = hit.snapPoint.plusScaled(normal, lengthY); + const pt4 = hit.snapPoint.plusScaled(normal, -lengthY); + builder.addLineString([pt3, pt4]); + + context.addDecorationFromBuilder(builder); + } + + /** @internal */ + public drawLocateCursor(context: DecorateContext, viewPt: Point3d, aperture: number, isLocateCircleOn: boolean, hit?: HitDetail): void { + if (hit) + ScreenViewport.drawLocateHitDetail(context, aperture, hit); + + if (isLocateCircleOn) { + // draw a filled and outlined circle to represent the size of the location aperture in the current view. + const radius = Math.floor(aperture * 0.5) + 0.5; + const position = viewPt.clone(); + position.x = Math.floor(position.x) + 0.5; + position.y = Math.floor(position.y) + 0.5; + const drawDecoration = (ctx: CanvasRenderingContext2D) => { + ctx.beginPath(); + ctx.strokeStyle = "rgba(255,255,255,.4)"; + ctx.fillStyle = "rgba(255,255,255,.2)"; + ctx.arc(0, 0, radius, 0, 2 * Math.PI); + ctx.fill(); + ctx.stroke(); + ctx.beginPath(); + ctx.strokeStyle = "rgba(0,0,0,.8)"; + ctx.lineWidth = 1; + ctx.arc(0, 0, radius + 1, 0, 2 * Math.PI); + ctx.stroke(); + }; + context.addCanvasDecoration({ position, drawDecoration }, true); + } + } + + /** By default, a Viewport's webgl content is rendered to an off-screen canvas owned by the RenderSystem, then the resultant image is copied to the 2d rendering context + * belonging to the Viewport's own canvas. However, on non-chromium-based browsers this copying incurs a significant performance penalty. So, when only one Viewport + * needs to be drawn, we can switch to rendering the webgl content directly to the screen to improve performance in those browsers. + * ViewManager takes care of toggling this behavior. + * @internal + */ + public get rendersToScreen(): boolean { return undefined !== this._webglCanvas; } + public set rendersToScreen(toScreen: boolean) { + if (toScreen === this.rendersToScreen) + return; + + // Returns a webgl canvas if we're rendering webgl directly to the screen. + const webglCanvas = this.target.setRenderToScreen(toScreen); + if (undefined === webglCanvas) { + assert(undefined !== this._webglCanvas); // see getter... + this.vpDiv.removeChild(this._webglCanvas); + this._webglCanvas = undefined; + } else { + assert(undefined === this._webglCanvas); // see getter... + this._webglCanvas = webglCanvas; + + this.addChildDiv(this.vpDiv, webglCanvas, 5); + + /** We really want this WebGL canvas' zIndex to be lower than this.canvas, but if we do that, browsers can decide to + * not update the WebGL canvas contents once it is re-added to the parent div after dropping other viewports. + * The offending element is the 2d canvas sitting on top of the WebGL canvas. We need to clear the 2d canvas' contents + * in order to ensure browsers allow the underlying WebGL canvas to update. If a decorator is present, the 2d canvas + * is cleared during the frame render process by virtue of updating the decorator. For the non-decorator case, and for + * iOS, we must make sure we still clear the 2d canvas, done here. iOS appears to need this clear even when decorators + * clear the canvas later in the frame render process. + */ + _clear2dCanvas(this.canvas); + } + + this.target.updateViewRect(); + this.invalidateRenderPlan(); + } +} + +function _clear2dCanvas(canvas: HTMLCanvasElement) { + const ctx = canvas.getContext("2d", { alpha: true })!; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); // revert any previous devicePixelRatio scale for clearRect() call below. + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.restore(); +} + +/** Options supplied when creating an [[OffScreenViewport]]. + * @see [[OffScreenViewport.create]]. + * @public + */ +export interface OffScreenViewportOptions { + /** The view to be drawn in the viewport. */ + view: ViewState; + /** The dimensions of the viewport. */ + viewRect: ViewRect; + /** If true, the viewport's aspect ratio will remain fixed. */ + lockAspectRatio?: boolean; +} + +/** A viewport that draws to an offscreen buffer instead of to the screen. An offscreen viewport is never added to the [[ViewManager]], therefore does not participate in + * the render loop. Its dimensions are specified directly instead of being derived from an HTMLCanvasElement, and its renderFrame function must be manually invoked. + * Offscreen viewports can be useful for, e.g., producing an image from the contents of a view (see [[Viewport.readImageBuffer]] and [[Viewport.readImageToCanvas]]) + * without drawing to the screen. + * @public + */ +export class OffScreenViewport extends Viewport { + protected _isAspectRatioLocked = false; + /** @internal see AttachToViewportArgs.drawingToSheetTransform. */ + private _drawingToSheetTransform?: Transform; + /** @internal see AttachToViewportArgs.drawingToSheetTransform. */ + public get drawingToSheetTransform(): Transform | undefined { + return this._drawingToSheetTransform; + } + public set drawingToSheetTransform(transform: Transform | undefined) { + this.detachFromView(); + this._drawingToSheetTransform = transform; + this.attachToView(); + } + + public static create(options: OffScreenViewportOptions): OffScreenViewport { + return this.createViewport(options.view, IModelApp.renderSystem.createOffscreenTarget(options.viewRect), options.lockAspectRatio); + } + + /** @internal because RenderTarget is internal */ + public static createViewport(view: ViewState, target: RenderTarget, lockAspectRatio = false): OffScreenViewport { + const vp = new this(target); + vp._isAspectRatioLocked = lockAspectRatio; + vp.changeView(view); + vp._decorationsValid = true; + return vp; + } + + /** @internal */ + public override get isAspectRatioLocked(): boolean { + return this._isAspectRatioLocked; + } + + /** @internal */ + public override get viewRect(): ViewRect { + return this.target.viewRect; + } + + /** Change the dimensions of the viewport. */ + public setRect(rect: ViewRect): void { + this.target.setViewRect(rect, false); + this.changeView(this.view); + } +} diff --git a/core/frontend/src/core-frontend.ts b/core/frontend/src/core-frontend.ts index abd612973e84..02af1d622fd3 100644 --- a/core/frontend/src/core-frontend.ts +++ b/core/frontend/src/core-frontend.ts @@ -11,6 +11,7 @@ export * from "./BriefcaseConnection"; export * from "./BriefcaseTxns"; export * from "./CategorySelectorState"; export * from "./ChangeFlags"; +export * from "./CheckpointConnection"; export * from "./ContextRealityModelState"; export * from "./CoordSystem"; export * from "./DecorationsCache"; @@ -21,6 +22,7 @@ export * from "./ElementLocateManager"; export * from "./EmphasizeElements"; export * from "./EntityState"; export * from "./EnvironmentDecorations"; +export * from "./extension/extensions"; export * from "./FeatureOverrideProvider"; export * from "./FlashSettings"; export * from "./FrontendLoggerCategory"; @@ -30,12 +32,12 @@ export * from "./FrustumAnimator"; export * from "./FuzzySearch"; export * from "./GeoServices"; export * from "./GlobeAnimator"; +export * from "./GraphicalEditingScope"; export * from "./HitDetail"; export * from "./ImageUtil"; export * from "./IModelApp"; export * from "./IModelConnection"; export * from "./IModelRoutingContext"; -export * from "./GraphicalEditingScope"; export * from "./IpcApp"; export * from "./LinePlaneIntersect"; export * from "./MarginPercent"; @@ -53,7 +55,6 @@ export * from "./quantity-formatting/BaseUnitFormattingSettingsProvider"; export * from "./quantity-formatting/LocalUnitFormatProvider"; export * from "./quantity-formatting/QuantityTypesEditorSpecs"; export * from "./RenderScheduleState"; -export * from "./CheckpointConnection"; export * from "./SelectionSet"; export * from "./SheetViewState"; export * from "./SpatialViewState"; @@ -103,8 +104,8 @@ export * from "./render/VisibleFeature"; export * from "./render/webgl/PerformanceMetrics"; export * from "./render/webgl/Target"; export * from "./render/webgl/IModelFrameLifecycle"; -export * from "./tools/AccuDrawTool"; export * from "./tile/internal"; +export * from "./tools/AccuDrawTool"; export * from "./tools/ClipViewTool"; export * from "./tools/EditManipulator"; export * from "./tools/ElementSetTool"; @@ -176,7 +177,7 @@ export * from "./RealityDataSource"; */ /** * @docs-group-description Extensions - * Classes for creating and managing runtime [Extensions]($docs/learning/frontend/Extensions.md) + * Classes for creating and managing Extensions. */ /** * @docs-group-description Properties @@ -224,4 +225,3 @@ export * from "./RealityDataSource"; * @docs-group-description MapLayers * Classes supporting map layers display. */ - diff --git a/core/frontend/src/extension/Extension.ts b/core/frontend/src/extension/Extension.ts new file mode 100644 index 000000000000..f24f678e3ac9 --- /dev/null +++ b/core/frontend/src/extension/Extension.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +/** + * @alpha + */ +export enum ActivationEvent { + onStartup = "onStartup", +} + +/** + * @alpha + */ +export type ResolveFunc = () => Promise; + +/** Defines the format of an Extension manifest + * @alpha +*/ +export interface ExtensionManifest { + /** The extension name */ + readonly name: string; + /** The extension display name */ + readonly displayName?: string; + /** The extension version */ + readonly version: string; + /** The extension description */ + readonly description?: string; + /** The main module file to load. This should be a path to the javascript file + * e.g "./lib/main.js" + */ + readonly main: string; + /** List of activation events this Extension supports. */ + readonly activationEvents: ActivationEvent[]; +} + +/** @alpha */ +export interface BuildExtensionManifest extends ExtensionManifest { + /** Only valid when the Extension is loaded at build-time. + * + * Defines the main ES module that will be imported + */ + readonly module: string; +} + +/** Describes an Extension that has already been downloaded and has a location files can be easily executed. + * @alpha +*/ +export interface LocalExtensionProps { + readonly manifest: ExtensionManifest; + readonly mainFunc?: ResolveFunc; +} diff --git a/core/frontend/src/extension/ExtensionAdmin.ts b/core/frontend/src/extension/ExtensionAdmin.ts new file mode 100644 index 000000000000..0749a5d07add --- /dev/null +++ b/core/frontend/src/extension/ExtensionAdmin.ts @@ -0,0 +1,115 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +import { IModelApp } from "../IModelApp"; +import { ActivationEvent, BuildExtensionManifest, ExtensionManifest, LocalExtensionProps, ResolveFunc } from "./Extension"; +import { ExtensionLoader } from "./ExtensionLoader"; + +/** The Extensions loading system has the following goals: + * 1. Only fetch what is needed when it is required + * 1. Load a manifest file + * 2. Load the the main module when necessary + * 2. Download the extension's files + * + * 2 ways to load an Extension into the system: + * + * 1. At build-time provide the function to load both the Extension Manifest and import the main module of the extension. + * The main module must contain the activate() function. + * 2. A minimum set of ExtensionLoaderProps that provide enough information to get the manifest + * + * An Extension can be in 3 different states: + * - Known + * - The Extension Admin has the minimal information needed to fetch the manifest for the Extension. + * knows the Extension exists but has not yet loaded the manifest + * - Installed + * - The Extension has the full manifest loaded and can be executed on the activation events + * - Disabled + * - The Extension has the full manifest but is not currently enabled and will not be executed based on the + * activation events. + */ + +/** The Extension Admin controls the list of currently known, loaded and executing an Extension. + * Handles the loading of Extensions and maintains a list of the currently loaded Extensions. + * + * @alpha + */ +export class ExtensionAdmin { + /** The list of places to download an Extension. */ + private _extensionLoaders: ExtensionLoader[] = []; + + /** Defines the set of extensions that are currently known and can be invoked during activation events. */ + private _installedExtensions: Map = new Map(); + + /** Fired when an Extension has been added or removed. + * @internal + */ + public onStartup = async () => { + await this.activateExtensionEvents(ActivationEvent.onStartup); + }; + + public constructor() { + IModelApp.onAfterStartup.addListener(this.onStartup); + } + + /** Add an ExtensionLoader to the front of the list of extension loaders. Extension loaders are invoked front to back. + * @param extensionLoader Extension loader to add + */ + public addExtensionLoaderFront(extensionLoader: ExtensionLoader) { + this._extensionLoaders.unshift(extensionLoader); + } + + /** Add an ExtensionLoader to the list of extension loaders in use. + * @param extensionLoader Extension loader to add + */ + public addExtensionLoader(extensionLoader: ExtensionLoader) { + this._extensionLoaders.push(extensionLoader); + } + + /** Add an Extension intend to be bundled during compilation. + * @param manifestLoader A function that loads the manifest file. + * @param mainFunc The main function to be executed upon + */ + public async addBuildExtension(manifestPromise: Promise, mainFunc?: ResolveFunc): Promise { + const manifest = await this.getManifest(manifestPromise); + this._installedExtensions.set(manifest.name, { manifest, mainFunc }); + } + + /** Loops over all enabled Extensions and triggers each one if the provided event is defined. */ + private async activateExtensionEvents(event: string) { + for (const extension of this._installedExtensions.values()) { + if (!extension.manifest.activationEvents) + continue; + for (const activationEvent of extension.manifest.activationEvents) { + if (activationEvent === event) { + this.execute(extension); // eslint-disable-line @typescript-eslint/no-floating-promises + } + } + } + } + + /** Resolves an import function provided for build-time Extensions that should return a valid + * Extension Manifest. + */ + private async getManifest(loader: Promise): Promise { + const manifest = await loader; + return manifest; + } + + // Important: The Function constructor is used here to isolate the context in which the Extension javascript has access. + // By using the Function constructor to create and then execute the extension it will only have access to two scopes: + // 1. It's own function scope + // 2. The global scope + // + // The global scope is important for an Extension as that is where the reference to the Extension Implementation is supplied + // from the application side. + private async execute(extension: LocalExtensionProps): Promise { + if (extension.mainFunc) + return extension.mainFunc(); + } + +} diff --git a/core/frontend/src/extension/ExtensionHost.ts b/core/frontend/src/extension/ExtensionHost.ts new file mode 100644 index 000000000000..0d9442449ffb --- /dev/null +++ b/core/frontend/src/extension/ExtensionHost.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +import { IModelApp } from "../IModelApp"; +import type { ToolAdmin } from "../tools/ToolAdmin"; +import type { AccuSnap } from "../AccuSnap"; +import type { NotificationManager } from "../NotificationManager"; +import type { ViewManager } from "../ViewManager"; +import type { ElementLocateManager } from "../ElementLocateManager"; +import type { RenderSystem } from "../render/RenderSystem"; + +/** + * Subset of IModelApp exposed to Extensions + * @alpha + */ +export class ExtensionHost { + protected constructor() { } + + public static get toolAdmin(): ToolAdmin { return IModelApp.toolAdmin; } + public static get notifications(): NotificationManager { return IModelApp.notifications; } + public static get viewManager(): ViewManager { return IModelApp.viewManager; } + public static get locateManager(): ElementLocateManager { return IModelApp.locateManager; } // internal ? + public static get accuSnap(): AccuSnap { return IModelApp.accuSnap; } + public static get renderSystem(): RenderSystem { return IModelApp.renderSystem; } // re think this, should be smaller interface +} diff --git a/core/frontend/src/extension/ExtensionImpl.ts b/core/frontend/src/extension/ExtensionImpl.ts new file mode 100644 index 000000000000..520019dfc883 --- /dev/null +++ b/core/frontend/src/extension/ExtensionImpl.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +import { ToolType } from "../tools/Tool"; +import { IModelApp } from "../IModelApp"; +import { CommonToolbarItem, StageUsage, ToolbarItemUtilities, ToolbarOrientation, ToolbarUsage, UiItemsManager, UiItemsProvider } from "@itwin/appui-abstract"; + +/** @alpha */ +export class ToolProvider implements UiItemsProvider { + public readonly id; + private _toolId = ""; + private _toolIcon; + private _toolLabel; + + public constructor(tool: ToolType) { + this.id = `ToolProvider:${tool.toolId}`; + this._toolId = tool.toolId; + this._toolIcon = tool.iconSpec; + this._toolLabel = tool.description; + } + + public provideToolbarButtonItems(_stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation): CommonToolbarItem[] { + const toolbarItem = ToolbarItemUtilities.createActionButton(this._toolId, 0, this._toolIcon, this._toolLabel, async () => { await IModelApp.tools.run(this._toolId); }); + return stageUsage === StageUsage.General && toolbarUsage === ToolbarUsage.ContentManipulation && toolbarOrientation === ToolbarOrientation.Vertical ? [toolbarItem] : []; + } +} + +/** @alpha */ +export class ExtensionImpl { + constructor(private _id: string) { } + + public async registerTool(tool: ToolType, onRegistered?: () => any): Promise { + try { + IModelApp.tools.register(tool); + UiItemsManager.register(new ToolProvider(tool)); + onRegistered?.(); + } catch (e: any) { + console.log(`Error registering tool: ${e}`); // eslint-disable-line + } + } +} diff --git a/core/frontend/src/extension/ExtensionLoader.ts b/core/frontend/src/extension/ExtensionLoader.ts new file mode 100644 index 000000000000..7e2ec3bbc40d --- /dev/null +++ b/core/frontend/src/extension/ExtensionLoader.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +import { ExtensionManifest, LocalExtensionProps, ResolveFunc } from "./Extension"; + +/** The minimum information required to download an Extension + * @alpha +*/ +export interface ExtensionLoaderProps { + name: string; + version: string; +} + +/** @alpha */ +export interface BuiltInExtensionLoaderProps { + manifest: Promise; + loader: ResolveFunc; +} + +/** Describes what is needed in order to write an Extension Loader. + * @alpha + */ +export interface ExtensionLoader { + /** Retrieves an Extension manifest for the provided Extension identifier */ + getManifest(arg: ExtensionLoaderProps): Promise; + /** Downloads an Extension provided the name of the Extension */ + downloadExtension(arg: ExtensionLoaderProps): Promise; +} diff --git a/core/frontend/src/extension/ExtensionRuntime.ts b/core/frontend/src/extension/ExtensionRuntime.ts new file mode 100644 index 000000000000..65a1b9066d66 --- /dev/null +++ b/core/frontend/src/extension/ExtensionRuntime.ts @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Extensions + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import { + BackgroundFill, BackgroundMapType, BatchType, BisCodeSpec, BriefcaseIdValue, ChangedValueState, ChangeOpCode, ChangesetType, ColorByName, ColorDef, CommonLoggerCategory, + ECSqlSystemProperty, ECSqlValueType, ElementGeometryOpcode, FeatureOverrideType, FillDisplay, FillFlags, FontType, GeoCoordStatus, GeometryClass, GeometryStreamFlags, + GeometrySummaryVerbosity, GlobeMode, GridOrientationType, HSVConstants, ImageBufferFormat, ImageSourceFormat, LinePixels, MassPropertiesOperation, MonochromeMode, + Npc, PlanarClipMaskMode, PlanarClipMaskPriority, QueryRowFormat, Rank, RenderMode, SectionType, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, SyncMode, + TerrainHeightOriginMode, TextureMapUnits, TextureTransparency, ThematicDisplayMode, ThematicGradientColorScheme, ThematicGradientMode, TxnAction, TypeOfChange, +} from "@itwin/core-common"; +import { ExtensionImpl } from "./ExtensionImpl"; +import { ExtensionHost } from "./ExtensionHost"; + +import { AccuDrawHintBuilder, ContextRotationId } from "../AccuDraw"; +import { ACSDisplayOptions, ACSType } from "../AuxCoordSys"; +import { CoordSystem } from "../CoordSystem"; +import { LocateAction, LocateFilterStatus, LocateResponse, SnapStatus } from "../ElementLocateManager"; +import { FlashMode } from "../FlashSettings"; +import { FrontendLoggerCategory } from "../FrontendLoggerCategory"; +import { HitDetailType, HitGeomType, HitParentGeomType, HitPriority, HitSource, SnapHeat, SnapMode } from "../HitDetail"; +import { ActivityMessageEndReason, MessageBoxIconType, MessageBoxType, MessageBoxValue, NotifyMessageDetails, OutputMessageAlert, OutputMessagePriority, OutputMessageType } from "../NotificationManager"; +import { SelectionSetEventType } from "../SelectionSet"; +import { StandardViewId } from "../StandardView"; +import { ViewRect } from "../ViewRect"; +import { ViewStatus } from "../ViewStatus"; +import { DepthPointSource, ViewUndoEvent } from "../Viewport"; +import { GraphicType } from "../render/GraphicBuilder"; +import { Pixel } from "../render/Pixel"; +import { UniformType, VaryingType } from "../render/ScreenSpaceEffectBuilder"; +import { BingElevationProvider, readElementGraphics, TileBoundingBoxes, TileGraphicType, TileLoadPriority, TileLoadStatus, TileTreeLoadStatus, TileVisibility } from "../tile/internal"; +import { ClipEventType } from "../tools/ClipViewTool"; +import { PrimitiveTool } from "../tools/PrimitiveTool"; +import { SelectionMethod, SelectionMode, SelectionProcessing } from "../tools/SelectTool"; +import { BeButton, BeButtonEvent, BeModifierKeys, CoordinateLockOverrides, CoordSource, EventHandled, InputCollector, InputSource, InteractiveTool, KeyinParseError, ParseAndRunResult, Tool } from "../tools/Tool"; +import { ManipulatorToolEvent, StartOrResume } from "../tools/ToolAdmin"; +import { ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod } from "../tools/ToolAssistance"; +import { ViewTool } from "../tools/ViewTool"; +import { EditManipulator } from "../tools/EditManipulator"; +import { EmphasizeElements } from "../EmphasizeElements"; +import { FeatureSymbology } from "../render/FeatureSymbology"; +import { GraphicBranch } from "../render/GraphicBranch"; +import { canvasToImageBuffer, canvasToResizedCanvasWithBars, extractImageSourceDimensions, getCompressedJpegFromCanvas, getImageSourceFormatForMimeType, getImageSourceMimeType, + imageBufferToBase64EncodedPng, imageBufferToCanvas, imageBufferToPngDataUrl, imageElementFromImageSource, imageElementFromUrl } from "../ImageUtil"; +import { queryTerrainElevationOffset } from "../ViewGlobalLocation"; +import { BingLocationProvider } from "../BingLocation"; +import { FrustumAnimator } from "../FrustumAnimator"; +import { GlobeAnimator } from "../GlobeAnimator"; +import { MarginPercent } from "../MarginPercent"; +import { Cluster, Marker } from "../Marker"; + +const globalSymbol = Symbol.for("itwin.core.frontend.globals"); +if ((globalThis as any)[globalSymbol]) + throw new Error("Multiple @itwin/core-frontend imports detected!"); + +const getExtensionApi = (id: string) => { + return { + exports: { + // Tools + InteractiveTool, PrimitiveTool, ViewTool, Tool, + + ToolAssistance, BeButtonEvent, ViewRect, Pixel, LocateResponse, EditManipulator, AccuDrawHintBuilder, EmphasizeElements, FeatureSymbology, GraphicBranch, NotifyMessageDetails, + + ColorDef, + + // Frontend functions + getCompressedJpegFromCanvas, getImageSourceFormatForMimeType, getImageSourceMimeType, imageBufferToBase64EncodedPng, imageBufferToCanvas, imageBufferToPngDataUrl, + imageElementFromImageSource, imageElementFromUrl, queryTerrainElevationOffset, readElementGraphics, canvasToImageBuffer, canvasToResizedCanvasWithBars, extractImageSourceDimensions, + + // Frontend classes + BingElevationProvider, BingLocationProvider, InputCollector, FrustumAnimator, GlobeAnimator, MarginPercent, Marker, Cluster, + + ExtensionHost, + + ACSDisplayOptions, ACSType, ActivityMessageEndReason, BeButton, BeModifierKeys, ClipEventType, ContextRotationId, CoordinateLockOverrides, + CoordSource, CoordSystem, DepthPointSource, EventHandled, FlashMode, FrontendLoggerCategory, GraphicType, HitDetailType, HitGeomType, + HitParentGeomType, HitPriority, HitSource, InputSource, KeyinParseError, LocateAction, LocateFilterStatus, ManipulatorToolEvent, + MessageBoxIconType, MessageBoxType, MessageBoxValue, OutputMessageAlert, OutputMessagePriority, OutputMessageType, ParseAndRunResult, + SelectionMethod, SelectionMode, SelectionProcessing, SelectionSetEventType, SnapHeat, SnapMode, SnapStatus, StandardViewId, StartOrResume, + TextureTransparency, TileBoundingBoxes, TileGraphicType, TileLoadPriority, TileLoadStatus, TileTreeLoadStatus, TileVisibility, + ToolAssistanceImage, ToolAssistanceInputMethod, UniformType, VaryingType, ViewStatus, ViewUndoEvent, + + BackgroundFill, BackgroundMapType, BatchType, BisCodeSpec, BriefcaseIdValue, ChangedValueState, ChangeOpCode, ChangesetType, ColorByName, + CommonLoggerCategory, ECSqlSystemProperty, ECSqlValueType, ElementGeometryOpcode, FeatureOverrideType, FillDisplay, FillFlags, FontType, + GeoCoordStatus, GeometryClass, GeometryStreamFlags, GeometrySummaryVerbosity, GlobeMode, GridOrientationType, HSVConstants, ImageBufferFormat, + ImageSourceFormat, LinePixels, MassPropertiesOperation, MonochromeMode, Npc, PlanarClipMaskMode, PlanarClipMaskPriority, QueryRowFormat, Rank, + RenderMode, SectionType, + SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, SyncMode, TerrainHeightOriginMode, TextureMapUnits, + ThematicDisplayMode, ThematicGradientColorScheme, ThematicGradientMode, TxnAction, TypeOfChange, + }, + api: new ExtensionImpl(id), + }; +}; + +(globalThis as any)[globalSymbol] = { + getExtensionApi, +}; diff --git a/core/frontend/src/extension/extensions.ts b/core/frontend/src/extension/extensions.ts new file mode 100644 index 000000000000..c5bbfaefa00d --- /dev/null +++ b/core/frontend/src/extension/extensions.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ + +// Barrel file for all extension related files. + +/** + * The Extension framework is made up of multiple pieces: + * + * - Extension API + * - The Extension API defines all of the types and API that can be used by an Extension. + * - Extension Impl + * - The current implementation of the Extension API + * - Extension Admin + * - Handles loading and managing Extensions + * - Extension Hooks + * - Defines the contribution points for Extensions + */ + +export * from "./Extension"; +export * from "./ExtensionAdmin"; +export * from "./ExtensionImpl"; +export * from "./ExtensionLoader"; +export * from "./ExtensionHost"; +import "./ExtensionRuntime"; diff --git a/core/frontend/src/render/ParticleCollectionBuilder.ts b/core/frontend/src/render/ParticleCollectionBuilder.ts index ab2af6f645f7..f19ae54e9904 100644 --- a/core/frontend/src/render/ParticleCollectionBuilder.ts +++ b/core/frontend/src/render/ParticleCollectionBuilder.ts @@ -9,7 +9,7 @@ import { Id64String } from "@itwin/core-bentley"; import { Matrix3d, Point2d, Point3d, Range3d, Transform, Vector2d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { - ColorDef, Feature, FeatureTable, PackedFeatureTable, QParams3d, QPoint3dList, RenderTexture, + ColorDef, ColorIndex, Feature, FeatureIndex, FeatureTable, FillFlags, PackedFeatureTable, QParams3d, QPoint3dList, RenderTexture, } from "@itwin/core-common"; import { Viewport } from "../Viewport"; import { RenderGraphic } from "./RenderGraphic"; @@ -343,19 +343,29 @@ function createQuad(size: XAndY, texture: RenderTexture, transparency: number): new Point3d(-halfWidth, halfHeight, 0), new Point3d(halfWidth, halfHeight, 0), ]; - const quadArgs = new MeshArgs(); const range = new Range3d(); range.low = corners[0]; range.high = corners[3]; - quadArgs.points = new QPoint3dList(QParams3d.fromRange(range)); - for (const corner of corners) - quadArgs.points.add(corner); - quadArgs.vertIndices = [0, 1, 2, 2, 1, 3]; - quadArgs.textureUv = [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0)]; - quadArgs.texture = texture; - quadArgs.colors.initUniform(ColorDef.white.withTransparency(transparency)); - quadArgs.isPlanar = true; + const points = new QPoint3dList(QParams3d.fromRange(range)); + for (const corner of corners) + points.add(corner); + + const colors = new ColorIndex(); + colors.initUniform(ColorDef.white.withTransparency(transparency)); + + const quadArgs: MeshArgs = { + points, + vertIndices: [0, 1, 2, 2, 1, 3], + fillFlags: FillFlags.None, + isPlanar: true, + colors, + features: new FeatureIndex(), + textureMapping: { + texture, + uvParams: [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0)], + }, + }; return MeshParams.create(quadArgs); } diff --git a/core/frontend/src/render/RenderSystem.ts b/core/frontend/src/render/RenderSystem.ts index bc7ccfa17469..e5ecfff82058 100644 --- a/core/frontend/src/render/RenderSystem.ts +++ b/core/frontend/src/render/RenderSystem.ts @@ -8,7 +8,7 @@ import { base64StringToUint8Array, Id64String, IDisposable } from "@itwin/core-bentley"; import { - ColorDef, ElementAlignedBox3d, FeatureIndexType, Frustum, Gradient, ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, + ColorDef, ColorIndex, ElementAlignedBox3d, FeatureIndex, FeatureIndexType, FillFlags, Frustum, Gradient, ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, isValidImageSourceFormat, PackedFeatureTable, QParams3d, QPoint3dList, RenderMaterial, RenderTexture, SkyGradient, TextureProps, TextureTransparency, } from "@itwin/core-common"; import { ClipVector, Matrix3d, Point2d, Point3d, Range2d, Range3d, Transform, Vector2d, XAndY } from "@itwin/core-geometry"; @@ -441,39 +441,40 @@ export abstract class RenderSystem implements IDisposable { public createBackgroundMapDrape(_drapedTree: TileTreeReference, _mapTree: MapTileTreeReference): RenderTextureDrape | undefined { return undefined; } /** @internal */ public createTile(tileTexture: RenderTexture, corners: Point3d[], featureIndex?: number): RenderGraphic | undefined { - const rasterTile = new MeshArgs(); - // corners // [0] [1] // [2] [3] // Quantize the points according to their range - rasterTile.points = new QPoint3dList(QParams3d.fromRange(Range3d.create(...corners))); - for (let i = 0; i < 4; ++i) - rasterTile.points.add(corners[i]); + const points = new QPoint3dList(QParams3d.fromRange(Range3d.create(...corners))); + for (let i = 0; i < 4; i++) + points.add(corners[i]); // Now remove the translation from the quantized points and put it into a transform instead. // This prevents graphical artifacts when quantization origin is large relative to quantization scale. // ###TODO: Would be better not to create a branch for every tile. - const qorigin = rasterTile.points.params.origin; + const qorigin = points.params.origin; const transform = Transform.createTranslationXYZ(qorigin.x, qorigin.y, qorigin.z); qorigin.setZero(); - rasterTile.vertIndices = [0, 1, 2, 2, 1, 3]; - rasterTile.textureUv = [ - new Point2d(0.0, 0.0), - new Point2d(1.0, 0.0), - new Point2d(0.0, 1.0), - new Point2d(1.0, 1.0), - ]; - - rasterTile.texture = tileTexture; - rasterTile.isPlanar = true; - + const features = new FeatureIndex(); if (undefined !== featureIndex) { - rasterTile.features.featureID = featureIndex; - rasterTile.features.type = FeatureIndexType.Uniform; + features.featureID = featureIndex; + features.type = FeatureIndexType.Uniform; } + const rasterTile: MeshArgs = { + points, + vertIndices: [0, 1, 2, 2, 1, 3], + isPlanar: true, + features, + colors: new ColorIndex(), + fillFlags: FillFlags.None, + textureMapping: { + uvParams: [new Point2d(0, 0), new Point2d(1, 0), new Point2d(0, 1), new Point2d(1, 1)], + texture: tileTexture, + }, + }; + const trimesh = this.createTriMesh(rasterTile); if (undefined === trimesh) return undefined; diff --git a/core/frontend/src/render/primitives/EdgeParams.ts b/core/frontend/src/render/primitives/EdgeParams.ts index 4c0ad0b5c0f7..13b2cae389ff 100644 --- a/core/frontend/src/render/primitives/EdgeParams.ts +++ b/core/frontend/src/render/primitives/EdgeParams.ts @@ -293,7 +293,10 @@ export interface EdgeParams { export namespace EdgeParams { export function fromMeshArgs(meshArgs: MeshArgs, maxWidth?: number): EdgeParams | undefined { const args = meshArgs.edges; - const doJoints = wantJointTriangles(args.width, meshArgs.is2d); + if (!args) + return undefined; + + const doJoints = wantJointTriangles(args.width, true === meshArgs.is2d); const polylines = doJoints ? TesselatedPolyline.fromMesh(meshArgs) : undefined; let segments: SegmentEdgeParams | undefined; diff --git a/core/frontend/src/render/primitives/PolylineParams.ts b/core/frontend/src/render/primitives/PolylineParams.ts index 619ce86ae671..ffb69781b952 100644 --- a/core/frontend/src/render/primitives/PolylineParams.ts +++ b/core/frontend/src/render/primitives/PolylineParams.ts @@ -87,7 +87,6 @@ class PolylineVertex { class PolylineTesselator { private _polylines: PolylineData[]; - private _points: QPoint3dList; private _doJoints: boolean; private _numIndices = 0; private _vertIndex: number[] = []; @@ -96,9 +95,15 @@ class PolylineTesselator { private _nextParam: number[] = []; private _position: Point3d[] = []; - public constructor(polylines: PolylineData[], points: QPoint3dList, doJointTriangles: boolean) { + public constructor(polylines: PolylineData[], points: QPoint3dList | Point3d[], doJointTriangles: boolean) { this._polylines = polylines; - this._points = points; + if (points instanceof QPoint3dList) { + for (const p of points.list) + this._position.push(p.unquantize(points.params)); + } else { + this._position = points; + } + this._doJoints = doJointTriangles; } @@ -107,16 +112,13 @@ class PolylineTesselator { } public static fromMesh(args: MeshArgs): PolylineTesselator | undefined { - if (undefined !== args.edges.polylines.lines && undefined !== args.points) - return new PolylineTesselator(args.edges.polylines.lines, args.points, wantJointTriangles(args.edges.width, args.is2d)); + if (undefined !== args.edges?.polylines.lines && undefined !== args.points) + return new PolylineTesselator(args.edges.polylines.lines, args.points, wantJointTriangles(args.edges.width, true === args.is2d)); return undefined; } public tesselate(): TesselatedPolyline { - for (const p of this._points.list) - this._position.push(p.unquantize(this._points.params)); - this._tesselate(); const vertIndex = VertexIndices.fromArray(this._vertIndex); diff --git a/core/frontend/src/render/primitives/VertexKey.ts b/core/frontend/src/render/primitives/VertexKey.ts index 16b1f1252aca..db13c9141a8e 100644 --- a/core/frontend/src/render/primitives/VertexKey.ts +++ b/core/frontend/src/render/primitives/VertexKey.ts @@ -7,25 +7,36 @@ */ import { assert, compareWithTolerance, IndexMap } from "@itwin/core-bentley"; -import { Point2d } from "@itwin/core-geometry"; -import { OctEncodedNormal, QPoint3d } from "@itwin/core-common"; +import { Point2d, Point3d, XYAndZ } from "@itwin/core-geometry"; +import { OctEncodedNormal } from "@itwin/core-common"; /** @internal */ export interface VertexKeyProps { - position: QPoint3d; + position: Point3d; fillColor: number; normal?: OctEncodedNormal; uvParam?: Point2d; } +function comparePositions(p0: Point3d, p1: Point3d, tolerance: XYAndZ): number { + let diff = compareWithTolerance(p0.x, p1.x, tolerance.x); + if (0 === diff) { + diff = compareWithTolerance(p0.y, p1.y, tolerance.y); + if (0 === diff) + diff = compareWithTolerance(p0.z, p1.z, tolerance.z); + } + + return diff; +} + /** @internal */ export class VertexKey { - public readonly position: QPoint3d; + public readonly position: Point3d; public readonly normal?: OctEncodedNormal; public readonly uvParam?: Point2d; public readonly fillColor: number; - public constructor(position: QPoint3d, fillColor: number, normal?: OctEncodedNormal, uvParam?: Point2d) { + public constructor(position: Point3d, fillColor: number, normal?: OctEncodedNormal, uvParam?: Point2d) { this.position = position.clone(); this.fillColor = fillColor; this.normal = normal; @@ -34,7 +45,7 @@ export class VertexKey { public static create(props: VertexKeyProps): VertexKey { return new VertexKey(props.position, props.fillColor, props.normal, props.uvParam); } - public equals(rhs: VertexKey): boolean { + public equals(rhs: VertexKey, tolerance: XYAndZ): boolean { if (this.fillColor !== rhs.fillColor) return false; @@ -44,24 +55,24 @@ export class VertexKey { return false; } - if (!this.position.equals(rhs.position)) + if (0 !== comparePositions(this.position, rhs.position, tolerance)) return false; if (undefined !== this.uvParam) { assert(undefined !== rhs.uvParam); - return this.uvParam.isAlmostEqual(rhs.uvParam, 0.1); + return this.uvParam.isAlmostEqual(rhs.uvParam, 0.1); // ###TODO surely this is a typo? } return true; } - public compare(rhs: VertexKey): number { + public compare(rhs: VertexKey, tolerance: XYAndZ): number { if (this === rhs) return 0; let diff = this.fillColor - rhs.fillColor; if (0 === diff) { - diff = this.position.compare(rhs.position); + diff = comparePositions(this.position, rhs.position, tolerance); if (0 === diff) { if (undefined !== this.normal) { assert(undefined !== rhs.normal); @@ -83,9 +94,22 @@ export class VertexKey { /** @internal */ export class VertexMap extends IndexMap { - public constructor() { super((lhs, rhs) => lhs.compare(rhs)); } + private readonly _tolerance: XYAndZ; + + public constructor(tolerance: XYAndZ) { + super((lhs, rhs) => lhs.compare(rhs, tolerance)); + this._tolerance = tolerance; + } public insertKey(props: VertexKeyProps, onInsert?: (vk: VertexKey) => any): number { return this.insert(VertexKey.create(props), onInsert); } + + public arePositionsAlmostEqual(p0: VertexKeyProps, p1: VertexKeyProps): boolean { + return 0 === this.comparePositions(p0, p1); + } + + public comparePositions(p0: VertexKeyProps, p1: VertexKeyProps): number { + return comparePositions(p0.position, p1.position, this._tolerance); + } } diff --git a/core/frontend/src/render/primitives/VertexTable.ts b/core/frontend/src/render/primitives/VertexTable.ts index 481be3037815..65725dbb0a78 100644 --- a/core/frontend/src/render/primitives/VertexTable.ts +++ b/core/frontend/src/render/primitives/VertexTable.ts @@ -7,11 +7,11 @@ */ import { assert } from "@itwin/core-bentley"; -import { Point2d, Range2d } from "@itwin/core-geometry"; -import { ColorDef, ColorIndex, FeatureIndex, FeatureIndexType, QParams2d, QParams3d, QPoint2d } from "@itwin/core-common"; +import { Point2d, Point3d, Range2d } from "@itwin/core-geometry"; +import { ColorDef, ColorIndex, FeatureIndex, FeatureIndexType, QParams2d, QParams3d, QPoint2d, QPoint3dList } from "@itwin/core-common"; import { IModelApp } from "../../IModelApp"; import { AuxChannelTable } from "./AuxChannelTable"; -import { MeshArgs, PolylineArgs } from "./mesh/MeshPrimitives"; +import { MeshArgs, Point3dList, PolylineArgs } from "./mesh/MeshPrimitives"; import { createSurfaceMaterial, SurfaceParams, SurfaceType } from "./SurfaceParams"; import { EdgeParams } from "./EdgeParams"; @@ -116,7 +116,13 @@ export function computeDimensions(nEntries: number, nRgbaPerEntry: number, nExtr export interface VertexTableProps { /** The rectangular array of vertex data, of size width*height*numRgbaPerVertex bytes. */ readonly data: Uint8Array; - /** Quantization parameters for the vertex positions encoded into the array. */ + /** If true, positions are not quantized but instead stored as 32-bit floats. + * [[qparams]] will still be defined; it can be used to derive the range of positions in the table. + */ + readonly usesUnquantizedPositions?: boolean; + /** Quantization parameters for the vertex positions encoded into the array, the positions are quantized; + * and for deriving the range of positions in the table, whether quantized or not. + */ readonly qparams: QParams3d; /** The number of 4-byte 'RGBA' values in each row of the array. Must be divisible by numRgbaPerVertex. */ readonly width: number; @@ -149,7 +155,13 @@ export interface VertexTableProps { export class VertexTable implements VertexTableProps { /** The rectangular array of vertex data, of size width*height*numRgbaPerVertex bytes. */ public readonly data: Uint8Array; - /** Quantization parameters for the vertex positions encoded into the array. */ + /** If true, positions are not quantized but instead stored as 32-bit floats. + * [[qparams]] will still be defined; it can be used to derive the range of positions in the table. + */ + public readonly usesUnquantizedPositions?: boolean; + /** Quantization parameters for the vertex positions encoded into the array, the positions are quantized; + * and for deriving the range of positions in the table, whether quantized or not. + */ public readonly qparams: QParams3d; /** The number of 4-byte 'RGBA' values in each row of the array. Must be divisible by numRgbaPerVertex. */ public readonly width: number; @@ -174,6 +186,7 @@ export class VertexTable implements VertexTableProps { public constructor(props: VertexTableProps) { this.data = props.data; this.qparams = props.qparams; + this.usesUnquantizedPositions = !!props.usesUnquantizedPositions; this.width = props.width; this.height = props.height; this.hasTranslucency = true === props.hasTranslucency; @@ -204,6 +217,7 @@ export class VertexTable implements VertexTableProps { return new VertexTable({ data, qparams: builder.qparams, + usesUnquantizedPositions: builder.usesUnquantizedPositions, width: dimensions.width, height: dimensions.height, hasTranslucency: colorIndex.hasAlpha, @@ -219,7 +233,7 @@ export class VertexTable implements VertexTableProps { public static createForPolylines(args: PolylineArgs): VertexTable | undefined { const polylines = args.polylines; if (0 < polylines.length) - return this.buildFrom(new SimpleBuilder(args), args.colors, args.features); + return this.buildFrom(createPolylineBuilder(args), args.colors, args.features); else return undefined; } @@ -248,18 +262,18 @@ export class MeshParams { /** Construct from a MeshArgs. */ public static create(args: MeshArgs): MeshParams { - const builder = MeshBuilder.create(args); + const builder = createMeshBuilder(args); const vertices = VertexTable.buildFrom(builder, args.colors, args.features); - const surfaceIndices = VertexIndices.fromArray(args.vertIndices!); + const surfaceIndices = VertexIndices.fromArray(args.vertIndices); const surface: SurfaceParams = { type: builder.type, indices: surfaceIndices, fillFlags: args.fillFlags, - hasBakedLighting: args.hasBakedLighting, - hasFixedNormals: args.hasFixedNormals, - textureMapping: undefined !== args.texture ? { texture: args.texture, alwaysDisplayed: false } : undefined, + hasBakedLighting: true === args.hasBakedLighting, + hasFixedNormals: true === args.hasFixedNormals, + textureMapping: undefined !== args.textureMapping ? { texture: args.textureMapping.texture, alwaysDisplayed: false } : undefined, material: createSurfaceMaterial(args.material), }; @@ -277,6 +291,7 @@ export abstract class VertexTableBuilder { public abstract get numVertices(): number; public abstract get numRgbaPerVertex(): number; public abstract get qparams(): QParams3d; + public abstract get usesUnquantizedPositions(): boolean; public get uvParams(): QParams2d | undefined { return undefined; } public abstract appendVertex(vertIndex: number): void; @@ -340,150 +355,347 @@ export abstract class VertexTableBuilder { } } -type SimpleVertexData = PolylineArgs | MeshArgs; +type VertexData = PolylineArgs | MeshArgs; +type Quantized = Omit & { points: QPoint3dList }; +type Unquantized = Omit & { points: Omit }; -/** - * Supplies vertex data from a PolylineArgs or MeshArgs. Each vertex consists of 12 bytes: - * pos.x 00 - * pos.y 02 - * pos.z 04 - * colorIndex 06 - * featureIndex 08 - */ -class SimpleBuilder extends VertexTableBuilder { - public args: T; +namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare + /** + * Supplies vertex data from a PolylineArgs or MeshArgs. Each vertex consists of 12 bytes: + * pos.x 00 + * pos.y 02 + * pos.z 04 + * colorIndex 06 + * featureIndex 08 (24 bits) + * materialIndex 0B (for meshes that use a material atlas; otherwise unused). NOTE: Currently front-end code does not produce material atlases. + */ + export class SimpleBuilder> extends VertexTableBuilder { + public args: T; + protected _qpoints: QPoint3dList; + + public constructor(args: T) { + super(); + this._qpoints = args.points; + this.args = args; + assert(undefined !== this.args.points); + } + + public get numVertices() { return this.args.points.length; } + public get numRgbaPerVertex() { return 3; } + public get usesUnquantizedPositions() { return false; } + public get qparams() { + return this._qpoints.params; + } - public constructor(args: T) { - super(); - this.args = args; - assert(undefined !== this.args.points); + public appendVertex(vertIndex: number): void { + this.appendPosition(vertIndex); + this.appendColorIndex(vertIndex); + this.appendFeatureIndex(vertIndex); + } + + protected appendPosition(vertIndex: number) { + this.append16(this._qpoints.list[vertIndex].x); + this.append16(this._qpoints.list[vertIndex].y); + this.append16(this._qpoints.list[vertIndex].z); + } + + protected appendColorIndex(vertIndex: number) { + if (undefined !== this.args.colors.nonUniform) { + this.append16(this.args.colors.nonUniform.indices[vertIndex]); + } else { + this.advance(2); + } + } + + protected appendFeatureIndex(vertIndex: number) { + if (undefined !== this.args.features.featureIDs) { + this.append32(this.args.features.featureIDs[vertIndex]); + } else { + this.advance(4); + } + } } - public get numVertices() { return this.args.points!.length; } - public get numRgbaPerVertex() { return 3; } - public get qparams() { return this.args.points!.params; } + /** Supplies vertex data from a MeshArgs. */ + export class MeshBuilder extends SimpleBuilder> { + public readonly type: SurfaceType; + + protected constructor(args: Quantized, type: SurfaceType) { + super(args); + this.type = type; + } + + public static create(args: Quantized): MeshBuilder { + if (args.isVolumeClassifier) + return new MeshBuilder(args, SurfaceType.VolumeClassifier); + + const isLit = undefined !== args.normals && 0 < args.normals.length; + const isTextured = undefined !== args.textureMapping; - public appendVertex(vertIndex: number): void { - this.appendPosition(vertIndex); - this.appendColorIndex(vertIndex); - this.appendFeatureIndex(vertIndex); + let uvParams: QParams2d | undefined; + + if (args.textureMapping) { + const uvRange = Range2d.createNull(); + const fpts = args.textureMapping.uvParams; + const pt2d = new Point2d(); + if (undefined !== fpts && fpts.length > 0) + for (let i = 0; i < args.points.length; i++) + uvRange.extendPoint(Point2d.create(fpts[i].x, fpts[i].y, pt2d)); + + uvParams = QParams2d.fromRange(uvRange); + } + + if (isLit) + return isTextured ? new TexturedLitMeshBuilder(args, uvParams!) : new LitMeshBuilder(args); + else + return isTextured ? new TexturedMeshBuilder(args, uvParams!) : new MeshBuilder(args, SurfaceType.Unlit); + } } - protected appendPosition(vertIndex: number) { - const points = this.args.points!; - this.append16(points.list[vertIndex].x); - this.append16(points.list[vertIndex].y); - this.append16(points.list[vertIndex].z); + /** Supplies vertex data from a MeshArgs where each vertex consists of 16 bytes. + * In addition to the SimpleBuilder data, the final 4 bytes hold the quantized UV params + * The color index is left uninitialized as it is unused. + */ + class TexturedMeshBuilder extends MeshBuilder { + private _qparams: QParams2d; + private _qpoint = new QPoint2d(); + + public constructor(args: Quantized, qparams: QParams2d, type: SurfaceType = SurfaceType.Textured) { + super(args, type); + this._qparams = qparams; + assert(undefined !== args.textureMapping); + } + + public override get numRgbaPerVertex() { return 4; } + public override get uvParams() { return this._qparams; } + + public override appendVertex(vertIndex: number) { + this.appendPosition(vertIndex); + this.appendNormal(vertIndex); + this.appendFeatureIndex(vertIndex); + this.appendUVParams(vertIndex); + } + + protected appendNormal(_vertIndex: number): void { this.advance(2); } // no normal for unlit meshes + + protected appendUVParams(vertIndex: number) { + this._qpoint.init(this.args.textureMapping!.uvParams[vertIndex], this._qparams); + this.append16(this._qpoint.x); + this.append16(this._qpoint.y); + } } - protected appendColorIndex(vertIndex: number) { - if (undefined !== this.args.colors.nonUniform) { - this.append16(this.args.colors.nonUniform.indices[vertIndex]); - } else { - this.advance(2); + /** As with TexturedMeshBuilder, but the color index is replaced with the oct-encoded normal value. */ + class TexturedLitMeshBuilder extends TexturedMeshBuilder { + public constructor(args: Quantized, qparams: QParams2d) { + super(args, qparams, SurfaceType.TexturedLit); + assert(undefined !== args.normals); } + + protected override appendNormal(vertIndex: number) { this.append16(this.args.normals![vertIndex].value); } } - protected appendFeatureIndex(vertIndex: number) { - if (undefined !== this.args.features.featureIDs) { - this.append32(this.args.features.featureIDs[vertIndex]); - } else { - this.advance(4); + /** 16 bytes. The last 2 bytes are unused; the 2 immediately preceding it hold the oct-encoded normal value. */ + class LitMeshBuilder extends MeshBuilder { + public constructor(args: Quantized) { + super(args, SurfaceType.Lit); + assert(undefined !== args.normals); + } + + public override get numRgbaPerVertex() { return 4; } + + public override appendVertex(vertIndex: number) { + super.appendVertex(vertIndex); + this.append16(this.args.normals![vertIndex].value); + this.advance(2); // 2 unused bytes } } } -/** Supplies vertex data from a MeshArgs. */ -class MeshBuilder extends SimpleBuilder { - public readonly type: SurfaceType; +/** Builders in this namespace store vertex positions as 32-bit floats instead of quantizing to 16-bit unsigned integers. + * This is preferred for decoration graphics, which might contain ranges of positions that exceed the limits for quantization; if quantized, + * they could produce visual artifacts. + * Each builder produces a VertexTable that starts with the following layout: + * pos.x: 00 + * pos.y: 04 + * pos.z: 08 + * featureIndex: 0C + * materialIndex:0F (NOTE: frontend code currently doesn't produce material atlases, so this is always zero). + * Followed (by default) by: + * colorIndex: 10 + * unused: 12 + * Subclasses may add 4 more bytes and/or overwrite the final 4 bytes above. + */ +namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare + const u32Array = new Uint32Array(1); + const f32Array = new Float32Array(u32Array.buffer); + + // colorIndex: 10 + // unused: 12 + export class SimpleBuilder> extends VertexTableBuilder { + public args: T; + protected _points: Point3d[]; + private _qparams3d: QParams3d; + + public constructor(args: T) { + super(); + assert(!(args.points instanceof QPoint3dList)); + this._qparams3d = QParams3d.fromRange(args.points.range); + this.args = args; + this._points = args.points; + } - protected constructor(args: MeshArgs, type: SurfaceType) { - super(args); - this.type = type; - } + public get numVertices() { return this._points.length; } + public get numRgbaPerVertex() { return 5; } + public get usesUnquantizedPositions() { return true; } + public get qparams() { return this._qparams3d; } - public static create(args: MeshArgs): MeshBuilder { - if (args.isVolumeClassifier) - return new MeshBuilder(args, SurfaceType.VolumeClassifier); + public appendVertex(vertIndex: number): void { + this.appendPosition(vertIndex); + this.appendFeatureIndex(vertIndex); + this.appendColorIndex(vertIndex); + } - const isLit = undefined !== args.normals && 0 < args.normals.length; - const isTextured = undefined !== args.texture; + private appendFloat32(val: number) { + f32Array[0] = val; + this.append32(u32Array[0]); + } - let uvParams: QParams2d | undefined; + protected appendPosition(vertIndex: number) { + const pt = this._points[vertIndex]; + this.appendFloat32(pt.x); + this.appendFloat32(pt.y); + this.appendFloat32(pt.z); + } - if (isTextured) { - const uvRange = Range2d.createNull(); - const fpts = args.textureUv; - const pt2d = new Point2d(); - if (undefined !== fpts && fpts.length > 0) - for (let i = 0; i < args.points!.length; i++) - uvRange.extendPoint(Point2d.create(fpts[i].x, fpts[i].y, pt2d)); + protected appendFeatureIndex(vertIndex: number) { + if (this.args.features.featureIDs) + this.append32(this.args.features.featureIDs[vertIndex]); + else + this.advance(4); + } - uvParams = QParams2d.fromRange(uvRange); + protected _appendColorIndex(vertIndex: number) { + if (undefined !== this.args.colors.nonUniform) + this.append16(this.args.colors.nonUniform.indices[vertIndex]); + else + this.advance(2); } - if (isLit) - return isTextured ? new TexturedLitMeshBuilder(args, uvParams!) : new LitMeshBuilder(args); - else - return isTextured ? new TexturedMeshBuilder(args, uvParams!) : new MeshBuilder(args, SurfaceType.Unlit); + protected appendColorIndex(vertIndex: number) { + this._appendColorIndex(vertIndex); + this.advance(2); + } } -} -/** Supplies vertex data from a MeshArgs where each vertex consists of 16 bytes. - * In addition to the SimpleBuilder data, the final 4 bytes hold the quantized UV params - * The color index is left uninitialized as it is unused. - */ -class TexturedMeshBuilder extends MeshBuilder { - private _qparams: QParams2d; - private _qpoint = new QPoint2d(); - - public constructor(args: MeshArgs, qparams: QParams2d, type: SurfaceType = SurfaceType.Textured) { - super(args, type); - this._qparams = qparams; - assert(undefined !== args.textureUv); - } + export class MeshBuilder extends SimpleBuilder> { + public readonly type: SurfaceType; - public override get numRgbaPerVertex() { return 4; } - public override get uvParams() { return this._qparams; } + protected constructor(args: Unquantized, type: SurfaceType) { + super(args); + this.type = type; + } - public override appendVertex(vertIndex: number) { - this.appendPosition(vertIndex); - this.appendNormal(vertIndex); - this.appendFeatureIndex(vertIndex); - this.appendUVParams(vertIndex); - } + public static create(args: Unquantized): MeshBuilder { + if (args.isVolumeClassifier) + return new MeshBuilder(args, SurfaceType.VolumeClassifier); + + const isLit = undefined !== args.normals && 0 < args.normals.length; + const isTextured = undefined !== args.textureMapping; - protected appendNormal(_vertIndex: number): void { this.advance(2); } // no normal for unlit meshes + let uvParams: QParams2d | undefined; - protected appendUVParams(vertIndex: number) { - this._qpoint.init(this.args.textureUv![vertIndex], this._qparams); - this.append16(this._qpoint.x); - this.append16(this._qpoint.y); + if (args.textureMapping) { + const uvRange = Range2d.createNull(); + const fpts = args.textureMapping.uvParams; + const pt2d = new Point2d(); + if (undefined !== fpts && fpts.length > 0) + for (let i = 0; i < args.points.length; i++) + uvRange.extendPoint(Point2d.create(fpts[i].x, fpts[i].y, pt2d)); + + uvParams = QParams2d.fromRange(uvRange); + } + + if (isLit) + return isTextured ? new TexturedLitMeshBuilder(args, uvParams!) : new LitMeshBuilder(args); + else + return isTextured ? new TexturedMeshBuilder(args, uvParams!) : new MeshBuilder(args, SurfaceType.Unlit); + } } -} -/** As with TexturedMeshBuilder, but the color index is replaced with the oct-encoded normal value. */ -class TexturedLitMeshBuilder extends TexturedMeshBuilder { - public constructor(args: MeshArgs, qparams: QParams2d) { - super(args, qparams, SurfaceType.TexturedLit); - assert(undefined !== args.normals); + // u: 10 + // v: 12 + class TexturedMeshBuilder extends MeshBuilder { + private _qparams: QParams2d; + private _qpoint = new QPoint2d(); + + public constructor(args: Unquantized, qparams: QParams2d, type = SurfaceType.Textured) { + super(args, type); + this._qparams = qparams; + assert(undefined !== args.textureMapping); + } + + public override get uvParams() { return this._qparams; } + + public override appendVertex(vertIndex: number) { + super.appendVertex(vertIndex); + + this._qpoint.init(this.args.textureMapping!.uvParams[vertIndex], this._qparams); + this.append16(this._qpoint.x); + this.append16(this._qpoint.y); + } + + protected override appendColorIndex() { } } - protected override appendNormal(vertIndex: number) { this.append16(this.args.normals![vertIndex].value); } -} + // u: 10 + // v: 12 + // normal: 14 + // unused: 16 + class TexturedLitMeshBuilder extends TexturedMeshBuilder { + public constructor(args: Unquantized, qparams: QParams2d) { + super(args, qparams, SurfaceType.TexturedLit); + assert(undefined !== args.normals); + } + + public override get numRgbaPerVertex() { return 6; } -/** 16 bytes. The last 2 bytes are unused; the 2 immediately preceding it hold the oct-encoded normal value. */ -class LitMeshBuilder extends MeshBuilder { - public constructor(args: MeshArgs) { - super(args, SurfaceType.Lit); - assert(undefined !== args.normals); + public override appendVertex(vertIndex: number) { + super.appendVertex(vertIndex); + this.append16(this.args.normals![vertIndex].value); + this.advance(2); + } } - public override get numRgbaPerVertex() { return 4; } + // color: 10 + // normal: 12 + class LitMeshBuilder extends MeshBuilder { + public constructor(args: Unquantized) { + super(args, SurfaceType.Lit); + assert(undefined !== args.normals); + } + + protected override appendColorIndex(vertIndex: number) { + super._appendColorIndex(vertIndex); + } - public override appendVertex(vertIndex: number) { - super.appendVertex(vertIndex); - this.append16(this.args.normals![vertIndex].value); - this.advance(2); // 2 unused bytes + public override appendVertex(vertIndex: number) { + super.appendVertex(vertIndex); + this.append16(this.args.normals![vertIndex].value); + } } } + +function createMeshBuilder(args: MeshArgs): VertexTableBuilder & { type: SurfaceType } { + if (args.points instanceof QPoint3dList) + return Quantized.MeshBuilder.create(args as Quantized); // wtf compiler? + else + return Unquantized.MeshBuilder.create(args as Unquantized); // seriously wtf? +} + +function createPolylineBuilder(args: PolylineArgs): VertexTableBuilder { + if (args.points instanceof QPoint3dList) + return new Quantized.SimpleBuilder(args as Quantized); // wtf compiler? + else + return new Unquantized.SimpleBuilder(args as Unquantized); // seriously wtf? +} diff --git a/core/frontend/src/render/primitives/geometry/GeometryAccumulator.ts b/core/frontend/src/render/primitives/geometry/GeometryAccumulator.ts index 0fa933bdb5ce..72669d44a3f7 100644 --- a/core/frontend/src/render/primitives/geometry/GeometryAccumulator.ts +++ b/core/frontend/src/render/primitives/geometry/GeometryAccumulator.ts @@ -8,13 +8,13 @@ import { assert } from "@itwin/core-bentley"; import { IndexedPolyface, Loop, Path, Point3d, Range3d, SolidPrimitive, Transform } from "@itwin/core-geometry"; -import { AnalysisStyleDisplacement } from "@itwin/core-common"; +import { AnalysisStyleDisplacement, QPoint3dList } from "@itwin/core-common"; import { GraphicBranch } from "../../GraphicBranch"; import { RenderGraphic } from "../../RenderGraphic"; import { RenderSystem } from "../../RenderSystem"; import { DisplayParams } from "../DisplayParams"; import { MeshBuilderMap } from "../mesh/MeshBuilderMap"; -import { MeshGraphicArgs, MeshList } from "../mesh/MeshPrimitives"; +import { MeshList } from "../mesh/MeshPrimitives"; import { GeometryOptions } from "../Primitives"; import { GeometryList } from "./GeometryList"; import { Geometry, PrimitiveGeometryType } from "./GeometryPrimitives"; @@ -175,31 +175,39 @@ export class GeometryAccumulator { if (0 === meshes.length) return undefined; - const args = new MeshGraphicArgs(); - - // All of the meshes are quantized to the same range. - // If that range is small relative to the distance from the origin, quantization errors can produce display artifacts. - // Remove the translation from the quantization parameters and apply it in the transform instead. + // If the meshes contain quantized positions, they are all quantized to the same range. If that range is small relative to the distance + // from the origin, quantization errors can produce display artifacts. Remove the translation from the quantization parameters and apply + // it in the transform instead. + // + // If the positions are not quantized, they have already been transformed to be relative to the center of the meshes' range. + // Apply the inverse translation to put them back into model space. const branch = new GraphicBranch(true); - const qorigin = new Point3d(); + let transformOrigin: Point3d | undefined; for (const mesh of meshes) { const verts = mesh.points; if (branch.isEmpty) { - qorigin.setFrom(verts.params.origin); + assert(transformOrigin === undefined); + if (verts instanceof QPoint3dList) { + transformOrigin = verts.params.origin.clone(); + verts.params.origin.setZero(); + } else { + transformOrigin = verts.range.center; + } } else { - assert(verts.params.origin.isAlmostEqual(qorigin)); + assert(undefined !== transformOrigin); + assert((verts instanceof QPoint3dList && transformOrigin.isAlmostEqual(verts.params.origin)) + || (!(verts instanceof QPoint3dList) && transformOrigin.isAlmostEqual(verts.range.center))); } - verts.params.origin.setZero(); - - const graphic = mesh.getGraphics(args, this.system, this._viewIndependentOrigin); + const graphic = mesh.getGraphics(this.system, this._viewIndependentOrigin); if (undefined !== graphic) branch.add(graphic); } if (!branch.isEmpty) { - const transform = Transform.createTranslationXYZ(qorigin.x, qorigin.y, qorigin.z); + assert(undefined !== transformOrigin); + const transform = Transform.createTranslation(transformOrigin); graphics.push(this.system.createBranch(branch, transform)); } diff --git a/core/frontend/src/render/primitives/mesh/MeshBuilder.ts b/core/frontend/src/render/primitives/mesh/MeshBuilder.ts index 0f37138130dc..47db69d69c3f 100644 --- a/core/frontend/src/render/primitives/mesh/MeshBuilder.ts +++ b/core/frontend/src/render/primitives/mesh/MeshBuilder.ts @@ -8,7 +8,7 @@ import { assert, Dictionary } from "@itwin/core-bentley"; import { Angle, IndexedPolyface, Point2d, Point3d, Polyface, PolyfaceVisitor, Range3d, Vector3d } from "@itwin/core-geometry"; -import { MeshEdge, MeshEdges, MeshPolyline, OctEncodedNormal, OctEncodedNormalPair, QPoint3d, QPoint3dList, TextureMapping } from "@itwin/core-common"; +import { MeshEdge, MeshEdges, MeshPolyline, OctEncodedNormal, OctEncodedNormalPair, QPoint3dList, TextureMapping } from "@itwin/core-common"; import { DisplayParams } from "../DisplayParams"; import { Triangle, TriangleKey, TriangleSet } from "../Primitives"; import { StrokesPrimitivePointLists } from "../Strokes"; @@ -20,7 +20,7 @@ type VertexKeyPropsWithIndex = VertexKeyProps & { sourceIndex: number }; /** @internal */ export class MeshBuilder { - private _vertexMap?: VertexMap; + public readonly vertexMap: VertexMap; private _triangleSet?: TriangleSet; private _currentPolyface?: MeshBuilderPolyface; public readonly mesh: Mesh; @@ -30,12 +30,6 @@ export class MeshBuilder { public get currentPolyface(): MeshBuilderPolyface | undefined { return this._currentPolyface; } public set displayParams(params: DisplayParams) { this.mesh.displayParams = params; } - /** create reference for vertexMap on demand */ - public get vertexMap(): VertexMap { - if (undefined === this._vertexMap) this._vertexMap = new VertexMap(); - return this._vertexMap; - } - /** create reference for triangleSet on demand */ public get triangleSet(): TriangleSet { if (undefined === this._triangleSet) this._triangleSet = new TriangleSet(); @@ -47,6 +41,17 @@ export class MeshBuilder { this.tolerance = tolerance; this.areaTolerance = areaTolerance; this.tileRange = tileRange; + + let vertexTolerance; + if (mesh.points instanceof QPoint3dList) { + const p0 = mesh.points.params.unquantize(0, 0, 0); + const p1 = mesh.points.params.unquantize(1, 1, 1); + vertexTolerance = p1.minus(p0, p0); + } else { + vertexTolerance = { x: tolerance, y: tolerance, z: tolerance }; + } + + this.vertexMap = new VertexMap(vertexTolerance); } /** create a new MeshBuilder */ @@ -119,7 +124,6 @@ export class MeshBuilder { public createTriangleVertices(triangleIndex: number, visitor: PolyfaceVisitor, options: MeshBuilder.PolyfaceVisitorOptions): VertexKeyPropsWithIndex[] | undefined { const { point, requireNormals } = visitor; const { fillColor, haveParam } = options; - const qPointParams = this.mesh.points.params; // If we do not have UVParams stored on the IndexedPolyface, compute them now let params: Point2d[] | undefined; @@ -135,7 +139,7 @@ export class MeshBuilder { const vertices = []; for (let i = 0; i < 3; ++i) { const vertexIndex = 0 === i ? 0 : triangleIndex + i; - const position = QPoint3d.create(point.getPoint3dAtUncheckedPointIndex(vertexIndex), qPointParams); + const position = point.getPoint3dAtUncheckedPointIndex(vertexIndex); const normal = requireNormals ? OctEncodedNormal.fromVector(visitor.getNormal(vertexIndex)!) : undefined; const uvParam: Point2d | undefined = params ? params[vertexIndex] : undefined; vertices[i] = { position, fillColor, normal, uvParam, sourceIndex: vertexIndex }; @@ -144,7 +148,9 @@ export class MeshBuilder { // Previously we would add all 3 vertices to our map, then detect degenerate triangles in AddTriangle(). // This led to unused vertex data, and caused mismatch in # of vertices when recreating the MeshBuilder from the data in the tile cache. // Detect beforehand instead. - if (vertices[0].position.equals(vertices[1].position) || vertices[0].position.equals(vertices[2].position) || vertices[1].position.equals(vertices[2].position)) + if (this.vertexMap.arePositionsAlmostEqual(vertices[0], vertices[1]) + || this.vertexMap.arePositionsAlmostEqual(vertices[0], vertices[2]) + || this.vertexMap.arePositionsAlmostEqual(vertices[1], vertices[2])) return undefined; return vertices; @@ -190,12 +196,10 @@ export class MeshBuilder { } /** removed Feature for now */ - public addPolyline(pts: QPoint3dList | Point3d[], fillColor: number): void { + public addPolyline(points: Point3d[], fillColor: number): void { const { mesh } = this; const poly = new MeshPolyline(); - const points = pts instanceof QPoint3dList ? pts : QPoint3dList.createFrom(pts, mesh.points.params); - for (const position of points) poly.addIndex(this.addVertex({ position, fillColor })); @@ -203,10 +207,9 @@ export class MeshBuilder { } /** removed Feature for now */ - public addPointString(pts: Point3d[], fillColor: number): void { + public addPointString(points: Point3d[], fillColor: number): void { const { mesh } = this; const poly = new MeshPolyline(); - const points = QPoint3dList.createFrom(pts, mesh.points.params); for (const position of points) poly.addIndex(this.addVertex({ position, fillColor })); diff --git a/core/frontend/src/render/primitives/mesh/MeshBuilderMap.ts b/core/frontend/src/render/primitives/mesh/MeshBuilderMap.ts index cf3ac52e5310..3b016b82a090 100644 --- a/core/frontend/src/render/primitives/mesh/MeshBuilderMap.ts +++ b/core/frontend/src/render/primitives/mesh/MeshBuilderMap.ts @@ -132,7 +132,18 @@ export class MeshBuilderMap extends Dictionary const { facetAreaTolerance, tolerance, is2d, range } = this; const key = this.getKey(displayParams, type, hasNormals, isPlanar); - return this.getBuilderFromKey(key, { displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance: facetAreaTolerance, features: this.features }); + const quantizePositions = false; // ###TODO should this be configurable? + return this.getBuilderFromKey(key, { + displayParams, + type, + range, + quantizePositions, + is2d, + isPlanar, + tolerance, + areaTolerance: facetAreaTolerance, + features: this.features, + }); } public getKey(displayParams: DisplayParams, type: Mesh.PrimitiveType, hasNormals: boolean, isPlanar: boolean): MeshBuilderMap.Key { diff --git a/core/frontend/src/render/primitives/mesh/MeshPrimitives.ts b/core/frontend/src/render/primitives/mesh/MeshPrimitives.ts index dd689be06dca..e307b1083a67 100644 --- a/core/frontend/src/render/primitives/mesh/MeshPrimitives.ts +++ b/core/frontend/src/render/primitives/mesh/MeshPrimitives.ts @@ -20,70 +20,79 @@ import { DisplayParams } from "../DisplayParams"; import { Triangle, TriangleList } from "../Primitives"; import { VertexKeyProps } from "../VertexKey"; +/** A Point3d[] with an [[add]] method used to enable compatibility with the [[MeshPointList]] union type. + * It is provided a range to contain all of the points. Each point added to the list is transformed to be relative to + * the center of that range. + * In the finished graphic, a transform is applied to transform back from the range's center. + * @internal + */ +export interface Point3dList extends Array { + /** Identical to `push`, except it returns `void` instead of `number`; compatible with [QPoint3dList.add]($common). */ + add(point: Point3d): void; + /** The range containing all of the points to be contained in the list, computed in advance. */ + range: Range3d; +} + +/** The list of points associated with a [[Mesh]]. + * @see [[Mesh.Props.quantizePositions]] to specify whether points should be quantized or not. + * @internal + */ +export type MeshPointList = Point3dList | QPoint3dList; + /* Information needed to draw a set of indexed polylines using a shared vertex buffer. * @internal */ -export class PolylineArgs { - public colors = new ColorIndex(); - public features = new FeatureIndex(); - public width = 0; - public linePixels = LinePixels.Solid; - public flags: PolylineFlags; - public points: QPoint3dList; - public polylines: PolylineData[]; - public pointParams: QParams3d; - - public constructor(points: QPoint3dList = new QPoint3dList(QParams3d.fromRange(Range3d.createNull())), - polylines: PolylineData[] = [], pointParams?: QParams3d, is2d = false, isPlanar = false) { - this.points = points; - this.polylines = polylines; - if (undefined === pointParams) { - this.pointParams = QParams3d.fromRange(Range3d.createNull()); - } else { - this.pointParams = pointParams; +export interface PolylineArgs { + colors: ColorIndex; + features: FeatureIndex; + width: number; + linePixels: LinePixels; + flags: PolylineFlags; + points: QPoint3dList | Omit; + polylines: PolylineData[]; +} + +/** @internal */ +export namespace PolylineArgs { + export function fromMesh(mesh: Mesh): PolylineArgs | undefined { + if (!mesh.polylines || mesh.polylines.length === 0) + return undefined; + + const polylines = []; + for (const polyline of mesh.polylines) { + const polylineData = new PolylineData(); + if (polylineData.init(polyline)) + polylines.push(polylineData); } - this.flags = new PolylineFlags(is2d, isPlanar); - } - public get isValid(): boolean { return this.polylines.length !== 0; } - public reset(): void { - this.flags.initDefaults(); - this.points = new QPoint3dList(QParams3d.fromRange(Range3d.createNull())); - this.polylines = []; - this.colors.reset(); - this.features.reset(); - } - public init(mesh: Mesh) { - this.reset(); - if (undefined === mesh.polylines) - return; + if (polylines.length === 0) + return undefined; - this.width = mesh.displayParams.width; - this.linePixels = mesh.displayParams.linePixels; - this.flags.is2d = mesh.is2d; - this.flags.isPlanar = mesh.isPlanar; - this.flags.isDisjoint = Mesh.PrimitiveType.Point === mesh.type; - if (DisplayParams.RegionEdgeType.Outline === mesh.displayParams.regionEdgeType) { + const flags = new PolylineFlags(mesh.is2d, mesh.isPlanar); + flags.isDisjoint = mesh.type === Mesh.PrimitiveType.Point; + if (mesh.displayParams.regionEdgeType === DisplayParams.RegionEdgeType.Outline) { // This polyline is behaving as the edges of a region surface. - if (undefined === mesh.displayParams.gradient || mesh.displayParams.gradient.isOutlined) - this.flags.setIsNormalEdge(); + if (!mesh.displayParams.gradient || mesh.displayParams.gradient.isOutlined) + flags.setIsNormalEdge(); else - this.flags.setIsOutlineEdge(); // edges only displayed if fill undisplayed... + flags.setIsOutlineEdge(); // edges only displayed if fill undisplayed } - mesh.polylines.forEach((polyline) => { - const indexedPolyline = new PolylineData(); - if (indexedPolyline.init(polyline)) { this.polylines.push(indexedPolyline); } - }); - if (!this.isValid) { return false; } - this.finishInit(mesh); - return true; - } - public finishInit(mesh: Mesh) { - this.pointParams = mesh.points.params; - this.points = mesh.points; - mesh.colorMap.toColorIndex(this.colors, mesh.colors); - mesh.toFeatureIndex(this.features); + const colors = new ColorIndex(); + mesh.colorMap.toColorIndex(colors, mesh.colors); + + const features = new FeatureIndex(); + mesh.toFeatureIndex(features); + + return { + width: mesh.displayParams.width, + linePixels: mesh.displayParams.linePixels, + flags, + polylines, + points: mesh.points, + colors, + features, + }; } } @@ -110,101 +119,84 @@ export class MeshArgsEdges { /* A carrier of information needed to describe a triangle mesh and its edges. * @internal */ -export class MeshArgs { - public edges = new MeshArgsEdges(); - public vertIndices?: number[]; - public points?: QPoint3dList; - public normals?: OctEncodedNormal[]; - public textureUv?: Point2d[]; - public texture?: RenderTexture; - public colors = new ColorIndex(); - public features = new FeatureIndex(); - public material?: RenderMaterial; - public fillFlags = FillFlags.None; - public isPlanar = false; - public is2d = false; - public hasBakedLighting = false; - public isVolumeClassifier = false; - public hasFixedNormals = false; - public auxChannels?: ReadonlyArray; - - public clear() { - this.edges.clear(); - this.vertIndices = undefined; - this.points = undefined; - this.normals = undefined; - this.textureUv = undefined; - this.texture = undefined; - this.colors.reset(); - this.features.reset(); - this.material = undefined; - this.fillFlags = FillFlags.None; - this.isPlanar = this.is2d = this.hasBakedLighting = this.isVolumeClassifier = this.hasFixedNormals = false; - this.auxChannels = undefined; - } - - public init(mesh: Mesh): boolean { - this.clear(); - if (undefined === mesh.triangles || mesh.triangles.isEmpty) - return false; - - assert(0 < mesh.points.length); - - this.vertIndices = mesh.triangles.indices; - this.points = mesh.points; - - if (!mesh.displayParams.ignoreLighting && 0 < mesh.normals.length) - this.normals = mesh.normals; - - if (0 < mesh.uvParams.length) - this.textureUv = mesh.uvParams; - - mesh.colorMap.toColorIndex(this.colors, mesh.colors); - mesh.toFeatureIndex(this.features); - - this.material = mesh.displayParams.material; - if (undefined !== mesh.displayParams.textureMapping) - this.texture = mesh.displayParams.textureMapping.texture; - - this.fillFlags = mesh.displayParams.fillFlags; - this.isPlanar = mesh.isPlanar; - this.is2d = mesh.is2d; - this.hasBakedLighting = (true === mesh.hasBakedLighting); - this.isVolumeClassifier = (true === mesh.isVolumeClassifier); - - this.edges.width = mesh.displayParams.width; - this.edges.linePixels = mesh.displayParams.linePixels; - this.auxChannels = mesh.auxChannels; - - const meshEdges = mesh.edges; - if (undefined === meshEdges) - return true; - - this.edges.edges.init(mesh.edges); - this.edges.silhouettes.init(mesh.edges); +export interface MeshArgs { + edges?: MeshArgsEdges; + vertIndices: number[]; + points: QPoint3dList | Omit; + normals?: OctEncodedNormal[]; + colors: ColorIndex; + features: FeatureIndex; + fillFlags: FillFlags; + isPlanar?: boolean; + is2d?: boolean; + hasBakedLighting?: boolean; + isVolumeClassifier?: boolean; + hasFixedNormals?: boolean; + auxChannels?: ReadonlyArray; + material?: RenderMaterial; + textureMapping?: { + texture: RenderTexture; + uvParams: Point2d[]; + }; +} - const polylines: PolylineData[] = []; - meshEdges.polylines.forEach((meshPolyline: MeshPolyline) => { - const polyline = new PolylineData(); - if (polyline.init(meshPolyline)) { polylines.push(polyline); } - }); +/** @internal */ +export namespace MeshArgs { + export function fromMesh(mesh: Mesh): MeshArgs | undefined { + if (!mesh.triangles || mesh.triangles.isEmpty || mesh.points.length === 0) + return undefined; + + const texture = mesh.displayParams.textureMapping?.texture; + const textureMapping = texture && mesh.uvParams.length > 0 ? { texture, uvParams: mesh.uvParams } : undefined; + + const colors = new ColorIndex(); + mesh.colorMap.toColorIndex(colors, mesh.colors); + + const features = new FeatureIndex(); + mesh.toFeatureIndex(features); + + let edges; + if (mesh.edges) { + edges = new MeshArgsEdges(); + edges.width = mesh.displayParams.width; + edges.linePixels = mesh.displayParams.linePixels; + edges.edges.init(mesh.edges); + edges.silhouettes.init(mesh.edges); + + const polylines = []; + for (const meshPolyline of mesh.edges.polylines) { + const polyline = new PolylineData(); + if (polyline.init(meshPolyline)) + polylines.push(polyline); + } - this.edges.polylines.init(polylines); + edges.polylines.init(polylines); + } - return true; + return { + vertIndices: mesh.triangles.indices, + points: mesh.points, + normals: !mesh.displayParams.ignoreLighting && mesh.normals.length > 0 ? mesh.normals : undefined, + textureMapping, + colors, + features, + material: mesh.displayParams.material, + fillFlags: mesh.displayParams.fillFlags, + isPlanar: mesh.isPlanar, + is2d: mesh.is2d, + hasBakedLighting: true === mesh.hasBakedLighting, + hasFixedNormals: false, + isVolumeClassifier: true === mesh.isVolumeClassifier, + edges, + auxChannels: mesh.auxChannels, + }; } } -/** @internal */ -export class MeshGraphicArgs { - public polylineArgs = new PolylineArgs(); - public meshArgs: MeshArgs = new MeshArgs(); -} - /** @internal */ export class Mesh { private readonly _data: TriangleList | MeshPolylineList; - public readonly points: QPoint3dList; + public readonly points: MeshPointList; public readonly normals: OctEncodedNormal[] = []; public readonly uvParams: Point2d[] = []; public readonly colorMap: ColorMap = new ColorMap(); // used to be called ColorTable @@ -229,7 +221,18 @@ export class Mesh { this.isPlanar = isPlanar; this.hasBakedLighting = (true === props.hasBakedLighting); this.isVolumeClassifier = (true === props.isVolumeClassifier); - this.points = new QPoint3dList(QParams3d.fromRange(range)); + if (props.quantizePositions) { + this.points = new QPoint3dList(QParams3d.fromRange(range)); + } else { + const points = [] as unknown as Point3dList; + points.range = range; + const center = range.center; + points.add = (pt: Point3d) => { + // assert(range.containsPoint(pt)); rounding error triggers this sometimes... + points.push(pt.minus(center)); + }; + this.points = points; + } } public static create(props: Mesh.Props): Mesh { return new Mesh(props); } @@ -284,15 +287,21 @@ export class Mesh { this.features.toFeatureIndex(index); } - public getGraphics(args: MeshGraphicArgs, system: RenderSystem, instancesOrViewIndependentOrigin?: InstancedGraphicParams | Point3d): RenderGraphic | undefined { - if (undefined !== this.triangles && this.triangles.length !== 0) { - if (args.meshArgs.init(this)) - return system.createTriMesh(args.meshArgs, instancesOrViewIndependentOrigin); - } else if (undefined !== this.polylines && this.polylines.length !== 0 && args.polylineArgs.init(this)) { - return system.createIndexedPolylines(args.polylineArgs, instancesOrViewIndependentOrigin); - } + public toMeshArgs(): MeshArgs | undefined { + return MeshArgs.fromMesh(this); + } + + public toPolylineArgs(): PolylineArgs | undefined { + return PolylineArgs.fromMesh(this); + } + + public getGraphics(system: RenderSystem, instancesOrViewIndependentOrigin?: InstancedGraphicParams | Point3d): RenderGraphic | undefined { + const meshArgs = this.toMeshArgs(); + if (meshArgs) + return system.createTriMesh(meshArgs, instancesOrViewIndependentOrigin); - return undefined; + const plArgs = this.toPolylineArgs(); + return plArgs ? system.createIndexedPolylines(plArgs, instancesOrViewIndependentOrigin) : undefined; } public addPolyline(poly: MeshPolyline): void { @@ -321,7 +330,7 @@ export class Mesh { public addVertex(props: VertexKeyProps): number { const { position, normal, uvParam, fillColor } = props; - this.points.push(position); + this.points.add(position); if (undefined !== normal) this.normals.push(normal); @@ -411,6 +420,7 @@ export namespace Mesh { // eslint-disable-line no-redeclare features?: Mesh.Features; type: Mesh.PrimitiveType; range: Range3d; + quantizePositions: boolean; is2d: boolean; isPlanar: boolean; hasBakedLighting?: boolean; diff --git a/core/frontend/src/render/webgl/CachedGeometry.ts b/core/frontend/src/render/webgl/CachedGeometry.ts index f6fef00570cb..9669ece37809 100644 --- a/core/frontend/src/render/webgl/CachedGeometry.ts +++ b/core/frontend/src/render/webgl/CachedGeometry.ts @@ -91,6 +91,11 @@ export abstract class CachedGeometry implements WebGLDisposable, RenderMemory.Co // Returns true if this primitive contains auxillary animation data. public get hasAnimation(): boolean { return false; } + /** If false, the geometry's positions are not quantized. + * qOrigin and qScale can still be used to derive the geometry's range, but will not be passed to the shader. + * see VertexLUT.usesQuantizedPositions. + */ + public get usesQuantizedPositions(): boolean { return true; } /** Returns the origin of this geometry's quantization parameters. */ public abstract get qOrigin(): Float32Array; /** Returns the scale of this geometry's quantization parameters. */ @@ -198,6 +203,7 @@ export abstract class LUTGeometry extends CachedGeometry { // Override this if your color varies based on the target public getColor(_target: Target): ColorInfo { return this.lut.colorInfo; } + public override get usesQuantizedPositions() { return this.lut.usesQuantizedPositions; } public get qOrigin(): Float32Array { return this.lut.qOrigin; } public get qScale(): Float32Array { return this.lut.qScale; } public override get hasAnimation() { return this.lut.hasAnimation; } diff --git a/core/frontend/src/render/webgl/RealityMesh.ts b/core/frontend/src/render/webgl/RealityMesh.ts index 66b589674149..1e562d612512 100644 --- a/core/frontend/src/render/webgl/RealityMesh.ts +++ b/core/frontend/src/render/webgl/RealityMesh.ts @@ -218,6 +218,7 @@ export class RealityMeshGeometryParams extends IndexedGeometryParams { /** @internal */ export class RealityMeshGeometry extends IndexedGeometry implements IDisposable, RenderMemory.Consumer { + public readonly hasTextures: boolean; public override get asRealityMesh(): RealityMeshGeometry | undefined { return this; } public override get isDisposed(): boolean { return this._realityMeshParams.isDisposed; } public get uvQParams() { return this._realityMeshParams.uvParams.params; } @@ -228,6 +229,7 @@ export class RealityMeshGeometry extends IndexedGeometry implements IDisposable, private constructor(private _realityMeshParams: RealityMeshGeometryParams, public textureParams: RealityTextureParams | undefined, private readonly _transform: Transform | undefined, public readonly baseColor: ColorDef | undefined, private _baseIsTransparent: boolean, private _isTerrain: boolean) { super(_realityMeshParams); + this.hasTextures = undefined !== textureParams && textureParams.params.some((x) => undefined !== x.texture); } public override dispose() { diff --git a/core/frontend/src/render/webgl/ShaderBuilder.ts b/core/frontend/src/render/webgl/ShaderBuilder.ts index 198a7450f488..8e2e24997bcb 100644 --- a/core/frontend/src/render/webgl/ShaderBuilder.ts +++ b/core/frontend/src/render/webgl/ShaderBuilder.ts @@ -461,14 +461,11 @@ export class SourceBuilder { } /** @internal */ -export const enum ShaderBuilderFlags { - // No special flags. Vertex data comes from attributes, geometry is not instanced. - None = 0, - // Vertex data comes from a texture. - VertexTable = 1 << 0, - // Geometry is instanced. - Instanced = 1 << 1, - InstancedVertexTable = VertexTable | Instanced, +export interface ShaderBuilderFlags { + /** If defined and true, the geometry is instanced. */ + readonly instanced?: boolean; + /** If defined and greater than zero, the vertex data comes from a texture, and each vertex in the table uses no more than this number of RGBA values. */ + readonly maxRgbaPerVertex?: number; } /** @@ -487,8 +484,13 @@ export class ShaderBuilder extends ShaderVariables { protected readonly _flags: ShaderBuilderFlags; protected _initializers: string[] = new Array(); - public get usesVertexTable() { return ShaderBuilderFlags.None !== (this._flags & ShaderBuilderFlags.VertexTable); } - public get usesInstancedGeometry() { return ShaderBuilderFlags.None !== (this._flags & ShaderBuilderFlags.Instanced); } + public get usesVertexTable(): boolean { + return !!this._flags.maxRgbaPerVertex; + } + + public get usesInstancedGeometry(): boolean { + return !!this._flags.instanced; + } public addInitializer(initializer: string): void { if (-1 === this._initializers.indexOf(initializer)) @@ -711,7 +713,7 @@ export class VertexShaderBuilder extends ShaderBuilder { private buildPrelude(attrMap?: Map): SourceBuilder { return this.buildPreludeCommon(attrMap, true); } - public constructor(flags: ShaderBuilderFlags) { + public constructor(flags: ShaderBuilderFlags = { }) { super(VertexShaderComponent.COUNT, flags); this.addDefine("MAT_NORM", "g_nmx"); @@ -727,6 +729,10 @@ export class VertexShaderBuilder extends ShaderBuilder { addPosition(this, this.usesVertexTable); } + public get maxRgbaPerVertex(): number | undefined { + return this._flags.maxRgbaPerVertex; + } + public get(id: VertexShaderComponent): string | undefined { return this.getComponent(id); } public set(id: VertexShaderComponent, component: string) { this.addComponent(id, component); } public unset(id: VertexShaderComponent) { this.removeComponent(id); } @@ -922,7 +928,7 @@ export const enum FragmentShaderComponent { export class FragmentShaderBuilder extends ShaderBuilder { public requiresEarlyZWorkaround = false; - public constructor(flags: ShaderBuilderFlags) { + public constructor(flags: ShaderBuilderFlags = { }) { super(FragmentShaderComponent.COUNT, flags); if (System.instance.capabilities.isWebGL2) @@ -1129,7 +1135,7 @@ export class ProgramBuilder { private readonly _flags: ShaderBuilderFlags; private readonly _attrMap?: Map; - public constructor(attrMap?: Map, flags = ShaderBuilderFlags.None) { + public constructor(attrMap?: Map, flags: ShaderBuilderFlags = { }) { this._attrMap = attrMap; this.vert = new VertexShaderBuilder(flags); this.frag = new FragmentShaderBuilder(flags); diff --git a/core/frontend/src/render/webgl/VertexLUT.ts b/core/frontend/src/render/webgl/VertexLUT.ts index d4879a23fa94..7777ffaf0a74 100644 --- a/core/frontend/src/render/webgl/VertexLUT.ts +++ b/core/frontend/src/render/webgl/VertexLUT.ts @@ -65,7 +65,7 @@ export class AuxChannelLUT implements WebGLDisposable { } } -/** Represents the finished lookup table ready for submittal to GPU. +/** Represents the finished lookup table ready for submission to GPU. * @internal */ export class VertexLUT implements WebGLDisposable { @@ -73,8 +73,9 @@ export class VertexLUT implements WebGLDisposable { public readonly numVertices: number; public readonly numRgbaPerVertex: number; public readonly colorInfo: ColorInfo; - public readonly qOrigin: Float32Array; // Origin of quantized positions - public readonly qScale: Float32Array; // Scale of quantized positions + public readonly usesQuantizedPositions: boolean; // If true, positions are 16-bit integers quantized to qOrigin and qScale; otherwise they are unquantized 32-bit floats. + public readonly qOrigin: Float32Array; // Origin of quantized range + public readonly qScale: Float32Array; // Scale of quantized range public readonly uvQParams?: Float32Array; // If vertices contain texture UV params, quantization parameters as [origin.x, origin.y, scale.x, scale.y ] public readonly auxChannels?: AuxChannelLUT; @@ -95,16 +96,17 @@ export class VertexLUT implements WebGLDisposable { return undefined; const auxLUT = undefined !== aux ? AuxChannelLUT.create(aux) : undefined; - return new VertexLUT(texture, vt, ColorInfo.createFromVertexTable(vt), vt.qparams, vt.uvParams, auxLUT); + return new VertexLUT(texture, vt, ColorInfo.createFromVertexTable(vt), vt.qparams, !vt.usesUnquantizedPositions, vt.uvParams, auxLUT); } - private constructor(texture: TextureHandle, table: VertexTable, colorInfo: ColorInfo, qparams: QParams3d, uvParams?: QParams2d, auxChannels?: AuxChannelLUT) { + private constructor(texture: TextureHandle, table: VertexTable, colorInfo: ColorInfo, qparams: QParams3d, positionsAreQuantized: boolean, uvParams?: QParams2d, auxChannels?: AuxChannelLUT) { this.texture = texture; this.numVertices = table.numVertices; this.numRgbaPerVertex = table.numRgbaPerVertex; this.colorInfo = colorInfo; this.qOrigin = qorigin3dToArray(qparams.origin); this.qScale = qscale3dToArray(qparams.scale); + this.usesQuantizedPositions = positionsAreQuantized; this.auxChannels = auxChannels; if (undefined !== uvParams) diff --git a/core/frontend/src/render/webgl/glsl/Color.ts b/core/frontend/src/render/webgl/glsl/Color.ts index 74143939d359..c57a04e4f411 100644 --- a/core/frontend/src/render/webgl/glsl/Color.ts +++ b/core/frontend/src/render/webgl/glsl/Color.ts @@ -14,7 +14,7 @@ import { addInstanceColor } from "./Instancing"; // NB: Color in color table has pre-multiplied alpha - revert it. const computeElementColor = ` float colorTableStart = u_vertParams.z * u_vertParams.w; // num rgba per-vertex times num vertices - float colorIndex = decodeUInt16(g_vertexData2); + float colorIndex = decodeUInt16(g_usesQuantizedPosition ? g_vertLutData[1].zw : g_vertLutData[4].xy); vec2 tc = computeLUTCoords(colorTableStart+colorIndex, u_vertParams.xy, g_vert_center, 1.0); vec4 lutColor = TEXTURE(u_vertLUT, tc); lutColor.rgb /= max(0.0001, lutColor.a); diff --git a/core/frontend/src/render/webgl/glsl/Decode.ts b/core/frontend/src/render/webgl/glsl/Decode.ts index 4a31a2a94544..314f8beffb03 100644 --- a/core/frontend/src/render/webgl/glsl/Decode.ts +++ b/core/frontend/src/render/webgl/glsl/Decode.ts @@ -85,3 +85,21 @@ export function addUnpackAndNormalize2Bytes(builder: ShaderBuilder): void { builder.addFunction(unpack2Bytes); builder.addFunction(unpackAndNormalize2Bytes); } + +/** Given an IEEE 32-bit float stuffed into a RGBA unsigned byte texture, extract the float. + * The input vec4 components are in the integer range [0..255]. + * From https://github.com/CesiumGS/cesium/blob/main/Source/Shaders/Builtin/Functions/unpackFloat.glsl + * @internal + */ +export const decodeFloat32 = ` +float decodeFloat32(vec4 packedFloat) { + float sign = 1.0 - step(128.0, packedFloat[3]) * 2.0; + float exponent = 2.0 * mod(packedFloat[3], 128.0) + step(128.0, packedFloat[2]) - 127.0; + if (exponent == -127.0) + return 0.0; + + float mantissa = mod(packedFloat[2], 128.0) * 65536.0 + packedFloat[1] * 256.0 + packedFloat[0] + float(0x800000); + float result = sign * exp2(exponent - 23.0) * mantissa; + return result; +} +`; diff --git a/core/frontend/src/render/webgl/glsl/Edge.ts b/core/frontend/src/render/webgl/glsl/Edge.ts index 7ea77005f144..84850cf8d3f3 100644 --- a/core/frontend/src/render/webgl/glsl/Edge.ts +++ b/core/frontend/src/render/webgl/glsl/Edge.ts @@ -8,7 +8,7 @@ import { assert } from "@itwin/core-bentley"; import { AttributeMap } from "../AttributeMap"; -import { FragmentShaderComponent, ProgramBuilder, ShaderBuilderFlags, VariableType, VertexShaderBuilder, VertexShaderComponent } from "../ShaderBuilder"; +import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderBuilder, VertexShaderComponent } from "../ShaderBuilder"; import { IsAnimated, IsInstanced, IsThematic } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { TextureUnit } from "../RenderFlags"; @@ -27,11 +27,20 @@ export type EdgeBuilderType = "SegmentEdge" | "Silhouette" | "IndexedEdge"; const computeOtherPos = ` vec2 tc = computeLUTCoords(g_otherIndex, u_vertParams.xy, g_vert_center, u_vertParams.z); - vec4 enc1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - tc.x += g_vert_stepX; - vec4 enc2 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec3 qpos = vec3(decodeUInt16(enc1.xy), decodeUInt16(enc1.zw), decodeUInt16(enc2.xy)); - g_otherPos = unquantizePosition(qpos, u_qOrigin, u_qScale); + if (g_usesQuantizedPosition) { + vec4 enc1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + tc.x += g_vert_stepX; + vec4 enc2 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + vec3 qpos = vec3(decodeUInt16(enc1.xy), decodeUInt16(enc1.zw), decodeUInt16(enc2.xy)); + g_otherPos = unquantizePosition(qpos, u_qOrigin, u_qScale); + } else { + for (int i = 0; i < 3; i++) { + g_otherPos[i] = decodeFloat32(floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5)); + tc.x += g_vert_stepX; + } + + g_otherPos.w = 1.0; + } `; const decodeEndPointAndQuadIndices = ` @@ -227,7 +236,7 @@ function createBase(type: EdgeBuilderType, instanced: IsInstanced, isAnimated: I const techId = isSilhouette ? TechniqueId.SilhouetteEdge : (isIndexed ? TechniqueId.IndexedEdge : TechniqueId.Edge); const attrMap = AttributeMap.findAttributeMap(techId, isInstanced); - const builder = new ProgramBuilder(attrMap, isInstanced ? ShaderBuilderFlags.InstancedVertexTable : ShaderBuilderFlags.VertexTable); + const builder = new ProgramBuilder(attrMap, { maxRgbaPerVertex: 5, instanced: isInstanced }); const vert = builder.vert; vert.addGlobal("g_otherPos", VariableType.Vec4); diff --git a/core/frontend/src/render/webgl/glsl/PointString.ts b/core/frontend/src/render/webgl/glsl/PointString.ts index 745c0cb6d87f..df4d12bebf1c 100644 --- a/core/frontend/src/render/webgl/glsl/PointString.ts +++ b/core/frontend/src/render/webgl/glsl/PointString.ts @@ -7,7 +7,7 @@ */ import { AttributeMap } from "../AttributeMap"; -import { FragmentShaderComponent, ProgramBuilder, ShaderBuilderFlags, VariableType, VertexShaderComponent } from "../ShaderBuilder"; +import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderComponent } from "../ShaderBuilder"; import { IsInstanced } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { addColor } from "./Color"; @@ -38,7 +38,7 @@ const computeRoundCorners = " v_roundCorners = gl_PointSize > 4.0 ? 1.0 : 0.0;" function createBase(instanced: IsInstanced): ProgramBuilder { const attrMap = AttributeMap.findAttributeMap(TechniqueId.PointString, IsInstanced.Yes === instanced); - const builder = new ProgramBuilder(attrMap, instanced ? ShaderBuilderFlags.InstancedVertexTable : ShaderBuilderFlags.VertexTable); + const builder = new ProgramBuilder(attrMap, { maxRgbaPerVertex: 5, instanced: IsInstanced.Yes === instanced }); const vert = builder.vert; vert.set(VertexShaderComponent.ComputePosition, computePosition); addModelViewProjectionMatrix(vert); diff --git a/core/frontend/src/render/webgl/glsl/Polyline.ts b/core/frontend/src/render/webgl/glsl/Polyline.ts index a3a991d2c634..ae3fa9459965 100644 --- a/core/frontend/src/render/webgl/glsl/Polyline.ts +++ b/core/frontend/src/render/webgl/glsl/Polyline.ts @@ -10,7 +10,7 @@ import { assert } from "@itwin/core-bentley"; import { AttributeMap } from "../AttributeMap"; import { TextureUnit } from "../RenderFlags"; import { - FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilderFlags, VariableType, VertexShaderBuilder, VertexShaderComponent, + FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderBuilder, VertexShaderComponent, } from "../ShaderBuilder"; import { System } from "../System"; import { IsInstanced } from "../TechniqueFlags"; @@ -208,11 +208,22 @@ const decodePosition = ` vec4 decodePosition(vec3 baseIndex) { float index = decodeUInt24(baseIndex); vec2 tc = compute_vert_coords(index); - vec4 e0 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - tc.x += g_vert_stepX; - vec4 e1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec3 qpos = vec3(decodeUInt16(e0.xy), decodeUInt16(e0.zw), decodeUInt16(e1.xy)); - return unquantizePosition(qpos, u_qOrigin, u_qScale); + if (g_usesQuantizedPosition) { + vec4 e0 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + tc.x += g_vert_stepX; + vec4 e1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + vec3 qpos = vec3(decodeUInt16(e0.xy), decodeUInt16(e0.zw), decodeUInt16(e1.xy)); + return unquantizePosition(qpos, u_qOrigin, u_qScale); + } + + vec4 position; + for (int i = 0; i < 3; i++) { + position[i] = decodeFloat32(floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5)); + tc.x += g_vert_stepX; + } + + position.w = 1.0; + return position; } `; @@ -332,8 +343,11 @@ const computePosition = ` const lineCodeArgs = "g_windowDir, g_windowPos, miterAdjust"; /** @internal */ -export function createPolylineBuilder(instanced: IsInstanced): ProgramBuilder { - const builder = new ProgramBuilder(AttributeMap.findAttributeMap(TechniqueId.Polyline, IsInstanced.Yes === instanced), instanced ? ShaderBuilderFlags.InstancedVertexTable : ShaderBuilderFlags.VertexTable); +export function createPolylineBuilder(isInstanced: IsInstanced): ProgramBuilder { + const instanced = IsInstanced.Yes === isInstanced; + const attrMap = AttributeMap.findAttributeMap(TechniqueId.Polyline, instanced); + const builder = new ProgramBuilder(attrMap, { maxRgbaPerVertex: 5, instanced }); + addShaderFlags(builder); addCommon(builder); @@ -348,8 +362,11 @@ export function createPolylineBuilder(instanced: IsInstanced): ProgramBuilder { } /** @internal */ -export function createPolylineHiliter(instanced: IsInstanced): ProgramBuilder { - const builder = new ProgramBuilder(AttributeMap.findAttributeMap(TechniqueId.Polyline, IsInstanced.Yes === instanced), instanced ? ShaderBuilderFlags.InstancedVertexTable : ShaderBuilderFlags.VertexTable); +export function createPolylineHiliter(isInstanced: IsInstanced): ProgramBuilder { + const instanced = IsInstanced.Yes === isInstanced; + const attrMap = AttributeMap.findAttributeMap(TechniqueId.Polyline, instanced); + const builder = new ProgramBuilder(attrMap, { maxRgbaPerVertex: 5, instanced }); + addCommon(builder); addFrustum(builder); addHiliter(builder, true); diff --git a/core/frontend/src/render/webgl/glsl/RealityMesh.ts b/core/frontend/src/render/webgl/glsl/RealityMesh.ts index 2a7022297764..b48f885df6c8 100644 --- a/core/frontend/src/render/webgl/glsl/RealityMesh.ts +++ b/core/frontend/src/render/webgl/glsl/RealityMesh.ts @@ -130,8 +130,7 @@ function addTextures(builder: ProgramBuilder, maxTexturesPerMesh: number) { builder.frag.addUniform("u_texturesPresent", VariableType.Boolean, (program) => { program.addGraphicUniform("u_texturesPresent", (uniform, params) => { - const textureCount = params.geometry.asRealityMesh!.textureParams?.params.length; - uniform.setUniform1i(textureCount ? 1 : 0); + uniform.setUniform1i(params.geometry.asRealityMesh!.hasTextures ? 1 : 0); }); }); diff --git a/core/frontend/src/render/webgl/glsl/Surface.ts b/core/frontend/src/render/webgl/glsl/Surface.ts index ce42b7cc84ad..3761b58be7e3 100644 --- a/core/frontend/src/render/webgl/glsl/Surface.ts +++ b/core/frontend/src/render/webgl/glsl/Surface.ts @@ -11,7 +11,7 @@ import { AttributeMap } from "../AttributeMap"; import { Material } from "../Material"; import { Pass, SurfaceBitIndex, SurfaceFlags, TextureUnit } from "../RenderFlags"; import { - FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilder, ShaderBuilderFlags, VariableType, VertexShaderComponent, + FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariableType, VertexShaderComponent, } from "../ShaderBuilder"; import { System } from "../System"; import { FeatureMode, IsAnimated, IsClassified, IsInstanced, IsShadowable, IsThematic, TechniqueFlags } from "../TechniqueFlags"; @@ -213,9 +213,10 @@ const computePositionPostlude = ` return u_proj * pos; `; -function createCommon(instanced: IsInstanced, animated: IsAnimated, shadowable: IsShadowable, isThematic: IsThematic, isHiliter: boolean): ProgramBuilder { - const attrMap = AttributeMap.findAttributeMap(TechniqueId.Surface, IsInstanced.Yes === instanced); - const builder = new ProgramBuilder(attrMap, instanced ? ShaderBuilderFlags.InstancedVertexTable : ShaderBuilderFlags.VertexTable); +function createCommon(isInstanced: IsInstanced, animated: IsAnimated, shadowable: IsShadowable, isThematic: IsThematic, isHiliter: boolean): ProgramBuilder { + const instanced = IsInstanced.Yes === isInstanced; + const attrMap = AttributeMap.findAttributeMap(TechniqueId.Surface, instanced); + const builder = new ProgramBuilder(attrMap, { maxRgbaPerVertex: 6, instanced }); const vert = builder.vert; if (animated) @@ -353,11 +354,16 @@ vec3 octDecodeNormal(vec2 e) { `; const computeNormal = ` - vec2 tc = g_vertexBaseCoords; - tc.x += 3.0 * g_vert_stepX; - vec4 enc = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec2 normal = u_surfaceFlags[kSurfaceBitIndex_HasColorAndNormal] ? enc.xy : g_vertexData2; - return u_surfaceFlags[kSurfaceBitIndex_HasNormals] ? normalize(MAT_NORM * octDecodeNormal(normal)) : vec3(0.0); + if (!u_surfaceFlags[kSurfaceBitIndex_HasNormals]) + return vec3(0.0); + + vec2 normal; + if (u_surfaceFlags[kSurfaceBitIndex_HasColorAndNormal]) + normal = g_usesQuantizedPosition ? g_vertLutData[3].xy : g_vertLutData[4].zw; + else + normal = g_usesQuantizedPosition ? g_vertLutData[1].zw : g_vertLutData[5].xy; + + return normalize(MAT_NORM * octDecodeNormal(normal)); `; const computeAnimatedNormal = ` @@ -370,9 +376,7 @@ const applyBackgroundColor = ` `; const computeTexCoord = ` - vec2 tc = g_vertexBaseCoords; - tc.x += 3.0 * g_vert_stepX; - vec4 rgba = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + vec4 rgba = g_usesQuantizedPosition ? g_vertLutData[3] : g_vertLutData[4]; vec2 qcoords = vec2(decodeUInt16(rgba.xy), decodeUInt16(rgba.zw)); return chooseVec2WithBitFlag(vec2(0.0), unquantize2d(qcoords, u_qTexCoordParams), surfaceFlags, kSurfaceBit_HasTexture); `; @@ -439,20 +443,15 @@ function addNormal(builder: ProgramBuilder, instanced: IsInstanced, animated: Is builder.vert.addFunction(octDecodeNormal); addChooseWithBitFlagFunctions(builder.vert); - builder.addFunctionComputedVarying("v_n", VariableType.Vec3, "computeLightingNormal", animated ? computeAnimatedNormal : computeNormal); + builder.vert.addFunction("vec3 computeSurfaceNormal()", computeNormal); + builder.addFunctionComputedVarying("v_n", VariableType.Vec3, "computeLightingNormal", animated ? computeAnimatedNormal : "return computeSurfaceNormal();"); // Set to true to colorize surfaces based on normals (in world space). // You must also set checkMaxVarying to false in ProgramBuilder.buildProgram to avoid assertions, if using a non-optimized build. const debugNormals = false; if (debugNormals) { builder.frag.set(FragmentShaderComponent.ApplyDebugColor, "return vec4(vec3(v_normal / 2.0 + 0.5), baseColor.a);"); - builder.addFunctionComputedVarying("v_normal", VariableType.Vec3, "computeDebugNormal", ` - vec2 tc = g_vertexBaseCoords; - tc.x += 3.0 * g_vert_stepX; - vec4 enc = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec2 normal = u_surfaceFlags[kSurfaceBitIndex_HasColorAndNormal] ? enc.xy : g_vertexData2; - return u_surfaceFlags[kSurfaceBitIndex_HasNormals] ? normalize(octDecodeNormal(normal)) : vec3(0.0); - `); + builder.addInlineComputedVarying("v_normal", VariableType.Vec3, "v_normal = computeSurfaceNormal();"); } } diff --git a/core/frontend/src/render/webgl/glsl/Thematic.ts b/core/frontend/src/render/webgl/glsl/Thematic.ts index 439350387fd7..2634428383cd 100644 --- a/core/frontend/src/render/webgl/glsl/Thematic.ts +++ b/core/frontend/src/render/webgl/glsl/Thematic.ts @@ -202,12 +202,7 @@ export function getComputeThematicIndex(instanced: boolean, skipSlopeAndHillShad v_thematicIndex = findFractionalPositionOnLine(a, b, c); }`; const hillShadeMode = ` else if (kThematicDisplayMode_HillShade == u_thematicDisplayMode) { - vec2 tc = g_vertexBaseCoords; - tc.x += 3.0 * g_vert_stepX; - vec4 enc = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec2 normal = u_surfaceFlags[kSurfaceBitIndex_HasColorAndNormal] ? enc.xy : g_vertexData2; - vec3 norm = u_surfaceFlags[kSurfaceBitIndex_HasNormals] ? octDecodeNormal(normal) : vec3(0.0); - v_thematicIndex = norm.z; + v_thematicIndex = computeSurfaceNormal().z; }`; const hillShadeMode2 = ` else if (kThematicDisplayMode_HillShade == u_thematicDisplayMode) { v_thematicIndex = g_hillshadeIndex; diff --git a/core/frontend/src/render/webgl/glsl/Vertex.ts b/core/frontend/src/render/webgl/glsl/Vertex.ts index d326c659c612..1d4adcf164ab 100644 --- a/core/frontend/src/render/webgl/glsl/Vertex.ts +++ b/core/frontend/src/render/webgl/glsl/Vertex.ts @@ -14,7 +14,7 @@ import { Pass, TextureUnit } from "../RenderFlags"; import { IsInstanced } from "../TechniqueFlags"; import { VariableType, VertexShaderBuilder } from "../ShaderBuilder"; import { System } from "../System"; -import { decodeUint16, decodeUint24 } from "./Decode"; +import { decodeFloat32, decodeUint16, decodeUint24 } from "./Decode"; import { addInstanceOverrides } from "./Instancing"; import { addLookupTable } from "./LookupTable"; @@ -34,13 +34,14 @@ vec4 unquantizeVertexPosition(vec3 pos, vec3 origin, vec3 scale) { return unquan // Need to read 2 rgba values to obtain 6 16-bit integers for position const unquantizeVertexPositionFromLUT = ` vec4 unquantizeVertexPosition(vec3 encodedIndex, vec3 origin, vec3 scale) { - vec2 tc = g_vertexBaseCoords; - vec4 enc1 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - tc.x += g_vert_stepX; - vec4 enc2 = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); - vec3 qpos = vec3(decodeUInt16(enc1.xy), decodeUInt16(enc1.zw), decodeUInt16(enc2.xy)); - g_vertexData2 = enc2.zw; - return unquantizePosition(qpos, origin, scale); + if (g_usesQuantizedPosition) { + vec4 enc1 = g_vertLutData[0]; + vec4 enc2 = g_vertLutData[1]; + vec3 qpos = vec3(decodeUInt16(enc1.xy), decodeUInt16(enc1.zw), decodeUInt16(enc2.xy)); + return unquantizePosition(qpos, origin, scale); + } + + return vec4(decodeFloat32(g_vertLutData[0]), decodeFloat32(g_vertLutData[1]), decodeFloat32(g_vertLutData[2]), 1.0); } `; @@ -160,10 +161,10 @@ const scratchLutParams = new Float32Array(4); function addPositionFromLUT(vert: VertexShaderBuilder) { vert.addGlobal("g_vertexLUTIndex", VariableType.Float); vert.addGlobal("g_vertexBaseCoords", VariableType.Vec2); - vert.addGlobal("g_vertexData2", VariableType.Vec2); vert.addFunction(decodeUint24); vert.addFunction(decodeUint16); + vert.addFunction(decodeFloat32); vert.addFunction(unquantizeVertexPositionFromLUT); vert.addUniform("u_vertLUT", VariableType.Sampler2D, (prog) => { @@ -187,20 +188,41 @@ function addPositionFromLUT(vert: VertexShaderBuilder) { addLookupTable(vert, "vert", "u_vertParams.z"); vert.addInitializer(initializeVertLUTCoords); + + assert(undefined !== vert.maxRgbaPerVertex); + const maxRgbaPerVertex = vert.maxRgbaPerVertex.toString(); + vert.addGlobal(`g_vertLutData[${maxRgbaPerVertex}]`, VariableType.Vec4); + vert.addGlobal("g_usesQuantizedPosition", VariableType.Boolean); + + // Read the vertex data from the vertex table up front. If using WebGL 2, only read the number of RGBA values we actually need for this vertex table. + const loopStart = `for (int i = 0; i < ${System.instance.capabilities.isWebGL2 ? "int(u_vertParams.z)" : maxRgbaPerVertex}; i++)`; + vert.addInitializer(` + g_usesQuantizedPosition = u_qScale.x >= 0.0; + vec2 tc = g_vertexBaseCoords; + ${loopStart} { + g_vertLutData[i] = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); + tc.x += g_vert_stepX; + } + `); } +// Shader tests u_qScale.x < 0 to determine that positions are not quantized. +const unquantizedScale = new Float32Array([-1, -1, -1]); + /** @internal */ export function addPosition(vert: VertexShaderBuilder, fromLUT: boolean) { vert.addFunction(unquantizePosition); vert.addUniform("u_qScale", VariableType.Vec3, (prog) => { prog.addGraphicUniform("u_qScale", (uniform, params) => { - uniform.setUniform3fv(params.geometry.qScale); + uniform.setUniform3fv(params.geometry.usesQuantizedPositions ? params.geometry.qScale : unquantizedScale); }); }); vert.addUniform("u_qOrigin", VariableType.Vec3, (prog) => { prog.addGraphicUniform("u_qOrigin", (uniform, params) => { - uniform.setUniform3fv(params.geometry.qOrigin); + // If positions aren't quantized, the shader doesn't use the origin - don't bother updating it. + if (params.geometry.usesQuantizedPositions) + uniform.setUniform3fv(params.geometry.qOrigin); }); }); @@ -274,10 +296,8 @@ export function addFeatureAndMaterialLookup(vert: VertexShaderBuilder): void { return; const computeFeatureAndMaterialIndex = ` - vec2 tc = g_vertexBaseCoords; - tc.x += g_vert_stepX * 2.0; - g_featureAndMaterialIndex = floor(TEXTURE(u_vertLUT, tc) * 255.0 + 0.5); -`; + g_featureAndMaterialIndex = g_usesQuantizedPosition ? g_vertLutData[2] : g_vertLutData[3]; + `; vert.addGlobal("g_featureAndMaterialIndex", VariableType.Vec4); if (!vert.usesInstancedGeometry) { diff --git a/core/frontend/src/test/render/GraphicBuilder.test.ts b/core/frontend/src/test/render/GraphicBuilder.test.ts index d8666e08c7a8..7019f902fd60 100644 --- a/core/frontend/src/test/render/GraphicBuilder.test.ts +++ b/core/frontend/src/test/render/GraphicBuilder.test.ts @@ -6,7 +6,7 @@ import { expect } from "chai"; import { Cone, Point3d, PolyfaceBuilder, Range3d, Sphere, StrokeOptions, Transform, } from "@itwin/core-geometry"; -import { ColorByName, QParams3d, QPoint3dList, RenderMode } from "@itwin/core-common"; +import { ColorByName, ColorIndex, FeatureIndex, FillFlags, QParams3d, QPoint3dList, RenderMode } from "@itwin/core-common"; import { GraphicBuilder, GraphicType, ViewportGraphicBuilderOptions } from "../../render/GraphicBuilder"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; @@ -114,15 +114,21 @@ describe("GraphicBuilder", () => { describe("createTriMesh", () => { it("should create a simple mesh graphic", () => { - const args = new MeshArgs(); - const points = [new Point3d(0, 0, 0), new Point3d(10, 0, 0), new Point3d(0, 10, 0)]; - args.points = new QPoint3dList(QParams3d.fromRange(Range3d.createArray(points))); + const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createArray(points))); for (const point of points) - args.points.add(point); + qpoints.add(point); + + const colors = new ColorIndex(); + colors.initUniform(ColorByName.tan); - args.vertIndices = [0, 1, 2]; - args.colors.initUniform(ColorByName.tan); + const args: MeshArgs = { + points: qpoints, + vertIndices: [0, 1, 2], + colors, + fillFlags: FillFlags.None, + features: new FeatureIndex(), + }; const graphic = IModelApp.renderSystem.createTriMesh(args); expect(graphic).not.to.be.undefined; @@ -161,7 +167,7 @@ describe("GraphicBuilder", () => { function injectNormalsCheck(expectNormals: boolean): void { const verifyParams = (params: MeshParams) => { - expect(params.vertices.numRgbaPerVertex).to.equal(expectNormals ? 4 : 3); + expect(params.vertices.numRgbaPerVertex).to.equal(5); }; const verifyGraphic = (graphic: MeshGraphic) => { expect(graphic.meshData.type).to.equal(expectNormals ? SurfaceType.Lit : SurfaceType.Unlit); diff --git a/core/frontend/src/test/render/primitives/MeshBuilder.test.ts b/core/frontend/src/test/render/primitives/MeshBuilder.test.ts index a1d0c41dd6ae..b76bc7b6e29f 100644 --- a/core/frontend/src/test/render/primitives/MeshBuilder.test.ts +++ b/core/frontend/src/test/render/primitives/MeshBuilder.test.ts @@ -11,7 +11,7 @@ import { MockRender } from "../../../render/MockRender"; import { ScreenViewport } from "../../../Viewport"; import { DisplayParams } from "../../../render/primitives/DisplayParams"; import { Geometry } from "../../../render/primitives/geometry/GeometryPrimitives"; -import { Mesh, MeshGraphicArgs } from "../../../render/primitives/mesh/MeshPrimitives"; +import { Mesh } from "../../../render/primitives/mesh/MeshPrimitives"; import { PolyfacePrimitive, PolyfacePrimitiveList } from "../../../render/primitives/Polyface"; import { PrimitiveBuilder } from "../../../render/primitives/geometry/GeometryListBuilder"; import { StrokesPrimitiveList, StrokesPrimitivePointLists } from "../../../render/primitives/Strokes"; @@ -50,7 +50,7 @@ describe("Mesh Builder Tests", () => { const tolerance = 0.15; const areaTolerance = ToleranceRatio.facetArea * tolerance; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); expect(mb.currentPolyface).to.be.undefined; expect(mb.mesh.displayParams).to.equal(displayParams); expect(mb.mesh.type).to.equal(type); @@ -99,7 +99,7 @@ describe("Mesh Builder Tests", () => { const tolerance = 0.15; const areaTolerance = ToleranceRatio.facetArea * tolerance; - let mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + let mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); // calls addPolyline for each stroke points list in strokes expect(mb.mesh.polylines!.length).to.equal(0); @@ -110,7 +110,7 @@ describe("Mesh Builder Tests", () => { expect(lengthA).to.be.lte(lengthB); expect(mb.mesh.points.length).to.be.greaterThan(0); // calls addPointString for each stroke points list in strokes - mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); expect(mb.mesh.polylines!.length).to.equal(0); expect(mb.mesh.points.length).to.equal(0); mb.addStrokePointLists(strksPrims, true, fillColor); @@ -156,7 +156,7 @@ describe("Mesh Builder Tests", () => { const areaTolerance = ToleranceRatio.facetArea * tolerance; const type = Mesh.PrimitiveType.Mesh; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); const includeParams = false; const fillColor = ColorDef.white.tbgr; @@ -204,7 +204,7 @@ describe("Mesh Builder Tests", () => { const areaTolerance = ToleranceRatio.facetArea * tolerance; const type = Mesh.PrimitiveType.Mesh; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); const visitor = pfPrim.indexedPolyface.createVisitor(); const includeParams = false; @@ -251,7 +251,7 @@ describe("Mesh Builder Tests", () => { const areaTolerance = ToleranceRatio.facetArea * tolerance; const type = Mesh.PrimitiveType.Mesh; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); const includeParams = false; const visitor = pfPrim.indexedPolyface.createVisitor(); @@ -294,7 +294,7 @@ describe("Mesh Builder Tests", () => { const areaTolerance = ToleranceRatio.facetArea * tolerance; const type = Mesh.PrimitiveType.Mesh; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); const includeParams = false; const visitor = pfPrim.indexedPolyface.createVisitor(); @@ -316,21 +316,21 @@ describe("Mesh Builder Tests", () => { const tolerance = 0.15; const areaTolerance = ToleranceRatio.facetArea * tolerance; - let mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + let mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); let points = [new Point3d(), new Point3d(100, 100, 100), new Point3d(200, 200, 200)]; const fillColor = ColorDef.white.tbgr; points = [new Point3d(), new Point3d(1, 1, 1), new Point3d(2, 2, 2)]; type = Mesh.PrimitiveType.Polyline; - mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); expect(mb.mesh.polylines!.length).to.equal(0); mb.addPolyline(points, fillColor); expect(mb.mesh.polylines!.length).to.equal(1); points = [new Point3d()]; - mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); // if array is less than 1 in length, no polylines added expect(mb.mesh.polylines!.length).to.equal(0); @@ -347,21 +347,21 @@ describe("Mesh Builder Tests", () => { const tolerance = 0.15; const areaTolerance = ToleranceRatio.facetArea * tolerance; - let mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + let mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); let points = [new Point3d(), new Point3d(100, 100, 100), new Point3d(200, 200, 200)]; const fillColor = ColorDef.white.tbgr; points = [new Point3d(), new Point3d(1, 1, 1), new Point3d(2, 2, 2)]; type = Mesh.PrimitiveType.Polyline; - mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); expect(mb.mesh.polylines!.length).to.equal(0); mb.addPointString(points, fillColor); expect(mb.mesh.polylines!.length).to.equal(1); points = [new Point3d()]; - mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); // if array is less than 1 in length, no polylines added expect(mb.mesh.polylines!.length).to.equal(0); @@ -381,7 +381,7 @@ describe("Mesh Builder Tests", () => { const tolerance = 0.15; const areaTolerance = ToleranceRatio.facetArea * tolerance; - const mb = MeshBuilder.create({ displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const mb = MeshBuilder.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); expect(mb.mesh.triangles!.length).to.equal(0); mb.addTriangle(triangle); expect(mb.mesh.triangles!.length).to.equal(1); @@ -391,6 +391,7 @@ describe("Mesh Builder Tests", () => { options = options ?? { }; const tolerance = options.tolerance ?? 0.15; return MeshBuilder.create({ + quantizePositions: false, type, range, tolerance, @@ -403,9 +404,9 @@ describe("Mesh Builder Tests", () => { describe("aux data", () => { function expectAuxChannelTable(mesh: Mesh, expectedUint16Data: number[]): void { - const args = new MeshGraphicArgs(); - mesh.getGraphics(args, IModelApp.renderSystem); - const meshParams = MeshParams.create(args.meshArgs); + const args = mesh.toMeshArgs()!; + expect(args).not.to.be.undefined; + const meshParams = MeshParams.create(args); const aux = meshParams.auxChannels!; expect(aux).not.to.be.undefined; expect(Array.from(new Uint16Array(aux.data.buffer))).to.deep.equal(expectedUint16Data); diff --git a/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts b/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts index 0fd5d9703f32..039fbf0a44e7 100644 --- a/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts +++ b/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts @@ -436,21 +436,21 @@ describe("MeshBuilderMap Tests", () => { const areaTolerance = ToleranceRatio.facetArea * tolerance; const map = new MeshBuilderMap(tolerance, range, is2d, new GeometryOptions(GenerateEdges.No)); const key = map.getKey(displayParams, type, hasNormals, isPlanar); - const builder = map.getBuilderFromKey(key, { displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const builder = map.getBuilderFromKey(key, { quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); const builder2 = map.get(key); // expect same key to return same builder reference expect(builder).to.equal(builder2); - const builder3 = map.getBuilderFromKey(key, { displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const builder3 = map.getBuilderFromKey(key, { quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); // expect same key pass into getBuilderFromKey to not create new instance of builder, but instead return previously stored instance expect(builder).to.equal(builder3); const key2 = map.getKey(displayParams, type, hasNormals, isPlanar); - const builder4 = map.getBuilderFromKey(key2, { displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); + const builder4 = map.getBuilderFromKey(key2, { quantizePositions: false, displayParams, type, range, is2d, isPlanar, tolerance, areaTolerance }); // expect an equivalent key (different key instance) to return same builder reference expect(builder).to.equal(builder4); diff --git a/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts b/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts index 1b96f4c63ba1..c0f3c230a536 100644 --- a/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts +++ b/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; -import { ColorDef, MeshPolyline, OctEncodedNormal, QPoint3d } from "@itwin/core-common"; +import { ColorDef, MeshPolyline, OctEncodedNormal } from "@itwin/core-common"; import { DisplayParams } from "../../../render/primitives/DisplayParams"; import { Triangle } from "../../../render/primitives/Primitives"; import { Mesh } from "../../../render/primitives/mesh/MeshPrimitives"; @@ -26,24 +26,24 @@ describe("MeshPrimitive Tests", () => { const is2d = false; const isPlanar = true; - let m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + let m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.type).to.equal(type); expect(m.displayParams).to.equal(displayParams); expect(m.features).to.be.undefined; expect(m.is2d).to.equal(is2d); expect(m.isPlanar).to.equal(isPlanar); - expect(m.points).to.not.be.empty; + expect(m.points.length).to.equal(0); expect(m.edges).to.be.undefined; expect(m.triangles).to.not.be.undefined; expect(m.polylines).to.be.undefined; type = Mesh.PrimitiveType.Polyline; - m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.polylines).to.not.be.undefined; expect(m.triangles).to.be.undefined; type = Mesh.PrimitiveType.Point; - m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.polylines).to.not.be.undefined; expect(m.triangles).to.be.undefined; }); @@ -55,7 +55,7 @@ describe("MeshPrimitive Tests", () => { const is2d = false; const isPlanar = true; - let m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + let m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.polylines!.length).to.equal(0); let mp = new MeshPolyline([1, 2, 3]); @@ -64,7 +64,7 @@ describe("MeshPrimitive Tests", () => { // doesn't add polyline if meshpolyline indices has a length less that 2 type = Mesh.PrimitiveType.Polyline; - m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.polylines!.length).to.equal(0); mp = new MeshPolyline([1]); m.addPolyline(mp); @@ -78,7 +78,7 @@ describe("MeshPrimitive Tests", () => { const is2d = false; const isPlanar = true; - const m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + const m = Mesh.create({ quantizePositions: false, displayParams, type, range, is2d, isPlanar }); expect(m.triangles!.length).to.equal(0); const t = new Triangle(); @@ -93,30 +93,30 @@ describe("MeshPrimitive Tests", () => { const is2d = false; const isPlanar = true; - let m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + let m = Mesh.create({ quantizePositions: true, displayParams, type, range, is2d, isPlanar }); expect(m.points.length).to.equal(0); - let q = QPoint3d.create(new Point3d(100, 100, 100), m.points.params); - let index = m.addVertex({ position: q, fillColor: ColorDef.white.tbgr }); + let p = new Point3d(100, 100, 100); + let index = m.addVertex({ position: p, fillColor: ColorDef.white.tbgr }); expect(index).to.equal(0); expect(m.points.length).to.equal(1); expect(m.normals.length).to.equal(0); expect(m.uvParams.length).to.equal(0); - m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); + m = Mesh.create({ quantizePositions: true, displayParams, type, range, is2d, isPlanar }); expect(m.normals.length).to.equal(0); expect(m.uvParams.length).to.equal(0); expect(m.points.length).to.equal(0); const oct = new OctEncodedNormal(10); const param = new Point2d(10, 10); - q = QPoint3d.create(new Point3d(100, 100, 100), m.points.params); - index = m.addVertex({ position: q, fillColor: ColorDef.white.tbgr, normal: oct, uvParam: param }); + p = new Point3d(100, 100, 100); + index = m.addVertex({ position: p, fillColor: ColorDef.white.tbgr, normal: oct, uvParam: param }); expect(m.normals.length).to.equal(1); expect(m.uvParams.length).to.equal(1); expect(m.points.length).to.equal(1); - m = Mesh.create({ displayParams, type, range, is2d, isPlanar }); - const key = new VertexKey(q, ColorDef.white.tbgr, oct, param); + m = Mesh.create({ quantizePositions: true, displayParams, type, range, is2d, isPlanar }); + const key = new VertexKey(p, ColorDef.white.tbgr, oct, param); m.addVertex(key); expect(m.points.length).to.equal(1); expect(m.normals.length).to.equal(1); diff --git a/core/frontend/src/test/render/primitives/VertexKey.test.ts b/core/frontend/src/test/render/primitives/VertexKey.test.ts index 56ee99c7ec01..c915807eae94 100644 --- a/core/frontend/src/test/render/primitives/VertexKey.test.ts +++ b/core/frontend/src/test/render/primitives/VertexKey.test.ts @@ -3,19 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { OctEncodedNormal, QPoint3d } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; +import { OctEncodedNormal } from "@itwin/core-common"; import { VertexKey } from "../../../render/primitives/VertexKey"; describe("VertexKey", () => { it("comparisons work as expected", () => { - const key123 = new VertexKey(QPoint3d.fromScalars(1, 2, 3), 456, new OctEncodedNormal(7)); - const copy123 = new VertexKey(QPoint3d.fromScalars(1, 2, 3), 456, new OctEncodedNormal(7)); - const key456 = new VertexKey(QPoint3d.fromScalars(4, 5, 6), 456, new OctEncodedNormal(7)); + const key123 = new VertexKey(new Point3d(1, 2, 3), 456, new OctEncodedNormal(7)); + const copy123 = new VertexKey(new Point3d(1, 2, 3), 456, new OctEncodedNormal(7)); + const key456 = new VertexKey(new Point3d(4, 5, 6), 456, new OctEncodedNormal(7)); - expect(key123.equals(copy123)).to.be.true; - expect(key123.equals(key456)).to.be.false; - expect(key123.compare(copy123)).to.equal(0); - expect(key123.compare(key456)).to.be.lessThan(0); - expect(key456.compare(key123)).to.be.greaterThan(0); + const tolerance = { x: 0, y: 0, z: 0 }; + expect(key123.equals(copy123, tolerance)).to.be.true; + expect(key123.equals(key456, tolerance)).to.be.false; + expect(key123.compare(copy123, tolerance)).to.equal(0); + expect(key123.compare(key456, tolerance)).to.be.lessThan(0); + expect(key456.compare(key123, tolerance)).to.be.greaterThan(0); }); }); diff --git a/core/frontend/src/test/render/primitives/VertexTable.test.ts b/core/frontend/src/test/render/primitives/VertexTable.test.ts index 88188d9027bb..cd972d7b36fb 100644 --- a/core/frontend/src/test/render/primitives/VertexTable.test.ts +++ b/core/frontend/src/test/render/primitives/VertexTable.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { Point2d } from "@itwin/core-geometry"; -import { ColorIndex, FeatureIndexType, QParams2d, QParams3d, QPoint3d, QPoint3dList, RenderTexture } from "@itwin/core-common"; +import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; +import { ColorIndex, FeatureIndex, FeatureIndexType, FillFlags, QParams2d, QParams3d, QPoint3d, QPoint3dList, RenderTexture } from "@itwin/core-common"; import { MockRender } from "../../../render/MockRender"; -import { MeshArgs } from "../../../render/primitives/mesh/MeshPrimitives"; +import { MeshArgs, Point3dList } from "../../../render/primitives/mesh/MeshPrimitives"; import { MeshParams } from "../../../render/primitives/VertexTable"; function expectMeshParams(args: MeshArgs, colorIndex: ColorIndex, vertexBytes: number[][], expectedColors?: number[], quvParams?: QParams2d) { @@ -51,7 +51,7 @@ describe("VertexLUT", () => { before(async () => MockRender.App.startup()); after(async () => MockRender.App.shutdown()); - it("should produce correct VertexLUT.Params from MeshArgs", () => { + it("should produce correct VertexLUT.Params from quantized MeshArgs", () => { // Make a mesh consisting of a single triangle. const positions = new QPoint3dList(QParams3d.fromZeroToOne()); positions.push(QPoint3d.fromScalars(0, 1, 2)); @@ -59,9 +59,13 @@ describe("VertexLUT", () => { positions.push(QPoint3d.fromScalars(0xbaad, 0, 0xffff)); // Test simple unlit vertices (no normals or uv params; uniform colors + features) - const args = new MeshArgs(); - args.points = positions; - args.vertIndices = [0, 1, 2]; + const args: MeshArgs = { + points: positions, + vertIndices: [0, 1, 2], + colors: new ColorIndex(), + features: new FeatureIndex(), + fillFlags: FillFlags.None, + }; const expected = [ [ @@ -84,11 +88,11 @@ describe("VertexLUT", () => { expectMeshParams(args, args.colors, expected); // Add uv params - args.texture = new FakeTexture(); - args.textureUv = []; - args.textureUv.push(new Point2d(-1, 1)); // 0, 0xffff - args.textureUv.push(new Point2d(1, 0)); // 0xffff, 0x8000 - args.textureUv.push(new Point2d(0, -1)); // 0x8000, 0 + args.textureMapping = { + texture: new FakeTexture(), + // quantized: (0, 0xffff), (0xffff, 0x8000), (0x8000, 0) + uvParams: [new Point2d(-1, 1), new Point2d(1, 0), new Point2d(0, -1)], + }; expected[0].push(0x00); expected[0].push(0x00); expected[0].push(0xff); expected[0].push(0xff); expected[1].push(0xff); expected[1].push(0xff); expected[1].push(0x00); expected[1].push(0x80); @@ -110,7 +114,7 @@ describe("VertexLUT", () => { expectMeshParams(args, args.colors, expected); // Remove uv params - args.texture = undefined; + args.textureMapping = undefined; for (const arr of expected) { arr.splice(12); } @@ -136,4 +140,96 @@ describe("VertexLUT", () => { expectMeshParams(args, args.colors, expected, expectedColors); }); + + it("should produce correct VertexLUT.Params from unquantized MeshArgs", () => { + // Make a mesh consisting of a single triangle + const positions = [ + new Point3d(0, 1, 2), + new Point3d(-1, 0, 1), + new Point3d(12.34, 99999.9, -98.76), + ] as Point3dList; + + positions.range = Range3d.createArray(positions); + const args: MeshArgs = { + points: positions, + vertIndices: [0, 1, 2], + colors: new ColorIndex(), + features: new FeatureIndex(), + fillFlags: FillFlags.None, + }; + + const makeExpected = () => [ + [ + 0x00, 0x00, 0x00, 0x00, // pos.x + 0x00, 0x00, 0x80, 0x3f, // pos.y + 0x00, 0x00, 0x00, 0x40, // pos.z + 0x00, 0x00, 0x00, 0x00, // feature index + 0x00, 0x00, 0x00, 0x00, // color index; unused + ], + [ + 0x00, 0x00, 0x80, 0xbf, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + [ + 0xa4, 0x70, 0x45, 0x41, + 0xf3, 0x4f, 0xc3, 0x47, + 0x1f, 0x85, 0xc5, 0xc2, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + ]; + + expectMeshParams(args, args.colors, makeExpected()); + + // Add uv params + args.textureMapping = { + texture: new FakeTexture(), + // quantized: (0, 0xffff), (0xffff, 0x8000), (0x8000, 0) + uvParams: [new Point2d(-1, 1), new Point2d(1, 0), new Point2d(0, -1)], + }; + + const exp = makeExpected(); + exp[0][16] = 0x00; exp[0][17] = 0x00; exp[0][18] = 0xff; exp[0][19] = 0xff; + exp[1][16] = 0xff; exp[1][17] = 0xff; exp[1][18] = 0x00; exp[1][19] = 0x80; + exp[2][16] = 0x00; exp[2][17] = 0x80; exp[2][18] = 0x00; exp[2][19] = 0x00; + + expectMeshParams(args, args.colors, exp, undefined, QParams2d.fromNormalizedRange()); + + // Add feature IDs + args.features.type = FeatureIndexType.NonUniform; + args.features.featureIDs = new Uint32Array(3); + args.features.featureIDs[0] = 0xbaadf00d; + args.features.featureIDs[1] = 0xc001bead; + args.features.featureIDs[2] = 0; + + exp[0][12] = 0x0d; exp[0][13] = 0xf0; exp[0][14] = 0xad; exp[0][15] = 0xba; + exp[1][12] = 0xad; exp[1][13] = 0xbe; exp[1][14] = 0x01; exp[1][15] = 0xc0; + + expectMeshParams(args, args.colors, exp); + + // Remove texture and add non-uniform color + args.textureMapping = undefined; + const colors = new Uint32Array(3); + colors[0] = 0xffeeddcc; + colors[1] = 0x00010203; + colors[2] = 0x7f00ff00; + const colorIndices = [0, 0x0001, 0xffee]; + args.colors.initNonUniform(colors, colorIndices, true); + + exp[0][18] = exp[0][19] = 0; + exp[1][16] = 0x01; exp[1][17] = 0x00; exp[1][18] = exp[1][19] = 0; + exp[2][16] = 0xee; exp[2][17] = 0xff; exp[2][18] = exp[2][19] = 0; + + // NB: The color values in VertexLUT.Params have premultiplied alpha, and alpha set to (255 - transparency) + const expectedColors = [ + 0x00, 0x00, 0x00, 0x00, + 0x03, 0x02, 0x01, 0xff, + 0x00, 0x80, 0x00, 0x80, + ]; + + expectMeshParams(args, args.colors, exp, expectedColors); + }); }); diff --git a/core/frontend/src/test/render/webgl/IndexedEdges.test.ts b/core/frontend/src/test/render/webgl/IndexedEdges.test.ts index f08bc0ce82de..28aea51dd8eb 100644 --- a/core/frontend/src/test/render/webgl/IndexedEdges.test.ts +++ b/core/frontend/src/test/render/webgl/IndexedEdges.test.ts @@ -5,9 +5,9 @@ import { expect } from "chai"; import { ByteStream } from "@itwin/core-bentley"; import { Point3d } from "@itwin/core-geometry"; -import { MeshEdge, OctEncodedNormal, OctEncodedNormalPair, PolylineData, QPoint3dList } from "@itwin/core-common"; +import { ColorIndex, FeatureIndex, FillFlags, MeshEdge, OctEncodedNormal, OctEncodedNormalPair, PolylineData, QPoint3dList } from "@itwin/core-common"; import { IModelApp } from "../../../IModelApp"; -import { MeshArgs } from "../../../render/primitives/mesh/MeshPrimitives"; +import { MeshArgs, MeshArgsEdges } from "../../../render/primitives/mesh/MeshPrimitives"; import { VertexIndices } from "../../../render/primitives/VertexTable"; import { EdgeParams, EdgeTable } from "../../../render/primitives/EdgeParams"; @@ -21,20 +21,22 @@ function makeNormalPair(n0: number, n1: number): OctEncodedNormalPair { * /__\/__\ * 0 2 4 */ -function createMeshArgs(opts?: { - is2d?: boolean; -}): MeshArgs { - const args = new MeshArgs(); - args.points = QPoint3dList.fromPoints([new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 0, 0), new Point3d(3, 1, 0), new Point3d(4, 0, 0)]); - args.vertIndices = [0, 1, 2, 2, 1, 3, 2, 3, 4]; - - args.edges.edges.edges = [new MeshEdge(0, 1), new MeshEdge(1, 3), new MeshEdge(3, 4)]; - args.edges.silhouettes.edges = [new MeshEdge(1, 2), new MeshEdge(2, 3)]; - args.edges.silhouettes.normals = [makeNormalPair(0, 0xffff), makeNormalPair(0x1234, 0xfedc)]; - args.edges.polylines.lines = [new PolylineData([0, 2, 4]), new PolylineData([2, 4, 3, 1]), new PolylineData([1, 0])]; - - args.is2d = true === opts?.is2d; - return args; +function createMeshArgs(opts?: { is2d?: boolean }): MeshArgs { + const edges = new MeshArgsEdges(); + edges.edges.edges = [new MeshEdge(0, 1), new MeshEdge(1, 3), new MeshEdge(3, 4)]; + edges.silhouettes.edges = [new MeshEdge(1, 2), new MeshEdge(2, 3)]; + edges.silhouettes.normals = [makeNormalPair(0, 0xffff), makeNormalPair(0x1234, 0xfedc)]; + edges.polylines.lines = [new PolylineData([0, 2, 4]), new PolylineData([2, 4, 3, 1]), new PolylineData([1, 0])]; + + return { + points: QPoint3dList.fromPoints([new Point3d(0, 0, 0), new Point3d(1, 1, 0), new Point3d(2, 0, 0), new Point3d(3, 1, 0), new Point3d(4, 0, 0)]), + vertIndices: [0, 1, 2, 2, 1, 3, 2, 3, 4], + edges, + fillFlags: FillFlags.None, + is2d: true === opts?.is2d, + colors: new ColorIndex(), + features: new FeatureIndex(), + }; } function expectIndices(indices: VertexIndices, expected: number[]): void { @@ -121,7 +123,7 @@ describe("IndexedEdgeParams", () => { it("are not produced if MeshArgs supplies no edges", () => { const args = createMeshArgs(); - args.edges.clear(); + args.edges?.clear(); expect(EdgeParams.fromMeshArgs(args)).to.be.undefined; }); @@ -138,7 +140,8 @@ describe("IndexedEdgeParams", () => { it("are not produced for polylines if width > 3", () => { const args = createMeshArgs(); - args.edges.width = 4; + expect(args.edges).not.to.be.undefined; + args.edges!.width = 4; const edges = EdgeParams.fromMeshArgs(args)!; expect(edges).not.to.be.undefined; @@ -214,18 +217,20 @@ describe("IndexedEdgeParams", () => { function makeEdgeTable(nSegs: number, nSils: number): EdgeTable { const meshargs = createMeshArgs(); - meshargs.edges.polylines.clear(); - meshargs.edges.silhouettes.clear(); + const edgs = meshargs.edges!; + expect(edgs).not.to.be.undefined; + edgs.polylines.clear(); + edgs.silhouettes.clear(); - meshargs.edges.edges.edges = []; + edgs.edges.edges = []; for (let i = 0; i < nSegs; i++) - meshargs.edges.edges.edges.push(new MeshEdge(0, 1)); + edgs.edges.edges.push(new MeshEdge(0, 1)); - meshargs.edges.silhouettes.edges = []; - meshargs.edges.silhouettes.normals = []; + edgs.silhouettes.edges = []; + edgs.silhouettes.normals = []; for (let i = 0; i < nSils; i++) { - meshargs.edges.silhouettes.edges.push(new MeshEdge(2 + i, 3)); - meshargs.edges.silhouettes.normals.push(makeNormalPair(4, 5)); + edgs.silhouettes.edges.push(new MeshEdge(2 + i, 3)); + edgs.silhouettes.normals.push(makeNormalPair(4, 5)); } const edgeParams = EdgeParams.fromMeshArgs(meshargs, 15)!; diff --git a/core/frontend/src/test/render/webgl/RenderMemory.test.ts b/core/frontend/src/test/render/webgl/RenderMemory.test.ts index 904d29e55d3a..c1a631257bcb 100644 --- a/core/frontend/src/test/render/webgl/RenderMemory.test.ts +++ b/core/frontend/src/test/render/webgl/RenderMemory.test.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; -import { ColorDef, ImageBuffer, ImageBufferFormat, MeshEdge, QParams3d, QPoint3dList, RenderTexture, TextureTransparency } from "@itwin/core-common"; +import { ColorDef, ColorIndex, FeatureIndex, FillFlags, ImageBuffer, ImageBufferFormat, MeshEdge, QParams3d, QPoint3dList, RenderTexture, TextureTransparency } from "@itwin/core-common"; import { IModelApp } from "../../../IModelApp"; import { IModelConnection } from "../../../IModelConnection"; import { RenderMemory } from "../../../render/RenderMemory"; import { RenderGeometry } from "../../../render/RenderSystem"; import { RenderGraphic } from "../../../render/RenderGraphic"; -import { MeshArgs } from "../../../render/primitives/mesh/MeshPrimitives"; +import { MeshArgs, MeshArgsEdges } from "../../../render/primitives/mesh/MeshPrimitives"; import { MeshParams } from "../../../render/primitives/VertexTable"; import { Texture } from "../../../render/webgl/Texture"; import { createBlankConnection } from "../../createBlankConnection"; @@ -23,28 +23,41 @@ function expectMemory(consumer: RenderMemory.Consumers, total: number, max: numb } function createMeshGeometry(opts?: { texture?: RenderTexture, includeEdges?: boolean }): RenderGeometry { - const args = new MeshArgs(); - args.colors.initUniform(ColorDef.from(255, 0, 0, 0)); + const colors = new ColorIndex(); + colors.initUniform(ColorDef.from(255, 0, 0)); + let textureMapping; if (opts?.texture) { - args.texture = opts.texture; - args.textureUv = [ new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ]; + textureMapping = { + texture: opts.texture, + uvParams: [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ], + }; } const points = [ new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0) ]; - args.points = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); + const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); for (const point of points) - args.points.add(point); - - args.vertIndices = [0, 1, 2, 2, 1, 3]; - args.isPlanar = true; + qpoints.add(point); + let edges; if (opts?.includeEdges) { - args.edges.edges.edges = []; + edges = new MeshArgsEdges(); + edges.edges.edges = []; for (const indexPair of [[0, 1], [1, 3], [3, 2], [2, 0]]) - args.edges.edges.edges.push(new MeshEdge(indexPair[0], indexPair[1])); + edges.edges.edges.push(new MeshEdge(indexPair[0], indexPair[1])); } + const args: MeshArgs = { + points: qpoints, + vertIndices: [0, 1, 2, 2, 1, 3], + isPlanar: true, + fillFlags: FillFlags.None, + edges, + features: new FeatureIndex(), + colors, + textureMapping, + }; + const params = MeshParams.create(args); const geom = IModelApp.renderSystem.createMeshGeometry(params); expect(geom).not.to.be.undefined; diff --git a/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts b/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts index b765deebe2ec..94c3707cde3f 100644 --- a/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts +++ b/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts @@ -5,7 +5,7 @@ import { expect } from "chai"; import { Point2d, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { - ColorDef, ImageBuffer, ImageBufferFormat, QParams3d, QPoint3dList, RenderMaterial, RenderMode, RenderTexture, TextureTransparency, + ColorDef, ColorIndex, FeatureIndex, FillFlags, ImageBuffer, ImageBufferFormat, QParams3d, QPoint3dList, RenderMaterial, RenderMode, RenderTexture, TextureMapping, TextureTransparency, } from "@itwin/core-common"; import { RenderGraphic } from "../../../render/RenderGraphic"; import { createRenderPlanFromViewport } from "../../../render/RenderPlan"; @@ -23,26 +23,33 @@ import { MeshParams } from "../../../render/primitives/VertexTable"; import { createBlankConnection } from "../../createBlankConnection"; function createMesh(transparency: number, mat?: RenderMaterial | RenderTexture): RenderGraphic { - const args = new MeshArgs(); - args.colors.initUniform(ColorDef.from(255, 0, 0, transparency)); + const colors = new ColorIndex(); + colors.initUniform(ColorDef.from(255, 0, 0, transparency)); + const points = [ new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0) ]; + const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); + for (const point of points) + qpoints.add(point); + + const args: MeshArgs = { + points: qpoints, + vertIndices: [0, 1, 2, 2, 1, 3], + isPlanar: true, + colors, + features: new FeatureIndex(), + fillFlags: FillFlags.None, + }; + + let texture; if (mat instanceof RenderMaterial) { args.material = mat; - args.texture = args.material.textureMapping?.texture; + texture = mat.textureMapping?.texture; } else { - args.texture = mat; + texture = mat; } - if (args.texture) - args.textureUv = [ new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ]; - - const points = [ new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0) ]; - args.points = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); - for (const point of points) - args.points.add(point); - - args.vertIndices = [0, 1, 2, 2, 1, 3]; - args.isPlanar = true; + if (texture) + args.textureMapping = { texture, uvParams: [ new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ] }; const params = MeshParams.create(args); return IModelApp.renderSystem.createMesh(params)!; @@ -101,7 +108,14 @@ describe("Surface transparency", () => { }); function createMaterial(alpha?: number, texture?: RenderTexture, textureWeight?: number): RenderMaterial { - const material = IModelApp.renderSystem.createRenderMaterial({ alpha, textureMapping: texture ? { texture, weight: textureWeight } : undefined }); + // eslint-disable-next-line deprecation/deprecation + const params = new RenderMaterial.Params(); + params.alpha = alpha; + if (texture) + params.textureMapping = new TextureMapping(texture, new TextureMapping.Params({ textureWeight })); + + // eslint-disable-next-line deprecation/deprecation + const material = IModelApp.renderSystem.createMaterial(params, imodel); expect(material).not.to.be.undefined; return material!; } diff --git a/core/frontend/src/tile/GltfReader.ts b/core/frontend/src/tile/GltfReader.ts index e5b4994c79d3..5b5e6dafaa9c 100644 --- a/core/frontend/src/tile/GltfReader.ts +++ b/core/frontend/src/tile/GltfReader.ts @@ -25,7 +25,7 @@ import { GraphicBranch } from "../render/GraphicBranch"; import { PickableGraphicOptions } from "../render/GraphicBuilder"; import { InstancedGraphicParams } from "../render/InstancedGraphicParams"; import { DisplayParams } from "../render/primitives/DisplayParams"; -import { Mesh, MeshGraphicArgs } from "../render/primitives/mesh/MeshPrimitives"; +import { Mesh } from "../render/primitives/mesh/MeshPrimitives"; import { RealityMeshPrimitive } from "../render/primitives/mesh/RealityMeshPrimitive"; import { Triangle } from "../render/primitives/Primitives"; import { RenderGraphic } from "../render/RenderGraphic"; @@ -1035,9 +1035,9 @@ export abstract class GltfReader { return { polyfaces }; } - private graphicFromMeshData(gltfMesh: GltfMeshData, meshGraphicArgs: MeshGraphicArgs, instances?: InstancedGraphicParams): RenderGraphic | undefined { + private graphicFromMeshData(gltfMesh: GltfMeshData, instances?: InstancedGraphicParams): RenderGraphic | undefined { if (!gltfMesh.points || !gltfMesh.pointRange) - return gltfMesh.primitive.getGraphics(meshGraphicArgs, this._system, instances); + return gltfMesh.primitive.getGraphics(this._system, instances); const realityMeshPrimitive = (this._vertexTableRequired || instances) ? undefined : RealityMeshPrimitive.createFromGltfMesh(gltfMesh); if (realityMeshPrimitive) { @@ -1048,6 +1048,7 @@ export abstract class GltfReader { const mesh = gltfMesh.primitive; const pointCount = gltfMesh.points.length / 3; + assert(mesh.points instanceof QPoint3dList); mesh.points.fromTypedArray(gltfMesh.pointRange, gltfMesh.points); if (mesh.triangles && gltfMesh.indices) mesh.triangles.addFromTypedArray(gltfMesh.indices); @@ -1062,7 +1063,7 @@ export abstract class GltfReader { for (const normal of gltfMesh.normals) mesh.normals.push(new OctEncodedNormal(normal)); - return mesh.getGraphics(meshGraphicArgs, this._system, instances); + return mesh.getGraphics(this._system, instances); } private readNodeAndCreateGraphics(renderGraphicList: RenderGraphic[], node: GltfNode, featureTable: FeatureTable | undefined, transformStack: TransformStack, instances?: InstancedGraphicParams, pseudoRtcBias?: Vector3d): TileReadStatus { @@ -1088,17 +1089,16 @@ export abstract class GltfReader { for (const meshKey of getNodeMeshIds(node)) { const nodeMesh = this._meshes[meshKey]; if (nodeMesh?.primitives) { - const meshGraphicArgs = new MeshGraphicArgs(); const meshes = this.readMeshPrimitives(node, featureTable, thisTransform, thisBias); let renderGraphic: RenderGraphic | undefined; if (0 !== meshes.length) { if (1 === meshes.length) { - renderGraphic = this.graphicFromMeshData(meshes[0], meshGraphicArgs, instances); + renderGraphic = this.graphicFromMeshData(meshes[0], instances); } else { const thisList: RenderGraphic[] = []; for (const mesh of meshes) { - renderGraphic = this.graphicFromMeshData(mesh, meshGraphicArgs, instances); + renderGraphic = this.graphicFromMeshData(mesh, instances); if (undefined !== renderGraphic) thisList.push(renderGraphic); } @@ -1427,6 +1427,7 @@ export abstract class GltfReader { isPlanar: false, hasBakedLighting, isVolumeClassifier, + quantizePositions: true, }); const mesh = new GltfMeshData(meshPrimitive); @@ -1544,6 +1545,7 @@ export abstract class GltfReader { posRange.extendXYZ(pos[i], pos[i + 1], pos[i + 2]); } + assert(mesh.points instanceof QPoint3dList); mesh.points.params.setFromRange(posRange); const pt = Point3d.createZero(); for (let i = 0; i < pos.length; i += 3) { diff --git a/core/frontend/src/tile/OPCFormatInterpreter.ts b/core/frontend/src/tile/OPCFormatInterpreter.ts index dbd8bac6d652..2e7bbd69f11f 100644 --- a/core/frontend/src/tile/OPCFormatInterpreter.ts +++ b/core/frontend/src/tile/OPCFormatInterpreter.ts @@ -5,9 +5,8 @@ import { Cartographic, EcefLocation } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; -import { ALong, CRSManager, Downloader, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, PointCloudReader, UrlFS } from "@itwin/core-orbitgt"; +import { ALong, CRSManager, Downloader, DownloaderXhr, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, PointCloudReader, UrlFS } from "@itwin/core-orbitgt"; import { FrontendLoggerCategory } from "../FrontendLoggerCategory"; -import { DownloaderNode } from "@itwin/core-orbitgt/lib/cjs/system/runtime/DownloaderNode"; import { BentleyError, Logger, LoggingMetaData, RealityDataStatus } from "@itwin/core-bentley"; import { RealityDataError, SpatialLocationAndExtents } from "../RealityDataSource"; @@ -25,7 +24,7 @@ export class OPCFormatInterpreter { */ public static async getFileReaderFromBlobFileURL(blobFileURL: string): Promise { if (Downloader.INSTANCE == null) - Downloader.INSTANCE = new DownloaderNode(); + Downloader.INSTANCE = new DownloaderXhr(); if (CRSManager.ENGINE == null) CRSManager.ENGINE = await OnlineEngine.create(); diff --git a/core/frontend/src/tile/TileTreeReference.ts b/core/frontend/src/tile/TileTreeReference.ts index 128701c0ad3f..0c8b4b3b94ee 100644 --- a/core/frontend/src/tile/TileTreeReference.ts +++ b/core/frontend/src/tile/TileTreeReference.ts @@ -16,7 +16,7 @@ import { RenderMemory } from "../render/RenderMemory"; import { DecorateContext, SceneContext } from "../ViewContext"; import { ScreenViewport } from "../Viewport"; import { - DisclosedTileTreeSet, GeometryTileTreeReference, TileDrawArgs, TileGeometryCollector, TileTree, TileTreeLoadStatus, TileTreeOwner, + DisclosedTileTreeSet, GeometryTileTreeReference, MapLayerFeatureInfo, TileDrawArgs, TileGeometryCollector, TileTree, TileTreeLoadStatus, TileTreeOwner, } from "./internal"; /** Describes the type of graphics produced by a [[TileTreeReference]]. @@ -70,6 +70,11 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { /** Optionally return a tooltip describing the hit. */ public async getToolTip(_hit: HitDetail): Promise { return undefined; } + /** Optionally return a MapLayerFeatureInfo object describing the hit.]. + * @alpha + */ + public async getMapFeatureInfo(_hit: HitDetail): Promise { return undefined; } + /** Optionally add any decorations specific to this reference. For example, map tile trees may add a logo image and/or copyright attributions. * @note This is currently only invoked for background maps and TiledGraphicsProviders - others have no decorations, but if they did implement this it would not be called. */ diff --git a/core/frontend/src/tile/internal.ts b/core/frontend/src/tile/internal.ts index 3f7adbd4d1b3..261ecad0f4ca 100644 --- a/core/frontend/src/tile/internal.ts +++ b/core/frontend/src/tile/internal.ts @@ -53,6 +53,7 @@ export * from "./map/ArcGISTileMap"; export * from "./map/MapLayerAuthentication"; export * from "./map/ArcGisTokenGenerator"; export * from "./map/ArcGisTokenManager"; +export * from "./map/MapFeatureInfo"; export * from "./map/MapLayerFormatRegistry"; export * from "./map/ArcGisUtilities"; export * from "./map/WmsUtilities"; diff --git a/core/frontend/src/tile/map/ArcGisUtilities.ts b/core/frontend/src/tile/map/ArcGisUtilities.ts index 2c2aab03a52b..26aa2698e93d 100644 --- a/core/frontend/src/tile/map/ArcGisUtilities.ts +++ b/core/frontend/src/tile/map/ArcGisUtilities.ts @@ -140,6 +140,19 @@ export class ArcGisUtilities { return { status: MapLayerSourceStatus.InvalidCredentials, authInfo: { authMethod: MapLayerAuthType.EsriToken } }; } + // Check this service support map queries + let hasMapCapability = false; + try { + if (json.capabilities + && typeof json.capabilities === "string" + && json.capabilities.toLowerCase().includes("map")) { + hasMapCapability = true; + } + } catch { } + if (!hasMapCapability) { + return { status: MapLayerSourceStatus.InvalidFormat}; + } + let subLayers; if (json.layers) { diff --git a/core/frontend/src/tile/map/BingElevation.ts b/core/frontend/src/tile/map/BingElevation.ts index e044171f1922..0e40f5fe2c16 100644 --- a/core/frontend/src/tile/map/BingElevation.ts +++ b/core/frontend/src/tile/map/BingElevation.ts @@ -6,18 +6,11 @@ /** @packageDocumentation * @module Tiles */ -import { BilinearPatch, Point2d, Point3d, Range1d, Range2d, Range3d } from "@itwin/core-geometry"; -import { Cartographic, ColorDef, FillFlags, LinePixels, QParams3d, QPoint3d, RenderTexture, TextureMapping } from "@itwin/core-common"; import { request, RequestOptions, Response } from "../../request/Request"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; -import { Mesh, MeshArgs } from "../../render/primitives/mesh/MeshPrimitives"; -import { DisplayParams } from "../../render/primitives/DisplayParams"; -import { Triangle } from "../../render/primitives/Primitives"; -import { VertexKey } from "../../render/primitives/VertexKey"; -import { MeshParams } from "../../render/primitives/VertexTable"; -import { RenderGraphic } from "../../render/RenderGraphic"; -import { RenderSystem } from "../../render/RenderSystem"; +import { Cartographic } from "@itwin/core-common"; +import { Point3d, Range1d, Range2d } from "@itwin/core-geometry"; // cspell:ignore atae qdng uyzv auje sealevel @@ -25,14 +18,6 @@ import { RenderSystem } from "../../render/RenderSystem"; * @public */ export class BingElevationProvider { - private static _scratchRange = Range3d.createNull(); - private static _scratchVertex = Point3d.createZero(); - private static _scratchQParams = QParams3d.fromRange(BingElevationProvider._scratchRange); - private static _scratchQPoint = QPoint3d.create(BingElevationProvider._scratchVertex, BingElevationProvider._scratchQParams); - private static _scratchMeshArgs = new MeshArgs(); - private static _scratchUV = Point2d.createZero(); - private static _scratchPoint = Point3d.createZero(); - private _heightRangeRequestTemplate: string; private _seaLevelOffsetRequestTemplate: string; private _heightListRequestTemplate: string; @@ -128,57 +113,4 @@ export class BingElevationProvider { for (const height of heights) total += height; return total / heights.length; } - /** @internal */ - public async getGraphic(latLongRange: Range2d, corners: Point3d[], groundBias: number, texture: RenderTexture, system: RenderSystem): Promise { - const heights = await this.getHeights(latLongRange); - if (undefined === heights) - return undefined; - - const patch = new BilinearPatch(corners[0], corners[1], corners[2], corners[3]); - const textureParams = new TextureMapping.Params({ mapMode: TextureMapping.Mode.Parametric }); - const textureMapping = new TextureMapping(texture, textureParams); - const displayParams = new DisplayParams(DisplayParams.Type.Mesh, ColorDef.white, ColorDef.white, 0.0, LinePixels.Solid, FillFlags.None, undefined, undefined, false, textureMapping); - BingElevationProvider._scratchRange.setNull(); - BingElevationProvider._scratchRange.extendArray(corners); - BingElevationProvider._scratchRange.low.z = 10E8; - BingElevationProvider._scratchRange.high.z = -1.0E8; - - for (const height of heights) { - BingElevationProvider._scratchRange.low.z = Math.min(BingElevationProvider._scratchRange.low.z, height); - BingElevationProvider._scratchRange.high.z = Math.max(BingElevationProvider._scratchRange.high.z, height); - } - - BingElevationProvider._scratchRange.low.z += groundBias; - BingElevationProvider._scratchRange.high.z += groundBias; - - BingElevationProvider._scratchQParams.setFromRange(BingElevationProvider._scratchRange); - const mesh = Mesh.create({ displayParams, type: Mesh.PrimitiveType.Mesh, range: BingElevationProvider._scratchRange, isPlanar: false, is2d: false }); - const size = 16; - const sizeM1 = size - 1; - const triangle0 = new Triangle(false), triangle1 = new Triangle(false); - for (let row = 0; row < sizeM1; row++) { - const thisRowIndex = row * size; - const nextRowIndex = thisRowIndex + size; - for (let col = 0; col < size - 1; col++) { - const q0 = thisRowIndex + col, q1 = q0 + 1, q3 = nextRowIndex + col, q2 = q3 + 1; - triangle0.setIndices(q0, q1, q2); - triangle1.setIndices(q0, q2, q3); - mesh.addTriangle(triangle0); - mesh.addTriangle(triangle1); - } - } - BingElevationProvider._scratchUV.y = 0.0; - const delta = 1.0 / sizeM1; - for (let row = 0; row < size; row++, BingElevationProvider._scratchUV.y += delta) { - BingElevationProvider._scratchUV.x = 0; - for (let col = 0; col < size; col++, BingElevationProvider._scratchUV.x += delta) { - patch.uvFractionToPoint(BingElevationProvider._scratchUV.x, BingElevationProvider._scratchUV.y, BingElevationProvider._scratchPoint); - BingElevationProvider._scratchPoint.z = groundBias + heights[(sizeM1 - row) * size + col]; - BingElevationProvider._scratchQPoint.init(BingElevationProvider._scratchPoint, BingElevationProvider._scratchQParams); - mesh.addVertex(VertexKey.create({ position: BingElevationProvider._scratchQPoint, fillColor: 0xffffff, uvParam: BingElevationProvider._scratchUV })); - } - } - BingElevationProvider._scratchMeshArgs.init(mesh); - return system.createMesh(MeshParams.create(BingElevationProvider._scratchMeshArgs)); - } } diff --git a/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts index 8de973441715..3ce61627b86a 100644 --- a/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts @@ -12,11 +12,11 @@ import { IModelApp } from "../../../IModelApp"; import { NotifyMessageDetails, OutputMessagePriority } from "../../../NotificationManager"; import { ArcGisErrorCode, ArcGISTileMap, ArcGisTokenClientType, ArcGisTokenManager, ArcGisUtilities, ImageryMapTile, ImageryMapTileTree, MapCartoRectangle, - MapLayerImageryProvider, MapLayerImageryProviderStatus, QuadId, + MapFeatureInfoRecord, + MapLayerFeatureInfo, + MapLayerImageryProvider, MapLayerImageryProviderStatus, MapSubLayerFeatureInfo, QuadId, } from "../../internal"; - -// eslint-disable-next-line prefer-const -let doToolTips = true; +import { PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; /** @internal */ export class ArcGISMapLayerImageryProvider extends MapLayerImageryProvider { @@ -181,24 +181,18 @@ export class ArcGISMapLayerImageryProvider extends MapLayerImageryProvider { return IModelApp.makeLogoCard({ heading: "ArcGIS", notice: this._copyrightText }); } - public override async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { - await super.getToolTip(strings, quadId, carto, tree); - if (!doToolTips) - return; - - if (!this._querySupported) - return; - - const stringSet = new Set(); + // Translates the provided Cartographic into a EPSG:3857 point, and retrieve information. + // tolerance is in pixels + private async getIdentifyData(quadId: QuadId, carto: Cartographic, tolerance: number): Promise { const bboxString = this.getEPSG3857ExtentString(quadId.row, quadId.column, quadId.level); const x = this.getEPSG3857X(carto.longitudeDegrees); const y = this.getEPSG3857Y(carto.latitudeDegrees); - const tmpUrl = `${this._settings.url}/identify?f=json&tolerance=1&returnGeometry=false&sr=3857&imageDisplay=${this.tileSize},${this.tileSize},96&layers=${this.getLayerString("visible")}&geometry=${x},${y}&geometryType=esriGeometryPoint&mapExtent=${bboxString}`; + const tmpUrl = `${this._settings.url}/identify?f=json&tolerance=${tolerance}&returnGeometry=false&sr=3857&imageDisplay=${this.tileSize},${this.tileSize},96&layers=${this.getLayerString("visible")}&geometry=${x},${y}&geometryType=esriGeometryPoint&mapExtent=${bboxString}`; const url = await this.appendSecurityToken(tmpUrl); let json = await getJson(url); if (json?.error?.code === ArcGisErrorCode.TokenRequired || json?.error?.code === ArcGisErrorCode.InvalidToken) { - // Token might have expired, make a second attempt by forcing new token. + // Token might have expired, make a second attempt by forcing new token. if (this._settings.userName && this._settings.userName.length > 0) { ArcGisTokenManager.invalidateToken(this._settings.url, this._settings.userName); json = await getJson(url); @@ -208,17 +202,30 @@ export class ArcGISMapLayerImageryProvider extends MapLayerImageryProvider { // have to provide credentials again. Change the layer status so we // don't make additional invalid requests.. if (json?.error?.code === ArcGisErrorCode.TokenRequired || json?.error?.code === ArcGisErrorCode.InvalidToken) { - // Check again layer status, it might have change during await. + // Check again layer status, it might have change during await. if (this.status === MapLayerImageryProviderStatus.Valid) { this.status = MapLayerImageryProviderStatus.RequireAuth; const msg = IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Messages.FetchTooltipTokenError", { layerName: this._settings.name }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Warning, msg)); } - return; + return undefined; } } + return json; + } + + // Makes an identify request to ESRI MapService server, and return it as a list of formatted strings + public override async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { + await super.getToolTip(strings, quadId, carto, tree); + + if (!this._querySupported) + return; + + const stringSet = new Set(); + const json = await this.getIdentifyData(quadId, carto, 1); + if (json && Array.isArray(json.results)) { for (const result of json.results) { if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) { @@ -231,6 +238,46 @@ export class ArcGISMapLayerImageryProvider extends MapLayerImageryProvider { } } } + + // Makes an identify request to ESRI MapService , and return it as a list MapLayerFeatureInfo object + public override async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree): Promise { + if (!this._querySupported) + return; + + const json = await this.getIdentifyData(quadId, carto,5 ); + if (json && Array.isArray(json.results)) { + const layerInfo: MapLayerFeatureInfo = {layerName: this._settings.name}; + + for (const result of json.results) { + + const subLayerInfo: MapSubLayerFeatureInfo = { + subLayerName: result.layerName ?? "", + displayFieldName: result.displayFieldName, + records : [], + }; + for (const [key, value] of Object.entries(result.attributes)) { + // Convert everything to string for now + const strValue = String(value); + subLayerInfo.records?.push(new MapFeatureInfoRecord ( + {valueFormat:PropertyValueFormat.Primitive, value:strValue, displayValue: strValue}, + {name: key, displayLabel: key, typename:StandardTypeNames.String} + )); + } + + if (layerInfo.info === undefined) { + layerInfo.info = []; + } + + if (!(layerInfo.info instanceof HTMLElement)) { + layerInfo.info.push(subLayerInfo); + } + + } + + featureInfos.push(layerInfo); + } + } + protected getLayerString(prefix = "show"): string { const layers = new Array(); this._settings.subLayers.forEach((subLayer) => { if (this._settings.isSubLayerVisible(subLayer)) layers.push(subLayer.idString); }); diff --git a/core/frontend/src/tile/map/ImageryTileTree.ts b/core/frontend/src/tile/map/ImageryTileTree.ts index 41be49884313..154547a25a97 100644 --- a/core/frontend/src/tile/map/ImageryTileTree.ts +++ b/core/frontend/src/tile/map/ImageryTileTree.ts @@ -1,298 +1,303 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Bentley Systems, Incorporated. All rights reserved. -* See LICENSE.md in the project root for license terms and full copyright notice. -*--------------------------------------------------------------------------------------------*/ -/** @packageDocumentation - * @module Tiles - */ - -import { assert, compareBooleans, compareNumbers, compareStrings, compareStringsOrUndefined, dispose } from "@itwin/core-bentley"; -import { Angle, Range3d, Transform } from "@itwin/core-geometry"; -import { Cartographic, ImageMapLayerSettings, ImageSource, MapLayerSettings, RenderTexture, ViewFlagOverrides } from "@itwin/core-common"; -import { IModelApp } from "../../IModelApp"; -import { IModelConnection } from "../../IModelConnection"; -import { RenderMemory } from "../../render/RenderMemory"; -import { RenderSystem } from "../../render/RenderSystem"; -import { ScreenViewport } from "../../Viewport"; -import { - MapCartoRectangle, MapLayerImageryProvider, MapLayerTileTreeReference, MapTile, MapTilingScheme, QuadId, RealityTile, RealityTileLoader, RealityTileTree, - RealityTileTreeParams, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileParams, TileRequest, TileTree, TileTreeLoadStatus, TileTreeOwner, - TileTreeSupplier, -} from "../internal"; - -/** @internal */ -export interface ImageryTileContent extends TileContent { - imageryTexture?: RenderTexture; -} - -/** @internal */ -export class ImageryMapTile extends RealityTile { - private _texture?: RenderTexture; - private _mapTileUsageCount = 0; - constructor(params: TileParams, public imageryTree: ImageryMapTileTree, public quadId: QuadId, public rectangle: MapCartoRectangle) { - super(params, imageryTree); - } - public get texture() { return this._texture; } - public get tilingScheme() { return this.imageryTree.tilingScheme; } - public override get isDisplayable() { return (this.depth > 1) && super.isDisplayable; } - - public override setContent(content: ImageryTileContent): void { - this._texture = content.imageryTexture; // No dispose - textures may be shared by terrain tiles so let garbage collector dispose them. - if (undefined === content.imageryTexture) - (this.parent! as ImageryMapTile).setLeaf(); // Avoid traversing bing branches after no graphics is found. - - this.setIsReady(); - } - - public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], rectangleToDrape: MapCartoRectangle, drapePixelSize: number, args: TileDrawArgs): TileTreeLoadStatus { - // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. - if (this.isLeaf || (this.rectangle.xLength() / this.maximumSize) < drapePixelSize || this._anyChildNotFound) { - if (this.isDisplayable && !this.isNotFound) - drapeTiles.push(this); - return TileTreeLoadStatus.Loaded; - } - - let status = this.loadChildren(); - if (TileTreeLoadStatus.Loading === status) { - args.markChildrenLoading(); - } else if (TileTreeLoadStatus.Loaded === status) { - if (undefined !== this.children) { - for (const child of this.children) { - const mapChild = child as ImageryMapTile; - if (mapChild.rectangle.intersectsRange(rectangleToDrape)) - status = mapChild.selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args); - if (TileTreeLoadStatus.Loaded !== status) - break; - } - } - } - return status; - } - public markMapTileUsage() { - this._mapTileUsageCount++; - } - public releaseMapTileUsage() { - assert(!this._texture || this._mapTileUsageCount > 0); - if (this._mapTileUsageCount) - this._mapTileUsageCount--; - } - - /** @internal */ - public override setLeaf(): void { - // Don't potentially re-request the children later. - this.disposeChildren(); - this._isLeaf = true; - this._childrenLoadStatus = TileTreeLoadStatus.Loaded; - } - - protected override _loadChildren(resolve: (children: Tile[] | undefined) => void, _reject: (error: Error) => void): void { - - const imageryTree = this.imageryTree; - const resolveChildren = (childIds: QuadId[]) => { - const children = new Array(); - const childrenAreLeaves = (this.depth + 1) === imageryTree.maxDepth; - // If children depth is lower than min LOD, mark them as disabled. - // This is important: if those tiles are requested and the server refuse to serve them, - // they will be marked as not found and their descendant will never be displayed. - const childrenAreDisabled = (this.depth + 1) < imageryTree.minDepth; - - childIds.forEach((quadId) => { - const rectangle = imageryTree.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); - const range = Range3d.createXYZXYZ(rectangle.low.x, rectangle.low.x, 0, rectangle.high.x, rectangle.high.y, 0); - const maximumSize = (childrenAreDisabled ? 0 : imageryTree.imageryLoader.maximumScreenSize); - children.push(new ImageryMapTile({ parent: this, isLeaf: childrenAreLeaves, contentId: quadId.contentId, range, maximumSize }, imageryTree, quadId, rectangle)); - }); - - resolve(children); - }; - - imageryTree.imageryLoader.generateChildIds(this, resolveChildren); - } - - protected override _collectStatistics(stats: RenderMemory.Statistics): void { - super._collectStatistics(stats); - if (this._texture) - stats.addTexture(this._texture.bytesUsed); - } - - public override freeMemory(): void { - // ###TODO MapTiles and ImageryMapTiles share resources and don't currently interact well with TileAdmin.freeMemory(). Opt out for now. - } - - public override disposeContents() { - if (0 === this._mapTileUsageCount) { - super.disposeContents(); - this.disposeTexture(); - } - } - - private disposeTexture(): void { - this._texture = dispose(this._texture); - } - public override dispose() { - this._mapTileUsageCount = 0; - super.dispose(); - } -} - -/** @internal */ -export class ImageryMapTileTree extends RealityTileTree { - constructor(params: RealityTileTreeParams, private _imageryLoader: ImageryTileLoader) { - super(params); - const rootQuadId = new QuadId(_imageryLoader.imageryProvider.tilingScheme.rootLevel, 0, 0); - this._rootTile = new ImageryMapTile(params.rootTile, this, rootQuadId, this.getTileRectangle(rootQuadId)); - } - public get tilingScheme(): MapTilingScheme { return this._imageryLoader.imageryProvider.tilingScheme; } - public getLogo(vp: ScreenViewport): HTMLTableRowElement | undefined { return this._imageryLoader.getLogo(vp); } - public getTileRectangle(quadId: QuadId): MapCartoRectangle { - return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); - } - public get imageryLoader(): ImageryTileLoader { return this._imageryLoader; } - public override get is3d(): boolean { assert(false); return false; } - public override get viewFlagOverrides(): ViewFlagOverrides { assert(false); return {}; } - public override get isContentUnbounded(): boolean { assert(false); return true; } - protected override _selectTiles(_args: TileDrawArgs): Tile[] { assert(false); return []; } - public override draw(_args: TileDrawArgs): void { assert(false); } - - private static _scratchDrapeRectangle = new MapCartoRectangle(); - private static _drapeIntersectionScale = 1.0 - 1.0E-5; - - public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], tileToDrape: MapTile, args: TileDrawArgs): TileTreeLoadStatus { - const drapeRectangle = tileToDrape.rectangle.clone(ImageryMapTileTree._scratchDrapeRectangle); - // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. - const drapePixelSize = 1.05 * tileToDrape.rectangle.xLength() / tileToDrape.maximumSize; - drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers. - return (this.rootTile as ImageryMapTile).selectCartoDrapeTiles(drapeTiles, drapeRectangle, drapePixelSize, args); - } - public cartoRectangleFromQuadId(quadId: QuadId): MapCartoRectangle { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); } -} - -class ImageryTileLoader extends RealityTileLoader { - constructor(private _imageryProvider: MapLayerImageryProvider, private _iModel: IModelConnection) { - super(); - } - public override computeTilePriority(tile: Tile): number { - return 25 * (this._imageryProvider.usesCachedTiles ? 2 : 1) - tile.depth; // Always cached first then descending by depth (high resolution/front first) - } // Prioritized fast, cached tiles first. - - public get maxDepth(): number { return this._imageryProvider.maximumZoomLevel; } - public get minDepth(): number { return this._imageryProvider.minimumZoomLevel; } - public get priority(): TileLoadPriority { return TileLoadPriority.Map; } - public getLogo(vp: ScreenViewport): HTMLTableRowElement | undefined { return this._imageryProvider.getLogo(vp); } - public get maximumScreenSize(): number { return this._imageryProvider.maximumScreenSize; } - public get imageryProvider(): MapLayerImageryProvider { return this._imageryProvider; } - public async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { await this._imageryProvider.getToolTip(strings, quadId, carto, tree); } - public generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void) { return this._imageryProvider.generateChildIds(tile, resolveChildren); } - - /** Load this tile's children, possibly asynchronously. Pass them to `resolve`, or an error to `reject`. */ - public async loadChildren(_tile: RealityTile): Promise { assert(false); return undefined; } - public async requestTileContent(tile: Tile, _isCanceled: () => boolean): Promise { - const quadId = QuadId.createFromContentId(tile.contentId); - return this._imageryProvider.loadTile(quadId.row, quadId.column, quadId.level); - } - - public getRequestChannel(_tile: Tile) { - // ###TODO use hostname from url - but so many layers to go through to get that... - return IModelApp.tileAdmin.channels.getForHttp("itwinjs-imagery"); - } - - public override async loadTileContent(tile: Tile, data: TileRequest.ResponseData, system: RenderSystem): Promise { - assert(data instanceof ImageSource); - assert(tile instanceof ImageryMapTile); - const content: ImageryTileContent = {}; - const texture = await this.loadTextureImage(data, system); - if (undefined === texture) - return content; - - content.imageryTexture = texture; - return content; - } - - private async loadTextureImage(source: ImageSource, system: RenderSystem): Promise { - try { - return await system.createTextureFromSource({ - type: RenderTexture.Type.FilteredTileSection, - source, - }); - } catch { - return undefined; - } - } -} - -interface ImageryMapLayerTreeId { - settings: ImageMapLayerSettings; -} - -/** Supplies a TileTree that can load and draw tiles based on our imagery provider. - * The TileTree is uniquely identified by its imagery type. - */ -class ImageryMapLayerTreeSupplier implements TileTreeSupplier { - /** Return a numeric value indicating how two tree IDs are ordered relative to one another. - * This allows the ID to serve as a lookup key to find the corresponding TileTree. - */ - public compareTileTreeIds(lhs: ImageryMapLayerTreeId, rhs: ImageryMapLayerTreeId): number { - let cmp = compareStrings(lhs.settings.url, rhs.settings.url); - if (0 === cmp) { - cmp = compareStringsOrUndefined(lhs.settings.userName, rhs.settings.userName); - if (0 === cmp) { - cmp = compareStringsOrUndefined(lhs.settings.password, rhs.settings.password); - if (0 === cmp) { - cmp = compareBooleans(lhs.settings.transparentBackground, rhs.settings.transparentBackground); - if (0 === cmp) { - cmp = compareNumbers(lhs.settings.subLayers.length, rhs.settings.subLayers.length); - if (0 === cmp) { - for (let i = 0; i < lhs.settings.subLayers.length && 0 === cmp; i++) - cmp = compareBooleans(lhs.settings.subLayers[i].visible, rhs.settings.subLayers[i].visible); - } - } - } - } - } - - return cmp; - } - - /** The first time a tree of a particular imagery type is requested, this function creates it. */ - public async createTileTree(id: ImageryMapLayerTreeId, iModel: IModelConnection): Promise { - const imageryProvider = IModelApp.mapLayerFormatRegistry.createImageryProvider(id.settings); - if (undefined === imageryProvider) - return undefined; - - await imageryProvider.initialize(); - const modelId = iModel.transientIds.next; - const tilingScheme = imageryProvider.tilingScheme; - const rootLevel = (1 === tilingScheme.numberOfLevelZeroTilesX && 1 === tilingScheme.numberOfLevelZeroTilesY) ? 0 : -1; - const rootTileId = new QuadId(rootLevel, 0, 0).contentId; - const rootRange = Range3d.createXYZXYZ(-Angle.piRadians, -Angle.piOver2Radians, 0, Angle.piRadians, Angle.piOver2Radians, 0); - const rootTileProps = { contentId: rootTileId, range: rootRange, maximumSize: 0 }; - const loader = new ImageryTileLoader(imageryProvider, iModel); - const treeProps = { rootTile: rootTileProps, id: modelId, modelId, iModel, location: Transform.createIdentity(), priority: TileLoadPriority.Map, loader, gcsConverterAvailable: false }; - return new ImageryMapTileTree(treeProps, loader); - } -} - -const imageryTreeSupplier = new ImageryMapLayerTreeSupplier(); - -/** A reference to one of our tile trees. The specific TileTree drawn may change when the desired imagery type or target iModel changes. - * @internal - */ -export class ImageryMapLayerTreeReference extends MapLayerTileTreeReference { - public constructor(layerSettings: MapLayerSettings, layerIndex: number, iModel: IModelConnection) { - super(layerSettings, layerIndex, iModel); - } - - public override get castsShadows() { return false; } - - /** Return the owner of the TileTree to draw. */ - public get treeOwner(): TileTreeOwner { - return this.iModel.tiles.getTileTreeOwner({ settings: this._layerSettings }, imageryTreeSupplier); - } - public override get imageryProvider(): MapLayerImageryProvider | undefined { - const tree = this.treeOwner.load(); - if (!tree || !(tree instanceof ImageryMapTileTree)) - return undefined; - - return tree.imageryLoader.imageryProvider; - } -} +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Tiles + */ + +import { assert, compareBooleans, compareNumbers, compareStrings, compareStringsOrUndefined, dispose } from "@itwin/core-bentley"; +import { Angle, Range3d, Transform } from "@itwin/core-geometry"; +import { Cartographic, ImageMapLayerSettings, ImageSource, MapLayerSettings, RenderTexture, ViewFlagOverrides } from "@itwin/core-common"; +import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; +import { RenderMemory } from "../../render/RenderMemory"; +import { RenderSystem } from "../../render/RenderSystem"; +import { ScreenViewport } from "../../Viewport"; +import { + MapCartoRectangle, MapLayerFeatureInfo, MapLayerImageryProvider, MapLayerTileTreeReference, MapTile, MapTilingScheme, QuadId, RealityTile, RealityTileLoader, RealityTileTree, + RealityTileTreeParams, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileParams, TileRequest, TileTree, TileTreeLoadStatus, TileTreeOwner, + TileTreeSupplier, +} from "../internal"; + +/** @internal */ +export interface ImageryTileContent extends TileContent { + imageryTexture?: RenderTexture; +} + +/** @internal */ +export class ImageryMapTile extends RealityTile { + private _texture?: RenderTexture; + private _mapTileUsageCount = 0; + constructor(params: TileParams, public imageryTree: ImageryMapTileTree, public quadId: QuadId, public rectangle: MapCartoRectangle) { + super(params, imageryTree); + } + public get texture() { return this._texture; } + public get tilingScheme() { return this.imageryTree.tilingScheme; } + public override get isDisplayable() { return (this.depth > 1) && super.isDisplayable; } + + public override setContent(content: ImageryTileContent): void { + this._texture = content.imageryTexture; // No dispose - textures may be shared by terrain tiles so let garbage collector dispose them. + if (undefined === content.imageryTexture) + (this.parent! as ImageryMapTile).setLeaf(); // Avoid traversing bing branches after no graphics is found. + + this.setIsReady(); + } + + public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], rectangleToDrape: MapCartoRectangle, drapePixelSize: number, args: TileDrawArgs): TileTreeLoadStatus { + // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. + if (this.isLeaf || (this.rectangle.xLength() / this.maximumSize) < drapePixelSize || this._anyChildNotFound) { + if (this.isDisplayable && !this.isNotFound) + drapeTiles.push(this); + return TileTreeLoadStatus.Loaded; + } + + let status = this.loadChildren(); + if (TileTreeLoadStatus.Loading === status) { + args.markChildrenLoading(); + } else if (TileTreeLoadStatus.Loaded === status) { + if (undefined !== this.children) { + for (const child of this.children) { + const mapChild = child as ImageryMapTile; + if (mapChild.rectangle.intersectsRange(rectangleToDrape)) + status = mapChild.selectCartoDrapeTiles(drapeTiles, rectangleToDrape, drapePixelSize, args); + if (TileTreeLoadStatus.Loaded !== status) + break; + } + } + } + return status; + } + public markMapTileUsage() { + this._mapTileUsageCount++; + } + public releaseMapTileUsage() { + assert(!this._texture || this._mapTileUsageCount > 0); + if (this._mapTileUsageCount) + this._mapTileUsageCount--; + } + + /** @internal */ + public override setLeaf(): void { + // Don't potentially re-request the children later. + this.disposeChildren(); + this._isLeaf = true; + this._childrenLoadStatus = TileTreeLoadStatus.Loaded; + } + + protected override _loadChildren(resolve: (children: Tile[] | undefined) => void, _reject: (error: Error) => void): void { + + const imageryTree = this.imageryTree; + const resolveChildren = (childIds: QuadId[]) => { + const children = new Array(); + const childrenAreLeaves = (this.depth + 1) === imageryTree.maxDepth; + // If children depth is lower than min LOD, mark them as disabled. + // This is important: if those tiles are requested and the server refuse to serve them, + // they will be marked as not found and their descendant will never be displayed. + const childrenAreDisabled = (this.depth + 1) < imageryTree.minDepth; + + childIds.forEach((quadId) => { + const rectangle = imageryTree.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); + const range = Range3d.createXYZXYZ(rectangle.low.x, rectangle.low.x, 0, rectangle.high.x, rectangle.high.y, 0); + const maximumSize = (childrenAreDisabled ? 0 : imageryTree.imageryLoader.maximumScreenSize); + children.push(new ImageryMapTile({ parent: this, isLeaf: childrenAreLeaves, contentId: quadId.contentId, range, maximumSize }, imageryTree, quadId, rectangle)); + }); + + resolve(children); + }; + + imageryTree.imageryLoader.generateChildIds(this, resolveChildren); + } + + protected override _collectStatistics(stats: RenderMemory.Statistics): void { + super._collectStatistics(stats); + if (this._texture) + stats.addTexture(this._texture.bytesUsed); + } + + public override freeMemory(): void { + // ###TODO MapTiles and ImageryMapTiles share resources and don't currently interact well with TileAdmin.freeMemory(). Opt out for now. + } + + public override disposeContents() { + if (0 === this._mapTileUsageCount) { + super.disposeContents(); + this.disposeTexture(); + } + } + + private disposeTexture(): void { + this._texture = dispose(this._texture); + } + public override dispose() { + this._mapTileUsageCount = 0; + super.dispose(); + } +} + +/** @internal */ +export class ImageryMapTileTree extends RealityTileTree { + constructor(params: RealityTileTreeParams, private _imageryLoader: ImageryTileLoader) { + super(params); + const rootQuadId = new QuadId(_imageryLoader.imageryProvider.tilingScheme.rootLevel, 0, 0); + this._rootTile = new ImageryMapTile(params.rootTile, this, rootQuadId, this.getTileRectangle(rootQuadId)); + } + public get tilingScheme(): MapTilingScheme { return this._imageryLoader.imageryProvider.tilingScheme; } + public getLogo(vp: ScreenViewport): HTMLTableRowElement | undefined { return this._imageryLoader.getLogo(vp); } + public getTileRectangle(quadId: QuadId): MapCartoRectangle { + return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); + } + public get imageryLoader(): ImageryTileLoader { return this._imageryLoader; } + public override get is3d(): boolean { assert(false); return false; } + public override get viewFlagOverrides(): ViewFlagOverrides { assert(false); return {}; } + public override get isContentUnbounded(): boolean { assert(false); return true; } + protected override _selectTiles(_args: TileDrawArgs): Tile[] { assert(false); return []; } + public override draw(_args: TileDrawArgs): void { assert(false); } + + private static _scratchDrapeRectangle = new MapCartoRectangle(); + private static _drapeIntersectionScale = 1.0 - 1.0E-5; + + public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], tileToDrape: MapTile, args: TileDrawArgs): TileTreeLoadStatus { + const drapeRectangle = tileToDrape.rectangle.clone(ImageryMapTileTree._scratchDrapeRectangle); + // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. + const drapePixelSize = 1.05 * tileToDrape.rectangle.xLength() / tileToDrape.maximumSize; + drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers. + return (this.rootTile as ImageryMapTile).selectCartoDrapeTiles(drapeTiles, drapeRectangle, drapePixelSize, args); + } + public cartoRectangleFromQuadId(quadId: QuadId): MapCartoRectangle { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); } +} + +class ImageryTileLoader extends RealityTileLoader { + constructor(private _imageryProvider: MapLayerImageryProvider, private _iModel: IModelConnection) { + super(); + } + public override computeTilePriority(tile: Tile): number { + return 25 * (this._imageryProvider.usesCachedTiles ? 2 : 1) - tile.depth; // Always cached first then descending by depth (high resolution/front first) + } // Prioritized fast, cached tiles first. + + public get maxDepth(): number { return this._imageryProvider.maximumZoomLevel; } + public get minDepth(): number { return this._imageryProvider.minimumZoomLevel; } + public get priority(): TileLoadPriority { return TileLoadPriority.Map; } + public getLogo(vp: ScreenViewport): HTMLTableRowElement | undefined { return this._imageryProvider.getLogo(vp); } + public get maximumScreenSize(): number { return this._imageryProvider.maximumScreenSize; } + public get imageryProvider(): MapLayerImageryProvider { return this._imageryProvider; } + public async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { await this._imageryProvider.getToolTip(strings, quadId, carto, tree); } + + public async getMapFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { + await this._imageryProvider.getFeatureInfo(featureInfos, quadId, carto, tree); + } + + public generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void) { return this._imageryProvider.generateChildIds(tile, resolveChildren); } + + /** Load this tile's children, possibly asynchronously. Pass them to `resolve`, or an error to `reject`. */ + public async loadChildren(_tile: RealityTile): Promise { assert(false); return undefined; } + public async requestTileContent(tile: Tile, _isCanceled: () => boolean): Promise { + const quadId = QuadId.createFromContentId(tile.contentId); + return this._imageryProvider.loadTile(quadId.row, quadId.column, quadId.level); + } + + public getRequestChannel(_tile: Tile) { + // ###TODO use hostname from url - but so many layers to go through to get that... + return IModelApp.tileAdmin.channels.getForHttp("itwinjs-imagery"); + } + + public override async loadTileContent(tile: Tile, data: TileRequest.ResponseData, system: RenderSystem): Promise { + assert(data instanceof ImageSource); + assert(tile instanceof ImageryMapTile); + const content: ImageryTileContent = {}; + const texture = await this.loadTextureImage(data, system); + if (undefined === texture) + return content; + + content.imageryTexture = texture; + return content; + } + + private async loadTextureImage(source: ImageSource, system: RenderSystem): Promise { + try { + return await system.createTextureFromSource({ + type: RenderTexture.Type.FilteredTileSection, + source, + }); + } catch { + return undefined; + } + } +} + +interface ImageryMapLayerTreeId { + settings: ImageMapLayerSettings; +} + +/** Supplies a TileTree that can load and draw tiles based on our imagery provider. + * The TileTree is uniquely identified by its imagery type. + */ +class ImageryMapLayerTreeSupplier implements TileTreeSupplier { + /** Return a numeric value indicating how two tree IDs are ordered relative to one another. + * This allows the ID to serve as a lookup key to find the corresponding TileTree. + */ + public compareTileTreeIds(lhs: ImageryMapLayerTreeId, rhs: ImageryMapLayerTreeId): number { + let cmp = compareStrings(lhs.settings.url, rhs.settings.url); + if (0 === cmp) { + cmp = compareStringsOrUndefined(lhs.settings.userName, rhs.settings.userName); + if (0 === cmp) { + cmp = compareStringsOrUndefined(lhs.settings.password, rhs.settings.password); + if (0 === cmp) { + cmp = compareBooleans(lhs.settings.transparentBackground, rhs.settings.transparentBackground); + if (0 === cmp) { + cmp = compareNumbers(lhs.settings.subLayers.length, rhs.settings.subLayers.length); + if (0 === cmp) { + for (let i = 0; i < lhs.settings.subLayers.length && 0 === cmp; i++) + cmp = compareBooleans(lhs.settings.subLayers[i].visible, rhs.settings.subLayers[i].visible); + } + } + } + } + } + + return cmp; + } + + /** The first time a tree of a particular imagery type is requested, this function creates it. */ + public async createTileTree(id: ImageryMapLayerTreeId, iModel: IModelConnection): Promise { + const imageryProvider = IModelApp.mapLayerFormatRegistry.createImageryProvider(id.settings); + if (undefined === imageryProvider) + return undefined; + + await imageryProvider.initialize(); + const modelId = iModel.transientIds.next; + const tilingScheme = imageryProvider.tilingScheme; + const rootLevel = (1 === tilingScheme.numberOfLevelZeroTilesX && 1 === tilingScheme.numberOfLevelZeroTilesY) ? 0 : -1; + const rootTileId = new QuadId(rootLevel, 0, 0).contentId; + const rootRange = Range3d.createXYZXYZ(-Angle.piRadians, -Angle.piOver2Radians, 0, Angle.piRadians, Angle.piOver2Radians, 0); + const rootTileProps = { contentId: rootTileId, range: rootRange, maximumSize: 0 }; + const loader = new ImageryTileLoader(imageryProvider, iModel); + const treeProps = { rootTile: rootTileProps, id: modelId, modelId, iModel, location: Transform.createIdentity(), priority: TileLoadPriority.Map, loader, gcsConverterAvailable: false }; + return new ImageryMapTileTree(treeProps, loader); + } +} + +const imageryTreeSupplier = new ImageryMapLayerTreeSupplier(); + +/** A reference to one of our tile trees. The specific TileTree drawn may change when the desired imagery type or target iModel changes. + * @internal + */ +export class ImageryMapLayerTreeReference extends MapLayerTileTreeReference { + public constructor(layerSettings: MapLayerSettings, layerIndex: number, iModel: IModelConnection) { + super(layerSettings, layerIndex, iModel); + } + + public override get castsShadows() { return false; } + + /** Return the owner of the TileTree to draw. */ + public get treeOwner(): TileTreeOwner { + return this.iModel.tiles.getTileTreeOwner({ settings: this._layerSettings }, imageryTreeSupplier); + } + public override get imageryProvider(): MapLayerImageryProvider | undefined { + const tree = this.treeOwner.load(); + if (!tree || !(tree instanceof ImageryMapTileTree)) + return undefined; + + return tree.imageryLoader.imageryProvider; + } +} diff --git a/core/frontend/src/tile/map/MapFeatureInfo.ts b/core/frontend/src/tile/map/MapFeatureInfo.ts new file mode 100644 index 000000000000..1453730cd247 --- /dev/null +++ b/core/frontend/src/tile/map/MapFeatureInfo.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module MapLayers + */ + +import { PropertyDescription, PropertyRecord, PropertyValue } from "@itwin/appui-abstract"; +import { Cartographic } from "@itwin/core-common"; +/** @alpha */ +export class MapFeatureInfoRecord extends PropertyRecord { + public constructor(value: PropertyValue, property: PropertyDescription) { + super(value, property); + } +} + +/** @alpha */ +export interface MapFeatureInfo { + layerInfo?: MapLayerFeatureInfo[]; + hitPoint?: Cartographic; +} + +/** @alpha */ +export interface MapLayerFeatureInfo { + layerName: string; + info?: MapSubLayerFeatureInfo[] | HTMLElement; +} + +/** @alpha */ +export interface MapSubLayerFeatureInfo { + subLayerName: string; + displayFieldName?: string; + records?: MapFeatureInfoRecord[]; +} diff --git a/core/frontend/src/tile/map/MapLayerImageryProvider.ts b/core/frontend/src/tile/map/MapLayerImageryProvider.ts index db68f8dd8004..0c82084bc232 100644 --- a/core/frontend/src/tile/map/MapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/MapLayerImageryProvider.ts @@ -12,7 +12,7 @@ import { IModelApp } from "../../IModelApp"; import { NotifyMessageDetails, OutputMessagePriority } from "../../NotificationManager"; import { getJson, request, RequestBasicCredentials, RequestOptions, Response } from "../../request/Request"; import { ScreenViewport } from "../../Viewport"; -import { GeographicTilingScheme, ImageryMapTile, ImageryMapTileTree, MapCartoRectangle, MapTilingScheme, QuadId, WebMercatorTilingScheme } from "../internal"; +import { GeographicTilingScheme, ImageryMapTile, ImageryMapTileTree, MapCartoRectangle, MapLayerFeatureInfo, MapTilingScheme, QuadId, WebMercatorTilingScheme } from "../internal"; const tileImageSize = 256, untiledImageSize = 256; @@ -85,6 +85,11 @@ export abstract class MapLayerImageryProvider { } } + public async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], _quadId: QuadId, _carto: Cartographic, _tree: ImageryMapTileTree): Promise { + // default implementation; simply return an empty feature info + featureInfos.push({layerName: this._settings.name}); + } + protected getRequestAuthorization(): RequestBasicCredentials | undefined { return (this._settings.userName && this._settings.password) ? { user: this._settings.userName, password: this._settings.password } : undefined; } diff --git a/core/frontend/src/tile/map/MapTileTree.ts b/core/frontend/src/tile/map/MapTileTree.ts index 312e36b8a39a..12fce23b85f1 100644 --- a/core/frontend/src/tile/map/MapTileTree.ts +++ b/core/frontend/src/tile/map/MapTileTree.ts @@ -1,883 +1,949 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Bentley Systems, Incorporated. All rights reserved. -* See LICENSE.md in the project root for license terms and full copyright notice. -*--------------------------------------------------------------------------------------------*/ -/** @packageDocumentation - * @module Tiles - */ - -import { assert, compareBooleans, compareBooleansOrUndefined, compareNumbers, compareStrings, compareStringsOrUndefined, CompressedId64Set, Id64String } from "@itwin/core-bentley"; -import { - BackgroundMapSettings, BaseLayerSettings, Cartographic, ColorDef, FeatureAppearance, GeoCoordStatus, GlobeMode, MapLayerSettings, PlanarClipMaskPriority, TerrainHeightOriginMode, - TerrainProviderName, -} from "@itwin/core-common"; -import { - Angle, AngleSweep, Constant, Ellipsoid, EllipsoidPatch, Point3d, Range1d, Range3d, Ray3d, Transform, Vector3d, XYZProps, -} from "@itwin/core-geometry"; -import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; -import { TerrainDisplayOverrides } from "../../DisplayStyleState"; -import { HitDetail } from "../../HitDetail"; -import { IModelConnection } from "../../IModelConnection"; -import { PlanarClipMaskState } from "../../PlanarClipMaskState"; -import { FeatureSymbology } from "../../render/FeatureSymbology"; -import { RenderPlanarClassifier } from "../../render/RenderPlanarClassifier"; -import { SceneContext } from "../../ViewContext"; -import { ScreenViewport } from "../../Viewport"; -import { - BingElevationProvider, - createDefaultViewFlagOverrides, createMapLayerTreeReference, DisclosedTileTreeSet, EllipsoidTerrainProvider, GeometryTileTreeReference, getCesiumTerrainProvider, GraphicsCollectorDrawArgs, - ImageryMapLayerTreeReference, - ImageryMapTileTree, - MapCartoRectangle, - MapLayerTileTreeReference, - MapTile, - MapTileLoader, - MapTilingScheme, - ModelMapLayerTileTreeReference, - PlanarTilePatch, - QuadId, - RealityTile, RealityTileDrawArgs, RealityTileTree, RealityTileTreeParams, Tile, TileDrawArgs, TileLoadPriority, TileParams, TileTree, TileTreeLoadStatus, TileTreeOwner, TileTreeReference, TileTreeSupplier, UpsampledMapTile, WebMercatorTilingScheme, -} from "../internal"; - -const scratchPoint = Point3d.create(); -const scratchCorners = [Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()]; -const scratchCorner = Point3d.createZero(); -const scratchZNormal = Vector3d.create(0, 0, 1); - -/** @internal */ -export class MapTileTree extends RealityTileTree { - private _mercatorFractionToDb: Transform; - public earthEllipsoid: Ellipsoid; - public minEarthEllipsoid: Ellipsoid; - public maxEarthEllipsoid: Ellipsoid; - public globeMode: GlobeMode; - public globeOrigin: Point3d; - private _mercatorTilingScheme: MapTilingScheme; - public useDepthBuffer: boolean; - public isOverlay: boolean; - public terrainExaggeration: number; - public baseColor?: ColorDef; - public baseTransparent: boolean; - public mapTransparent: boolean; - public produceGeometry?: boolean; - - constructor(params: RealityTileTreeParams, public ecefToDb: Transform, public bimElevationBias: number, public geodeticOffset: number, - public sourceTilingScheme: MapTilingScheme, id: MapTreeId, applyTerrain: boolean) { - super(params); - this._mercatorTilingScheme = new WebMercatorTilingScheme(); - this._mercatorFractionToDb = this._mercatorTilingScheme.computeMercatorFractionToDb(ecefToDb, bimElevationBias, params.iModel, applyTerrain); - const quadId = new QuadId(sourceTilingScheme.rootLevel, 0, 0); - this.globeOrigin = this.ecefToDb.getOrigin().clone(); - this.earthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.polar); - const globalHeightRange = applyTerrain ? ApproximateTerrainHeights.instance.globalHeightRange : Range1d.createXX(0, 0); - const globalRectangle = MapCartoRectangle.create(); - - this.globeMode = id.globeMode; - this.isOverlay = id.isOverlay; - this.useDepthBuffer = id.useDepthBuffer; - this.terrainExaggeration = id.terrainExaggeration; - this.baseColor = id.baseColor; - this.baseTransparent = id.baseTransparent; - this.mapTransparent = id.mapTransparent; - if (applyTerrain) { - this.minEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.polar + globalHeightRange.low); - this.maxEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.polar + globalHeightRange.high); - this.produceGeometry = id.produceGeometry; - } else { - this.minEarthEllipsoid = this.earthEllipsoid; - this.maxEarthEllipsoid = this.earthEllipsoid; - } - - const rootPatch = EllipsoidPatch.createCapture(this.maxEarthEllipsoid, AngleSweep.createStartSweepRadians(0, Angle.pi2Radians), AngleSweep.createStartSweepRadians(-Angle.piOver2Radians, Angle.piRadians)); - let range; - if (this.globeMode === GlobeMode.Ellipsoid) { - range = rootPatch.range(); - } else { - const corners = this.getFractionalTileCorners(quadId); - this._mercatorFractionToDb.multiplyPoint3dArrayInPlace(corners); - range = Range3d.createArray(MapTile.computeRangeCorners(corners, Vector3d.create(0, 0, 1), 0, scratchCorners, globalHeightRange)); - } - this._rootTile = this.createGlobeChild({ contentId: quadId.contentId, maximumSize: 0, range }, quadId, range.corners(), globalRectangle, rootPatch, undefined); - - } - - // If we are not depth buffering we force parents and exclusive to false to cause the map tiles to be sorted by depth so that painters algorithm will approximate correct depth display. - public override get parentsAndChildrenExclusive() { return this.useDepthBuffer ? this.loader.parentsAndChildrenExclusive : false; } - - public tileFromQuadId(quadId: QuadId): MapTile | undefined { - return (this._rootTile as MapTile).tileFromQuadId(quadId); - } - - public imageryTrees: ImageryMapTileTree[] = []; - private _layerSettings = new Map(); - private _modelIdToIndex = new Map(); - public layerClassifiers = new Map(); - - public addImageryLayer(tree: ImageryMapTileTree, settings: MapLayerSettings, index: number) { - this.imageryTrees.push(tree); - this._layerSettings.set(tree.modelId, settings); - this._modelIdToIndex.set(tree.modelId, index); - } - - public addModelLayer(layerTreeRef: ModelMapLayerTileTreeReference, context: SceneContext) { - const classifier = context.addPlanarClassifier(`MapLayer ${this.modelId}-${layerTreeRef.layerIndex}`, layerTreeRef); - if (classifier) - this.layerClassifiers.set(layerTreeRef.layerIndex, classifier); - } - - protected override collectClassifierGraphics(args: TileDrawArgs, selectedTiles: RealityTile[]) { - super.collectClassifierGraphics(args, selectedTiles); - - this.layerClassifiers.forEach((layerClassifier: RenderPlanarClassifier) => { - if (!(args instanceof GraphicsCollectorDrawArgs)) - layerClassifier.collectGraphics(args.context, { modelId: this.modelId, tiles: selectedTiles, location: args.location, isPointCloud: this.isPointCloud }); - - }); - } - - public clearImageryTreesAndClassifiers() { - this.imageryTrees.length = 0; - this._layerSettings.clear(); - this._modelIdToIndex.clear(); - this.layerClassifiers.clear(); - } - - public override get isTransparent() { - return this.mapTransparent || this.baseTransparent; - } - - public override get maxDepth() { - let maxDepth = this.loader.maxDepth; - this.imageryTrees?.forEach((imageryTree) => maxDepth = Math.max(maxDepth, imageryTree.maxDepth)); - - return maxDepth; - } - public createPlanarChild(params: TileParams, quadId: QuadId, corners: Point3d[], normal: Vector3d, rectangle: MapCartoRectangle, chordHeight: number, heightRange?: Range1d): MapTile | undefined{ - const childAvailable = this.mapLoader.isTileAvailable(quadId); - if (!childAvailable && this.produceGeometry) - return undefined; - const patch = new PlanarTilePatch(corners, normal, chordHeight); - const cornerNormals = this.getCornerRays(rectangle); - const ctor = childAvailable ? MapTile : UpsampledMapTile; - return new ctor(params, this, quadId, patch, rectangle, heightRange, cornerNormals); - } - - public createGlobeChild(params: TileParams, quadId: QuadId, _rangeCorners: Point3d[], rectangle: MapCartoRectangle, ellipsoidPatch: EllipsoidPatch, heightRange?: Range1d): MapTile { - return new MapTile(params, this, quadId, ellipsoidPatch, rectangle, heightRange, this.getCornerRays(rectangle)); - } - - public getChildHeightRange(quadId: QuadId, rectangle: MapCartoRectangle, parent: MapTile): Range1d | undefined { - return this.mapLoader.getChildHeightRange(quadId, rectangle, parent); - } - - public clearLayers() { - (this._rootTile as MapTile).clearLayers(); - } - - public static minReprojectionDepth = 8; // Reprojection does not work with very large tiles so just do linear transform. - public static maxGlobeDisplayDepth = 8; - public static minDisplayableDepth = 3; - public get mapLoader() { return this.loader as MapTileLoader; } - public override getBaseRealityDepth(sceneContext: SceneContext) { - // If the view has ever had global scope then preload low level (global) tiles. - return (sceneContext.viewport.view.maxGlobalScopeFactor > 1) ? MapTileTree.minDisplayableDepth : -1; - } - - public doCreateGlobeChildren(tile: Tile): boolean { - if (this.globeMode !== GlobeMode.Ellipsoid) - return false; - - const childDepth = tile.depth + 1; - if (childDepth < MapTileTree.maxGlobeDisplayDepth) // If the depth is too low (tile is too large) display as globe. - return true; - - return false; // Display as globe if more than 100 KM from project. - } - public override doReprojectChildren(tile: Tile): boolean { - if (this._gcsConverter === undefined) - return false; - - const childDepth = tile.depth + 1; - if (childDepth < MapTileTree.minReprojectionDepth) // If the depth is too low (tile is too large) omit reprojection. - return false; - - return this.cartesianRange.intersectsRange(tile.range); - } - - public getCornerRays(rectangle: MapCartoRectangle): Ray3d[] | undefined { - const rays = new Array(); - if (this.globeMode === GlobeMode.Ellipsoid) { - rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.low.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.high.y))!); - rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.high.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.high.y))!); - rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.low.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.low.y))!); - rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.high.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.low.y))!); - } else { - const mercatorFractionRange = rectangle.getTileFractionRange(this._mercatorTilingScheme); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.high.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.high.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.low.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.low.y), scratchZNormal)); - } - return rays; - } - public pointAboveEllipsoid(point: Point3d): boolean { - return this.earthEllipsoid.worldToLocal(point, scratchPoint)!.magnitude() > 1; - } - - private getMercatorFractionChildGridPoints(tile: MapTile, columnCount: number, rowCount: number): Point3d[] { - const gridPoints = []; - const quadId = tile.quadId; - const deltaX = 1.0 / columnCount, deltaY = 1.0 / rowCount; - for (let row = 0; row <= rowCount; row++) { - for (let column = 0; column <= columnCount; column++) { - const xFraction = this.sourceTilingScheme.tileXToFraction(quadId.column + column * deltaX, quadId.level); - const yFraction = this.sourceTilingScheme.tileYToFraction(quadId.row + row * deltaY, quadId.level); - - gridPoints.push(Point3d.create(xFraction, yFraction, 0)); - } - } - // If not mercator already need to remap latitude... - if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) - for (const gridPoint of gridPoints) - gridPoint.y = this._mercatorTilingScheme.latitudeToYFraction(this.sourceTilingScheme.yFractionToLatitude(gridPoint.y)); - - return gridPoints; - } - - private getChildCornersFromGridPoints(gridPoints: Point3d[], columnCount: number, rowCount: number) { - const childCorners = new Array(); - for (let row = 0; row < rowCount; row++) { - for (let column = 0; column < columnCount; column++) { - const index0 = column + row * (columnCount + 1); - const index1 = index0 + (columnCount + 1); - childCorners.push([gridPoints[index0], gridPoints[index0 + 1], gridPoints[index1], gridPoints[index1 + 1]]); - } - } - return childCorners; - } - - public getCachedReprojectedPoints(gridPoints: Point3d[]): (Point3d | undefined)[] | undefined { - const requestProps = []; - for (const gridPoint of gridPoints) - requestProps.push({ - x: this._mercatorTilingScheme.xFractionToLongitude(gridPoint.x) * Angle.degreesPerRadian, - y: this._mercatorTilingScheme.yFractionToLatitude(gridPoint.y) * Angle.degreesPerRadian, - z: this.bimElevationBias, - }); - - const iModelCoordinates = this._gcsConverter!.getCachedIModelCoordinatesFromGeoCoordinates(requestProps); - - if (iModelCoordinates.missing) - return undefined; - - return iModelCoordinates.result.map((result) => !result || result.s ? undefined : Point3d.fromJSON(result.p)); - } - - // Minimize reprojection requests by requesting this corners tile and a grid that will include all points for 4 levels of descendants. - // This greatly reduces the number of reprojection requests which currently require a roundtrip through the backend. - public async loadReprojectionCache(tile: MapTile): Promise { - const quadId = tile.quadId; - const xRange = Range1d.createXX(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level)); - const yRange = Range1d.createXX(this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level)); - const cacheDepth = 4, cacheDimension = 2 ** cacheDepth; - const delta = 1.0 / cacheDimension; - const requestProps = []; - - for (let row = 0; row <= cacheDimension; row++) { - for (let column = 0; column <= cacheDimension; column++) { - let yFraction = yRange.fractionToPoint(row * delta); - if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) - yFraction = this._mercatorTilingScheme.latitudeToYFraction(this.sourceTilingScheme.yFractionToLatitude(yFraction)); - requestProps.push({ - x: this._mercatorTilingScheme.xFractionToLongitude(xRange.fractionToPoint(column * delta)) * Angle.degreesPerRadian, - y: this._mercatorTilingScheme.yFractionToLatitude(yFraction) * Angle.degreesPerRadian, - z: this.bimElevationBias, - }); - } - } - - await this._gcsConverter!.getIModelCoordinatesFromGeoCoordinates(requestProps); - } - - private static _scratchCarto = Cartographic.createZero(); - - // Get the corners for planar children -- This generally will resolve immediately, but may require an asynchronous request for reprojecting the corners. - public getPlanarChildCorners(tile: MapTile, columnCount: number, rowCount: number, resolve: (childCorners: Point3d[][]) => void) { - const resolveCorners = (points: Point3d[], reprojected: (Point3d | undefined)[] | undefined = undefined) => { - for (let i = 0; i < points.length; i++) { - const gridPoint = points[i]; - this._mercatorFractionToDb.multiplyPoint3d(gridPoint, scratchCorner); - if (this.globeMode !== GlobeMode.Ellipsoid || this.cartesianRange.containsPoint(scratchCorner)) { - if (reprojected !== undefined && reprojected[i] !== undefined) - reprojected[i]!.clone(gridPoint); - else - scratchCorner.clone(gridPoint); - } else { - this._mercatorTilingScheme.fractionToCartographic(gridPoint.x, gridPoint.y, MapTileTree._scratchCarto); - this.earthEllipsoid.radiansToPoint(MapTileTree._scratchCarto.longitude, Cartographic.parametricLatitudeFromGeodeticLatitude(MapTileTree._scratchCarto.latitude), gridPoint); - const cartesianDistance = this.cartesianRange.distanceToPoint(scratchCorner); - if (cartesianDistance < this.cartesianTransitionDistance) - scratchCorner.interpolate(cartesianDistance / this.cartesianTransitionDistance, gridPoint, gridPoint); - } - } - resolve(this.getChildCornersFromGridPoints(points, columnCount, rowCount)); - }; - - let reprojectedPoints: (Point3d | undefined)[] | undefined; - const gridPoints = this.getMercatorFractionChildGridPoints(tile, columnCount, rowCount); - if (this.doReprojectChildren(tile)) { - reprojectedPoints = this.getCachedReprojectedPoints(gridPoints); - if (reprojectedPoints) { - // If the reprojected corners are in the cache, resolve immediately. - resolveCorners(gridPoints, reprojectedPoints); - } else { - // If the reprojected corners are not in cache request them - but also request reprojection of a grid that will include descendent corners to ensure they can - // be reloaded without expensive reprojection requests. - this.loadReprojectionCache(tile).then(() => { - const reprojected = this.getCachedReprojectedPoints(gridPoints); - assert(reprojected !== undefined); // We just cached them... they better be there now. - resolveCorners(gridPoints, reprojected); - }).catch((_error: Error) => { - resolveCorners(gridPoints); - }); - } - } else { - resolveCorners(gridPoints); - } - } - - public getFractionalTileCorners(quadId: QuadId): Point3d[] { - const corners: Point3d[] = []; - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); - return corners; - } - - public getTileRectangle(quadId: QuadId): MapCartoRectangle { - return this.sourceTilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); - } - public getLayerIndex(imageryTreeId: Id64String) { - const index = this._modelIdToIndex.get(imageryTreeId); - return index === undefined ? -1 : index; - } - - public getLayerTransparency(imageryTreeId: Id64String): number { - const layerSettings = this._layerSettings.get(imageryTreeId); - assert(undefined !== layerSettings); - return undefined === layerSettings || !layerSettings.transparency ? 0.0 : layerSettings.transparency; - } -} - -interface MapTreeId { - tileUserId: number; - applyTerrain: boolean; - terrainProviderName: TerrainProviderName; - terrainHeightOrigin: number; - terrainHeightOriginMode: number; - terrainExaggeration: number; - mapGroundBias: number; - wantSkirts: boolean; - wantNormals: boolean; - globeMode: GlobeMode; - useDepthBuffer: boolean; - isOverlay: boolean; - baseColor?: ColorDef; - baseTransparent: boolean; - mapTransparent: boolean; - maskModelIds?: string; - produceGeometry?: boolean; -} - -/** @internal */ -class MapTileTreeProps implements RealityTileTreeParams { - public id: string; - public modelId: string; - public location = Transform.createIdentity(); - public yAxisUp = true; - public is3d = true; - public rootTile = { contentId: "", range: Range3d.createNull(), maximumSize: 0 }; - public loader: MapTileLoader; - public iModel: IModelConnection; - public get priority(): TileLoadPriority { return this.loader.priority; } - - public constructor(modelId: Id64String, loader: MapTileLoader, iModel: IModelConnection, public gcsConverterAvailable: boolean) { - this.id = this.modelId = modelId; - this.loader = loader; - this.iModel = iModel; - } -} - -function createViewFlagOverrides(wantLighting: boolean, wantThematic: false | undefined) { - return createDefaultViewFlagOverrides({ clipVolume: false, lighting: wantLighting, thematic: wantThematic }); -} - -class MapTreeSupplier implements TileTreeSupplier { - public readonly isEcefDependent = true; - - public compareTileTreeIds(lhs: MapTreeId, rhs: MapTreeId): number { - let cmp = compareNumbers(lhs.tileUserId, rhs.tileUserId); - if (0 === cmp) { - cmp = compareStringsOrUndefined(lhs.maskModelIds, rhs.maskModelIds); - if (0 === cmp) { - cmp = compareBooleans(lhs.isOverlay, rhs.isOverlay); - if (0 === cmp && !lhs.isOverlay) { - cmp = compareBooleans(lhs.wantSkirts, rhs.wantSkirts); - if (0 === cmp) { - cmp = compareBooleans(lhs.wantNormals, rhs.wantNormals); - if (0 === cmp) { - cmp = compareNumbers(lhs.globeMode, rhs.globeMode); - if (0 === cmp) { - cmp = compareNumbers(lhs.baseColor ? lhs.baseColor.tbgr : -1, rhs.baseColor ? rhs.baseColor.tbgr : -1); - if (0 === cmp) { - cmp = compareBooleans(lhs.baseTransparent, rhs.baseTransparent); - if (0 === cmp) { - cmp = compareBooleans(lhs.mapTransparent, rhs.mapTransparent); - if (0 === cmp) { - cmp = compareBooleans(lhs.applyTerrain, rhs.applyTerrain); - if (0 === cmp) { - if (lhs.applyTerrain) { - // Terrain-only settings. - cmp = compareStrings(lhs.terrainProviderName, rhs.terrainProviderName); - if (0 === cmp) { - cmp = compareNumbers(lhs.terrainHeightOrigin, rhs.terrainHeightOrigin); - if (0 === cmp) { - cmp = compareNumbers(lhs.terrainHeightOriginMode, rhs.terrainHeightOriginMode); - if (0 === cmp) { - cmp = compareNumbers(lhs.terrainExaggeration, rhs.terrainExaggeration); - if (0 === cmp) - cmp = compareBooleansOrUndefined(lhs.produceGeometry, rhs.produceGeometry); - } - } - } - } else { - // Non-Terrain (flat) settings. - cmp = compareNumbers(lhs.mapGroundBias, rhs.mapGroundBias); - if (0 === cmp) - cmp = compareBooleans(lhs.useDepthBuffer, rhs.useDepthBuffer); - } - } - } - } - } - } - } - } - } - } - } - - return cmp; - } - - private async computeHeightBias(heightOrigin: number, heightOriginMode: TerrainHeightOriginMode, exaggeration: number, iModel: IModelConnection, elevationProvider: BingElevationProvider): Promise { - const projectCenter = iModel.projectExtents.center; - switch (heightOriginMode) { - case TerrainHeightOriginMode.Ground: - return heightOrigin + exaggeration * (await elevationProvider.getHeightValue(projectCenter, iModel, true)); - - case TerrainHeightOriginMode.Geodetic: - return heightOrigin; - - case TerrainHeightOriginMode.Geoid: - return heightOrigin + await elevationProvider.getGeodeticToSeaLevelOffset(projectCenter, iModel); - } - } - - public async createTileTree(id: MapTreeId, iModel: IModelConnection): Promise { - let bimElevationBias = 0, terrainProvider, geodeticOffset = 0; - let applyTerrain = id.applyTerrain; - const modelId = iModel.transientIds.next; - const gcsConverterAvailable = await getGcsConverterAvailable(iModel); - - if (id.applyTerrain) { - assert(id.terrainProviderName === "CesiumWorldTerrain"); - await ApproximateTerrainHeights.instance.initialize(); - const elevationProvider = new BingElevationProvider(); - - bimElevationBias = - await this.computeHeightBias(id.terrainHeightOrigin, id.terrainHeightOriginMode, id.terrainExaggeration, iModel, elevationProvider); - geodeticOffset = await elevationProvider.getGeodeticToSeaLevelOffset(iModel.projectExtents.center, iModel); - terrainProvider = await getCesiumTerrainProvider(iModel, modelId, id.wantSkirts, id.wantNormals, id.terrainExaggeration); - - if (!terrainProvider) { - applyTerrain = false; - geodeticOffset = 0; - } - } - - if (!terrainProvider) { - terrainProvider = new EllipsoidTerrainProvider(iModel, modelId, id.wantSkirts); - bimElevationBias = id.mapGroundBias; - } - - const loader = new MapTileLoader(iModel, modelId, bimElevationBias, terrainProvider); - const ecefToDb = iModel.getMapEcefToDb(bimElevationBias); - - if (id.maskModelIds) - await iModel.models.load(CompressedId64Set.decompressSet(id.maskModelIds)); - - const treeProps = new MapTileTreeProps(modelId, loader, iModel, gcsConverterAvailable); - return new MapTileTree(treeProps, ecefToDb, bimElevationBias, geodeticOffset, terrainProvider.tilingScheme, id, applyTerrain); - } -} - -const mapTreeSupplier = new MapTreeSupplier(); - -/** @internal */ -type CheckTerrainDisplayOverride = () => TerrainDisplayOverrides | undefined; - -/** Specialization of tile tree that represents background map. - * @internal - */ -export class MapTileTreeReference extends TileTreeReference { - private _tileUserId: number; - private _settings: BackgroundMapSettings; - private readonly _iModel: IModelConnection; - private _baseImageryLayerIncluded = false; - private _baseColor?: ColorDef; - private readonly _layerTrees = new Array(); - private _baseTransparent = false; - private _symbologyOverrides: FeatureSymbology.Overrides | undefined; - private _planarClipMask?: PlanarClipMaskState; - - public constructor(settings: BackgroundMapSettings, private _baseLayerSettings: BaseLayerSettings | undefined, private _layerSettings: MapLayerSettings[], iModel: IModelConnection, tileUserId: number, public isOverlay: boolean, private _isDrape: boolean, private _overrideTerrainDisplay?: CheckTerrainDisplayOverride) { - super(); - this._tileUserId = tileUserId; - this._settings = settings; - this._iModel = iModel; - let tree; - if (!isOverlay && this._baseLayerSettings !== undefined) { - if (this._baseLayerSettings instanceof MapLayerSettings) { - tree = createMapLayerTreeReference(this._baseLayerSettings, 0, iModel); - this._baseTransparent = this._baseLayerSettings.transparency > 0; - } else { - this._baseColor = this._baseLayerSettings; - this._baseTransparent = this._baseColor?.getTransparency() > 0; - } - } - - if (this._baseImageryLayerIncluded = (undefined !== tree)) - this._layerTrees.push(tree); - - for (let i = 0; i < this._layerSettings.length; i++) - if (undefined !== (tree = createMapLayerTreeReference(this._layerSettings[i], i + 1, iModel))) - this._layerTrees.push(tree); - - if (this._settings.planarClipMask && this._settings.planarClipMask.isValid) - this._planarClipMask = PlanarClipMaskState.create(this._settings.planarClipMask); - - if (this._overrideTerrainDisplay && this._overrideTerrainDisplay()?.produceGeometry) - this.collectTileGeometry = (collector) => this._collectTileGeometry(collector); - } - - public override get isGlobal() { return true; } - public get baseColor(): ColorDef | undefined { return this._baseColor; } - public override get planarclipMaskPriority(): number { return PlanarClipMaskPriority.BackgroundMap; } - - protected override _createGeometryTreeReference(): GeometryTileTreeReference | undefined { - if (! this._settings.applyTerrain || this._isDrape) - return undefined; // Don't bother generating non-terrain (flat) geometry. - - const ref = new MapTileTreeReference(this._settings, undefined, [], this._iModel, this._tileUserId, false, false, () => { return { produceGeometry: true }; }); - assert(undefined !== ref.collectTileGeometry); - return ref as GeometryTileTreeReference; - } - - /** Terrain tiles do not contribute to the range used by "fit view". */ - public override unionFitRange(_range: Range3d): void { } - public get settings(): BackgroundMapSettings { return this._settings; } - public set settings(settings: BackgroundMapSettings) { - this._settings = settings; - this._planarClipMask = settings.planarClipMask ? PlanarClipMaskState.create(settings.planarClipMask) : undefined; - } - public setBaseLayerSettings(baseLayerSettings: BaseLayerSettings) { - assert(!this.isOverlay); - let tree; - this._baseLayerSettings = baseLayerSettings; - - if (baseLayerSettings instanceof MapLayerSettings) { - tree = createMapLayerTreeReference(baseLayerSettings, 0, this._iModel); - this._baseColor = undefined; - this._baseTransparent = baseLayerSettings.transparency > 0; - } else { - this._baseColor = baseLayerSettings; - this._baseTransparent = this._baseColor.getTransparency() > 0; - } - - if (tree) { - if (this._baseImageryLayerIncluded) - this._layerTrees[0] = tree; - else - this._layerTrees.splice(0, 0, tree); - } else { - if (this._baseImageryLayerIncluded) - this._layerTrees.shift(); - } - this._baseImageryLayerIncluded = tree !== undefined; - this.clearLayers(); - } - public get layerSettings(): MapLayerSettings[] { - return this._layerSettings; - } - - public setLayerSettings(layerSettings: MapLayerSettings[]) { - this._layerSettings = layerSettings; - const baseLayerIndex = this._baseImageryLayerIncluded ? 1 : 0; - - this._layerTrees.length = Math.min(layerSettings.length + baseLayerIndex, this._layerTrees.length); // Truncate if number of layers reduced. - for (let i = 0; i < layerSettings.length; i++) { - const treeIndex = i + baseLayerIndex; - if (treeIndex >= this._layerTrees.length || !this._layerTrees[treeIndex].layerSettings.displayMatches(layerSettings[i])) - this._layerTrees[treeIndex] = createMapLayerTreeReference(layerSettings[i], treeIndex, this._iModel)!; - } - this.clearLayers(); - } - - public clearLayers() { - const tree = this.treeOwner.tileTree as MapTileTree; - if (undefined !== tree) - tree.clearLayers(); - } - - public override get castsShadows() { - return false; - } - - protected override get _isLoadingComplete(): boolean { - // Wait until drape tree is fully loaded too. - for (const drapeTree of this._layerTrees) - if (!drapeTree.isLoadingComplete) - return false; - - return super._isLoadingComplete; - } - public get useDepthBuffer() { - return !this.isOverlay && (this.settings.applyTerrain || this.settings.useDepthBuffer); - } - - public get treeOwner(): TileTreeOwner { - let wantSkirts = (this.settings.applyTerrain || this.useDepthBuffer) && !this.settings.transparency && !this._baseTransparent; - if (wantSkirts) { - const maskTrans = this._planarClipMask?.settings.transparency; - wantSkirts = (undefined === maskTrans || maskTrans <= 0); - } - - const id: MapTreeId = { - tileUserId: this._tileUserId, - applyTerrain: this.settings.applyTerrain && !this.isOverlay && !this._isDrape, - terrainProviderName: this.settings.terrainSettings.providerName, - terrainHeightOrigin: this.settings.terrainSettings.heightOrigin, - terrainHeightOriginMode: this.settings.terrainSettings.heightOriginMode, - terrainExaggeration: this.settings.terrainSettings.exaggeration, - mapGroundBias: this.settings.groundBias, - wantSkirts, - // Can set to this.settings.terrainSettings.applyLighting if we want to ever apply lighting to terrain again so that normals are retrieved when lighting is on. - wantNormals: false, - globeMode: this._isDrape ? GlobeMode.Plane : this.settings.globeMode, - isOverlay: this.isOverlay, - useDepthBuffer: this.useDepthBuffer, - baseColor: this._baseColor, - baseTransparent: this._baseTransparent, - mapTransparent: this.settings.transparency > 0, - maskModelIds: this._planarClipMask?.settings.compressedModelIds, - produceGeometry: false, - }; - - if (undefined !== this._overrideTerrainDisplay) { - const ovr = this._overrideTerrainDisplay(); - if (undefined !== ovr) { - id.wantSkirts = ovr.wantSkirts ?? id.wantSkirts; - id.wantNormals = ovr.wantNormals ?? id.wantNormals; - id.produceGeometry = ovr.produceGeometry === true; - } - } - - return this._iModel.tiles.getTileTreeOwner(id, mapTreeSupplier); - } - public getLayerImageryTreeRef(index: number) { - const baseLayerIndex = this._baseImageryLayerIncluded ? 1 : 0; - const treeIndex = index + baseLayerIndex; - return index < 0 || treeIndex >= this._layerTrees.length ? undefined : this._layerTrees[treeIndex]; - } - - public initializeLayers(context: SceneContext): boolean { - const tree = this.treeOwner.load() as MapTileTree; - if (undefined === tree) - return false; // Not loaded yet. - - tree.imageryTrees.length = 0; - if (0 === this._layerTrees.length) - return !this.isOverlay; - - let treeIndex = this._layerTrees.length - 1; - // Start displaying at the highest completely opaque layer... - for (; treeIndex >= 1; treeIndex--) { - const layerTreeRef = this._layerTrees[treeIndex]; - if (layerTreeRef.isOpaque) - break; // This layer is completely opaque and will obscure all others so ignore lower ones. - } - for (; treeIndex < this._layerTrees.length; treeIndex++) { - const layerTreeRef = this._layerTrees[treeIndex]; - if (TileTreeLoadStatus.NotFound !== layerTreeRef.treeOwner.loadStatus && layerTreeRef.layerSettings.visible && !layerTreeRef.layerSettings.allSubLayersInvisible) { - const layerTree = layerTreeRef.treeOwner.load(); - if (undefined === layerTree) - return false; // Not loaded yet. - if (layerTree instanceof ImageryMapTileTree) { - tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex); - } else if (layerTreeRef instanceof ModelMapLayerTileTreeReference) - tree.addModelLayer(layerTreeRef, context); - } - } - return true; - } - - /** Adds this reference's graphics to the scene. By default this invokes [[TileTree.drawScene]] on the referenced TileTree, if it is loaded. */ - public override addToScene(context: SceneContext): void { - if (!context.viewFlags.backgroundMap) - return; - - const tree = this.treeOwner.load() as MapTileTree; - if (undefined === tree || !this.initializeLayers(context)) - return; // Not loaded yet. - - if (this._planarClipMask && this._planarClipMask.settings.isValid) - context.addPlanarClassifier(tree.modelId, undefined, this._planarClipMask); - - const nonLocatable = this.settings.locatable ? undefined : true; - const transparency = this.settings.transparency ? this.settings.transparency : undefined; - this._symbologyOverrides = new FeatureSymbology.Overrides(); - if (nonLocatable || transparency) { - this._symbologyOverrides.override({ - modelId: tree.modelId, - appearance: FeatureAppearance.fromJSON({ transparency, nonLocatable }), - }); - } - - const args = this.createDrawArgs(context); - if (undefined !== args) - tree.draw(args); - - tree.clearImageryTreesAndClassifiers(); - } - - public override createDrawArgs(context: SceneContext): TileDrawArgs | undefined { - const args = super.createDrawArgs(context); - if (undefined === args) - return undefined; - - const tree = this.treeOwner.load() as MapTileTree; - return new RealityTileDrawArgs(args, args.worldToViewMap, args.frustumPlanes, undefined, tree?.layerClassifiers); - } - - protected override getViewFlagOverrides(_tree: TileTree) { - return createViewFlagOverrides(false, this._settings.applyTerrain ? undefined : false); - } - - protected override getSymbologyOverrides(_tree: TileTree) { - return this._symbologyOverrides; - } - - public override discloseTileTrees(trees: DisclosedTileTreeSet): void { - super.discloseTileTrees(trees); - this._layerTrees.forEach((imageryTree) => trees.disclose(imageryTree)); - if (this._planarClipMask) - this._planarClipMask.discloseTileTrees(trees); - } - public imageryTreeFromTreeModelIds(mapTreeModelId: Id64String, layerTreeModelId: Id64String): ImageryMapLayerTreeReference | undefined { - const tree = this.treeOwner.tileTree as MapTileTree; - if (undefined === tree || tree.modelId !== mapTreeModelId) - return undefined; - - for (const imageryTree of this._layerTrees) - if (imageryTree.treeOwner.tileTree && imageryTree.treeOwner.tileTree.modelId === layerTreeModelId) - return imageryTree; - - return undefined; - } - public layerFromTreeModelIds(mapTreeModelId: Id64String, layerTreeModelId: Id64String): MapLayerSettings | undefined { - const imageryTree = this.imageryTreeFromTreeModelIds(mapTreeModelId, layerTreeModelId); - return imageryTree === undefined ? imageryTree : imageryTree.layerSettings; - } - - public override async getToolTip(hit: HitDetail): Promise { - const tree = this.treeOwner.tileTree as MapTileTree; - // eslint-disable-next-line @typescript-eslint/unbound-method - if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.modelId || !hit.viewport || !hit.viewport.view.is3d) - return undefined; - - const backgroundMapGeometry = hit.viewport.displayStyle.getBackgroundMapGeometry(); - if (undefined === backgroundMapGeometry) - return undefined; - - const worldPoint = hit.hitPoint.clone(); - const cartoGraphic = await backgroundMapGeometry.dbToCartographicFromGcs(worldPoint); - const strings = []; - const imageryTreeRef = this.imageryTreeFromTreeModelIds(hit.modelId, hit.sourceId); - if (imageryTreeRef !== undefined) { - strings.push(`Imagery Layer: ${imageryTreeRef.layerSettings.name}`); - if (hit.tileId !== undefined) { - const terrainQuadId = QuadId.createFromContentId(hit.tileId); - const terrainTile = tree.tileFromQuadId(terrainQuadId); - if (terrainTile && terrainTile.imageryTiles) { - const imageryTree = imageryTreeRef.treeOwner.tileTree as ImageryMapTileTree; - if (imageryTree) { - for (const imageryTile of terrainTile.imageryTiles) { - if (imageryTree === imageryTile.imageryTree && imageryTile.rectangle.containsCartographic(cartoGraphic)) - await imageryTree.imageryLoader.getToolTip(strings, imageryTile.quadId, cartoGraphic, imageryTree); - } - } - } - } - } - - strings.push(`Latitude: ${cartoGraphic.latitudeDegrees.toFixed(4)}`); - strings.push(`Longitude: ${cartoGraphic.longitudeDegrees.toFixed(4)}`); - if (this.settings.applyTerrain) { - const geodeticHeight = (cartoGraphic.height - tree.bimElevationBias) / tree.terrainExaggeration; - strings.push(`Height (Meters) Geodetic: ${geodeticHeight.toFixed(1)} Sea Level: ${(geodeticHeight - tree.geodeticOffset).toFixed(1)}`); - } - const div = document.createElement("div"); - div.innerHTML = strings.join("
"); - return div; - } - - /** Add logo cards to logo div. */ - public override addLogoCards(cards: HTMLTableElement, vp: ScreenViewport): void { - const tree = this.treeOwner.tileTree as MapTileTree; - let logo; - if (tree) { - if (undefined !== (logo = tree.mapLoader.terrainProvider.getLogo())) - cards.appendChild(logo); - for (const imageryTreeRef of this._layerTrees) { - if (imageryTreeRef.layerSettings.visible) { - const imageryTree = imageryTreeRef.treeOwner.tileTree as ImageryMapTileTree; - if (imageryTree && (undefined !== (logo = imageryTree.getLogo(vp)))) - cards.appendChild(logo); - } - } - } - } -} - -/** Returns whether a GCS converter is available. - * @internal - */ -export async function getGcsConverterAvailable(iModel: IModelConnection) { - if (iModel.noGcsDefined) - return false; - - // Determine if we have a usable GCS. - const converter = iModel.geoServices.getConverter("WGS84"); - if (undefined === converter) - return false; - const requestProps: XYZProps[] = [{ x: 0, y: 0, z: 0 }]; - let haveConverter; - try { - const responseProps = await converter.getIModelCoordinatesFromGeoCoordinates(requestProps); - haveConverter = responseProps.iModelCoords.length === 1 && responseProps.iModelCoords[0].s !== GeoCoordStatus.NoGCSDefined; - } catch { - haveConverter = false; - } - return haveConverter; -} +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +/** @packageDocumentation + * @module Tiles + */ + +import { assert, compareBooleans, compareBooleansOrUndefined, compareNumbers, compareStrings, compareStringsOrUndefined, CompressedId64Set, Id64String } from "@itwin/core-bentley"; +import { + BackgroundMapSettings, BaseLayerSettings, Cartographic, ColorDef, FeatureAppearance, GeoCoordStatus, GlobeMode, MapLayerSettings, PlanarClipMaskPriority, TerrainHeightOriginMode, + TerrainProviderName, +} from "@itwin/core-common"; +import { + Angle, AngleSweep, Constant, Ellipsoid, EllipsoidPatch, Point3d, Range1d, Range3d, Ray3d, Transform, Vector3d, XYZProps, +} from "@itwin/core-geometry"; +import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; +import { TerrainDisplayOverrides } from "../../DisplayStyleState"; +import { HitDetail } from "../../HitDetail"; +import { IModelConnection } from "../../IModelConnection"; +import { PlanarClipMaskState } from "../../PlanarClipMaskState"; +import { FeatureSymbology } from "../../render/FeatureSymbology"; +import { RenderPlanarClassifier } from "../../render/RenderPlanarClassifier"; +import { SceneContext } from "../../ViewContext"; +import { ScreenViewport } from "../../Viewport"; +import { + BingElevationProvider, + createDefaultViewFlagOverrides, createMapLayerTreeReference, DisclosedTileTreeSet, EllipsoidTerrainProvider, GeometryTileTreeReference, getCesiumTerrainProvider, GraphicsCollectorDrawArgs, + ImageryMapLayerTreeReference, + ImageryMapTileTree, + MapCartoRectangle, + MapLayerFeatureInfo, + MapLayerTileTreeReference, + MapTile, + MapTileLoader, + MapTilingScheme, + ModelMapLayerTileTreeReference, + PlanarTilePatch, + QuadId, + RealityTile, RealityTileDrawArgs, RealityTileTree, RealityTileTreeParams, Tile, TileDrawArgs, TileLoadPriority, TileParams, TileTree, TileTreeLoadStatus, TileTreeOwner, TileTreeReference, TileTreeSupplier, UpsampledMapTile, WebMercatorTilingScheme, +} from "../internal"; + +const scratchPoint = Point3d.create(); +const scratchCorners = [Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()]; +const scratchCorner = Point3d.createZero(); +const scratchZNormal = Vector3d.create(0, 0, 1); + +/** @internal */ +export class MapTileTree extends RealityTileTree { + private _mercatorFractionToDb: Transform; + public earthEllipsoid: Ellipsoid; + public minEarthEllipsoid: Ellipsoid; + public maxEarthEllipsoid: Ellipsoid; + public globeMode: GlobeMode; + public globeOrigin: Point3d; + private _mercatorTilingScheme: MapTilingScheme; + public useDepthBuffer: boolean; + public isOverlay: boolean; + public terrainExaggeration: number; + public baseColor?: ColorDef; + public baseTransparent: boolean; + public mapTransparent: boolean; + public produceGeometry?: boolean; + + constructor(params: RealityTileTreeParams, public ecefToDb: Transform, public bimElevationBias: number, public geodeticOffset: number, + public sourceTilingScheme: MapTilingScheme, id: MapTreeId, applyTerrain: boolean) { + super(params); + this._mercatorTilingScheme = new WebMercatorTilingScheme(); + this._mercatorFractionToDb = this._mercatorTilingScheme.computeMercatorFractionToDb(ecefToDb, bimElevationBias, params.iModel, applyTerrain); + const quadId = new QuadId(sourceTilingScheme.rootLevel, 0, 0); + this.globeOrigin = this.ecefToDb.getOrigin().clone(); + this.earthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.polar); + const globalHeightRange = applyTerrain ? ApproximateTerrainHeights.instance.globalHeightRange : Range1d.createXX(0, 0); + const globalRectangle = MapCartoRectangle.create(); + + this.globeMode = id.globeMode; + this.isOverlay = id.isOverlay; + this.useDepthBuffer = id.useDepthBuffer; + this.terrainExaggeration = id.terrainExaggeration; + this.baseColor = id.baseColor; + this.baseTransparent = id.baseTransparent; + this.mapTransparent = id.mapTransparent; + if (applyTerrain) { + this.minEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.polar + globalHeightRange.low); + this.maxEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.polar + globalHeightRange.high); + this.produceGeometry = id.produceGeometry; + } else { + this.minEarthEllipsoid = this.earthEllipsoid; + this.maxEarthEllipsoid = this.earthEllipsoid; + } + + const rootPatch = EllipsoidPatch.createCapture(this.maxEarthEllipsoid, AngleSweep.createStartSweepRadians(0, Angle.pi2Radians), AngleSweep.createStartSweepRadians(-Angle.piOver2Radians, Angle.piRadians)); + let range; + if (this.globeMode === GlobeMode.Ellipsoid) { + range = rootPatch.range(); + } else { + const corners = this.getFractionalTileCorners(quadId); + this._mercatorFractionToDb.multiplyPoint3dArrayInPlace(corners); + range = Range3d.createArray(MapTile.computeRangeCorners(corners, Vector3d.create(0, 0, 1), 0, scratchCorners, globalHeightRange)); + } + this._rootTile = this.createGlobeChild({ contentId: quadId.contentId, maximumSize: 0, range }, quadId, range.corners(), globalRectangle, rootPatch, undefined); + + } + + // If we are not depth buffering we force parents and exclusive to false to cause the map tiles to be sorted by depth so that painters algorithm will approximate correct depth display. + public override get parentsAndChildrenExclusive() { return this.useDepthBuffer ? this.loader.parentsAndChildrenExclusive : false; } + + public tileFromQuadId(quadId: QuadId): MapTile | undefined { + return (this._rootTile as MapTile).tileFromQuadId(quadId); + } + + public imageryTrees: ImageryMapTileTree[] = []; + private _layerSettings = new Map(); + private _modelIdToIndex = new Map(); + public layerClassifiers = new Map(); + + public addImageryLayer(tree: ImageryMapTileTree, settings: MapLayerSettings, index: number) { + this.imageryTrees.push(tree); + this._layerSettings.set(tree.modelId, settings); + this._modelIdToIndex.set(tree.modelId, index); + } + + public addModelLayer(layerTreeRef: ModelMapLayerTileTreeReference, context: SceneContext) { + const classifier = context.addPlanarClassifier(`MapLayer ${this.modelId}-${layerTreeRef.layerIndex}`, layerTreeRef); + if (classifier) + this.layerClassifiers.set(layerTreeRef.layerIndex, classifier); + } + + protected override collectClassifierGraphics(args: TileDrawArgs, selectedTiles: RealityTile[]) { + super.collectClassifierGraphics(args, selectedTiles); + + this.layerClassifiers.forEach((layerClassifier: RenderPlanarClassifier) => { + if (!(args instanceof GraphicsCollectorDrawArgs)) + layerClassifier.collectGraphics(args.context, { modelId: this.modelId, tiles: selectedTiles, location: args.location, isPointCloud: this.isPointCloud }); + + }); + } + + public clearImageryTreesAndClassifiers() { + this.imageryTrees.length = 0; + this._layerSettings.clear(); + this._modelIdToIndex.clear(); + this.layerClassifiers.clear(); + } + + public override get isTransparent() { + return this.mapTransparent || this.baseTransparent; + } + + public override get maxDepth() { + let maxDepth = this.loader.maxDepth; + this.imageryTrees?.forEach((imageryTree) => maxDepth = Math.max(maxDepth, imageryTree.maxDepth)); + + return maxDepth; + } + public createPlanarChild(params: TileParams, quadId: QuadId, corners: Point3d[], normal: Vector3d, rectangle: MapCartoRectangle, chordHeight: number, heightRange?: Range1d): MapTile | undefined{ + const childAvailable = this.mapLoader.isTileAvailable(quadId); + if (!childAvailable && this.produceGeometry) + return undefined; + const patch = new PlanarTilePatch(corners, normal, chordHeight); + const cornerNormals = this.getCornerRays(rectangle); + const ctor = childAvailable ? MapTile : UpsampledMapTile; + return new ctor(params, this, quadId, patch, rectangle, heightRange, cornerNormals); + } + + public createGlobeChild(params: TileParams, quadId: QuadId, _rangeCorners: Point3d[], rectangle: MapCartoRectangle, ellipsoidPatch: EllipsoidPatch, heightRange?: Range1d): MapTile { + return new MapTile(params, this, quadId, ellipsoidPatch, rectangle, heightRange, this.getCornerRays(rectangle)); + } + + public getChildHeightRange(quadId: QuadId, rectangle: MapCartoRectangle, parent: MapTile): Range1d | undefined { + return this.mapLoader.getChildHeightRange(quadId, rectangle, parent); + } + + public clearLayers() { + (this._rootTile as MapTile).clearLayers(); + } + + public static minReprojectionDepth = 8; // Reprojection does not work with very large tiles so just do linear transform. + public static maxGlobeDisplayDepth = 8; + public static minDisplayableDepth = 3; + public get mapLoader() { return this.loader as MapTileLoader; } + public override getBaseRealityDepth(sceneContext: SceneContext) { + // If the view has ever had global scope then preload low level (global) tiles. + return (sceneContext.viewport.view.maxGlobalScopeFactor > 1) ? MapTileTree.minDisplayableDepth : -1; + } + + public doCreateGlobeChildren(tile: Tile): boolean { + if (this.globeMode !== GlobeMode.Ellipsoid) + return false; + + const childDepth = tile.depth + 1; + if (childDepth < MapTileTree.maxGlobeDisplayDepth) // If the depth is too low (tile is too large) display as globe. + return true; + + return false; // Display as globe if more than 100 KM from project. + } + public override doReprojectChildren(tile: Tile): boolean { + if (this._gcsConverter === undefined) + return false; + + const childDepth = tile.depth + 1; + if (childDepth < MapTileTree.minReprojectionDepth) // If the depth is too low (tile is too large) omit reprojection. + return false; + + return this.cartesianRange.intersectsRange(tile.range); + } + + public getCornerRays(rectangle: MapCartoRectangle): Ray3d[] | undefined { + const rays = new Array(); + if (this.globeMode === GlobeMode.Ellipsoid) { + rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.low.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.high.y))!); + rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.high.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.high.y))!); + rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.low.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.low.y))!); + rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.high.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.low.y))!); + } else { + const mercatorFractionRange = rectangle.getTileFractionRange(this._mercatorTilingScheme); + rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.high.y), scratchZNormal)); + rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.high.y), scratchZNormal)); + rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.low.y), scratchZNormal)); + rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.low.y), scratchZNormal)); + } + return rays; + } + public pointAboveEllipsoid(point: Point3d): boolean { + return this.earthEllipsoid.worldToLocal(point, scratchPoint)!.magnitude() > 1; + } + + private getMercatorFractionChildGridPoints(tile: MapTile, columnCount: number, rowCount: number): Point3d[] { + const gridPoints = []; + const quadId = tile.quadId; + const deltaX = 1.0 / columnCount, deltaY = 1.0 / rowCount; + for (let row = 0; row <= rowCount; row++) { + for (let column = 0; column <= columnCount; column++) { + const xFraction = this.sourceTilingScheme.tileXToFraction(quadId.column + column * deltaX, quadId.level); + const yFraction = this.sourceTilingScheme.tileYToFraction(quadId.row + row * deltaY, quadId.level); + + gridPoints.push(Point3d.create(xFraction, yFraction, 0)); + } + } + // If not mercator already need to remap latitude... + if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) + for (const gridPoint of gridPoints) + gridPoint.y = this._mercatorTilingScheme.latitudeToYFraction(this.sourceTilingScheme.yFractionToLatitude(gridPoint.y)); + + return gridPoints; + } + + private getChildCornersFromGridPoints(gridPoints: Point3d[], columnCount: number, rowCount: number) { + const childCorners = new Array(); + for (let row = 0; row < rowCount; row++) { + for (let column = 0; column < columnCount; column++) { + const index0 = column + row * (columnCount + 1); + const index1 = index0 + (columnCount + 1); + childCorners.push([gridPoints[index0], gridPoints[index0 + 1], gridPoints[index1], gridPoints[index1 + 1]]); + } + } + return childCorners; + } + + public getCachedReprojectedPoints(gridPoints: Point3d[]): (Point3d | undefined)[] | undefined { + const requestProps = []; + for (const gridPoint of gridPoints) + requestProps.push({ + x: this._mercatorTilingScheme.xFractionToLongitude(gridPoint.x) * Angle.degreesPerRadian, + y: this._mercatorTilingScheme.yFractionToLatitude(gridPoint.y) * Angle.degreesPerRadian, + z: this.bimElevationBias, + }); + + const iModelCoordinates = this._gcsConverter!.getCachedIModelCoordinatesFromGeoCoordinates(requestProps); + + if (iModelCoordinates.missing) + return undefined; + + return iModelCoordinates.result.map((result) => !result || result.s ? undefined : Point3d.fromJSON(result.p)); + } + + // Minimize reprojection requests by requesting this corners tile and a grid that will include all points for 4 levels of descendants. + // This greatly reduces the number of reprojection requests which currently require a roundtrip through the backend. + public async loadReprojectionCache(tile: MapTile): Promise { + const quadId = tile.quadId; + const xRange = Range1d.createXX(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level)); + const yRange = Range1d.createXX(this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level)); + const cacheDepth = 4, cacheDimension = 2 ** cacheDepth; + const delta = 1.0 / cacheDimension; + const requestProps = []; + + for (let row = 0; row <= cacheDimension; row++) { + for (let column = 0; column <= cacheDimension; column++) { + let yFraction = yRange.fractionToPoint(row * delta); + if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) + yFraction = this._mercatorTilingScheme.latitudeToYFraction(this.sourceTilingScheme.yFractionToLatitude(yFraction)); + requestProps.push({ + x: this._mercatorTilingScheme.xFractionToLongitude(xRange.fractionToPoint(column * delta)) * Angle.degreesPerRadian, + y: this._mercatorTilingScheme.yFractionToLatitude(yFraction) * Angle.degreesPerRadian, + z: this.bimElevationBias, + }); + } + } + + await this._gcsConverter!.getIModelCoordinatesFromGeoCoordinates(requestProps); + } + + private static _scratchCarto = Cartographic.createZero(); + + // Get the corners for planar children -- This generally will resolve immediately, but may require an asynchronous request for reprojecting the corners. + public getPlanarChildCorners(tile: MapTile, columnCount: number, rowCount: number, resolve: (childCorners: Point3d[][]) => void) { + const resolveCorners = (points: Point3d[], reprojected: (Point3d | undefined)[] | undefined = undefined) => { + for (let i = 0; i < points.length; i++) { + const gridPoint = points[i]; + this._mercatorFractionToDb.multiplyPoint3d(gridPoint, scratchCorner); + if (this.globeMode !== GlobeMode.Ellipsoid || this.cartesianRange.containsPoint(scratchCorner)) { + if (reprojected !== undefined && reprojected[i] !== undefined) + reprojected[i]!.clone(gridPoint); + else + scratchCorner.clone(gridPoint); + } else { + this._mercatorTilingScheme.fractionToCartographic(gridPoint.x, gridPoint.y, MapTileTree._scratchCarto); + this.earthEllipsoid.radiansToPoint(MapTileTree._scratchCarto.longitude, Cartographic.parametricLatitudeFromGeodeticLatitude(MapTileTree._scratchCarto.latitude), gridPoint); + const cartesianDistance = this.cartesianRange.distanceToPoint(scratchCorner); + if (cartesianDistance < this.cartesianTransitionDistance) + scratchCorner.interpolate(cartesianDistance / this.cartesianTransitionDistance, gridPoint, gridPoint); + } + } + resolve(this.getChildCornersFromGridPoints(points, columnCount, rowCount)); + }; + + let reprojectedPoints: (Point3d | undefined)[] | undefined; + const gridPoints = this.getMercatorFractionChildGridPoints(tile, columnCount, rowCount); + if (this.doReprojectChildren(tile)) { + reprojectedPoints = this.getCachedReprojectedPoints(gridPoints); + if (reprojectedPoints) { + // If the reprojected corners are in the cache, resolve immediately. + resolveCorners(gridPoints, reprojectedPoints); + } else { + // If the reprojected corners are not in cache request them - but also request reprojection of a grid that will include descendent corners to ensure they can + // be reloaded without expensive reprojection requests. + this.loadReprojectionCache(tile).then(() => { + const reprojected = this.getCachedReprojectedPoints(gridPoints); + assert(reprojected !== undefined); // We just cached them... they better be there now. + resolveCorners(gridPoints, reprojected); + }).catch((_error: Error) => { + resolveCorners(gridPoints); + }); + } + } else { + resolveCorners(gridPoints); + } + } + + public getFractionalTileCorners(quadId: QuadId): Point3d[] { + const corners: Point3d[] = []; + corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); + corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); + corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); + corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); + return corners; + } + + public getTileRectangle(quadId: QuadId): MapCartoRectangle { + return this.sourceTilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); + } + public getLayerIndex(imageryTreeId: Id64String) { + const index = this._modelIdToIndex.get(imageryTreeId); + return index === undefined ? -1 : index; + } + + public getLayerTransparency(imageryTreeId: Id64String): number { + const layerSettings = this._layerSettings.get(imageryTreeId); + assert(undefined !== layerSettings); + return undefined === layerSettings || !layerSettings.transparency ? 0.0 : layerSettings.transparency; + } +} + +interface MapTreeId { + tileUserId: number; + applyTerrain: boolean; + terrainProviderName: TerrainProviderName; + terrainHeightOrigin: number; + terrainHeightOriginMode: number; + terrainExaggeration: number; + mapGroundBias: number; + wantSkirts: boolean; + wantNormals: boolean; + globeMode: GlobeMode; + useDepthBuffer: boolean; + isOverlay: boolean; + baseColor?: ColorDef; + baseTransparent: boolean; + mapTransparent: boolean; + maskModelIds?: string; + produceGeometry?: boolean; +} + +/** @internal */ +class MapTileTreeProps implements RealityTileTreeParams { + public id: string; + public modelId: string; + public location = Transform.createIdentity(); + public yAxisUp = true; + public is3d = true; + public rootTile = { contentId: "", range: Range3d.createNull(), maximumSize: 0 }; + public loader: MapTileLoader; + public iModel: IModelConnection; + public get priority(): TileLoadPriority { return this.loader.priority; } + + public constructor(modelId: Id64String, loader: MapTileLoader, iModel: IModelConnection, public gcsConverterAvailable: boolean) { + this.id = this.modelId = modelId; + this.loader = loader; + this.iModel = iModel; + } +} + +function createViewFlagOverrides(wantLighting: boolean, wantThematic: false | undefined) { + return createDefaultViewFlagOverrides({ clipVolume: false, lighting: wantLighting, thematic: wantThematic }); +} + +class MapTreeSupplier implements TileTreeSupplier { + public readonly isEcefDependent = true; + + public compareTileTreeIds(lhs: MapTreeId, rhs: MapTreeId): number { + let cmp = compareNumbers(lhs.tileUserId, rhs.tileUserId); + if (0 === cmp) { + cmp = compareStringsOrUndefined(lhs.maskModelIds, rhs.maskModelIds); + if (0 === cmp) { + cmp = compareBooleans(lhs.isOverlay, rhs.isOverlay); + if (0 === cmp && !lhs.isOverlay) { + cmp = compareBooleans(lhs.wantSkirts, rhs.wantSkirts); + if (0 === cmp) { + cmp = compareBooleans(lhs.wantNormals, rhs.wantNormals); + if (0 === cmp) { + cmp = compareNumbers(lhs.globeMode, rhs.globeMode); + if (0 === cmp) { + cmp = compareNumbers(lhs.baseColor ? lhs.baseColor.tbgr : -1, rhs.baseColor ? rhs.baseColor.tbgr : -1); + if (0 === cmp) { + cmp = compareBooleans(lhs.baseTransparent, rhs.baseTransparent); + if (0 === cmp) { + cmp = compareBooleans(lhs.mapTransparent, rhs.mapTransparent); + if (0 === cmp) { + cmp = compareBooleans(lhs.applyTerrain, rhs.applyTerrain); + if (0 === cmp) { + if (lhs.applyTerrain) { + // Terrain-only settings. + cmp = compareStrings(lhs.terrainProviderName, rhs.terrainProviderName); + if (0 === cmp) { + cmp = compareNumbers(lhs.terrainHeightOrigin, rhs.terrainHeightOrigin); + if (0 === cmp) { + cmp = compareNumbers(lhs.terrainHeightOriginMode, rhs.terrainHeightOriginMode); + if (0 === cmp) { + cmp = compareNumbers(lhs.terrainExaggeration, rhs.terrainExaggeration); + if (0 === cmp) + cmp = compareBooleansOrUndefined(lhs.produceGeometry, rhs.produceGeometry); + } + } + } + } else { + // Non-Terrain (flat) settings. + cmp = compareNumbers(lhs.mapGroundBias, rhs.mapGroundBias); + if (0 === cmp) + cmp = compareBooleans(lhs.useDepthBuffer, rhs.useDepthBuffer); + } + } + } + } + } + } + } + } + } + } + } + + return cmp; + } + + private async computeHeightBias(heightOrigin: number, heightOriginMode: TerrainHeightOriginMode, exaggeration: number, iModel: IModelConnection, elevationProvider: BingElevationProvider): Promise { + const projectCenter = iModel.projectExtents.center; + switch (heightOriginMode) { + case TerrainHeightOriginMode.Ground: + return heightOrigin + exaggeration * (await elevationProvider.getHeightValue(projectCenter, iModel, true)); + + case TerrainHeightOriginMode.Geodetic: + return heightOrigin; + + case TerrainHeightOriginMode.Geoid: + return heightOrigin + await elevationProvider.getGeodeticToSeaLevelOffset(projectCenter, iModel); + } + } + + public async createTileTree(id: MapTreeId, iModel: IModelConnection): Promise { + let bimElevationBias = 0, terrainProvider, geodeticOffset = 0; + let applyTerrain = id.applyTerrain; + const modelId = iModel.transientIds.next; + const gcsConverterAvailable = await getGcsConverterAvailable(iModel); + + if (id.applyTerrain) { + assert(id.terrainProviderName === "CesiumWorldTerrain"); + await ApproximateTerrainHeights.instance.initialize(); + const elevationProvider = new BingElevationProvider(); + + bimElevationBias = - await this.computeHeightBias(id.terrainHeightOrigin, id.terrainHeightOriginMode, id.terrainExaggeration, iModel, elevationProvider); + geodeticOffset = await elevationProvider.getGeodeticToSeaLevelOffset(iModel.projectExtents.center, iModel); + terrainProvider = await getCesiumTerrainProvider(iModel, modelId, id.wantSkirts, id.wantNormals, id.terrainExaggeration); + + if (!terrainProvider) { + applyTerrain = false; + geodeticOffset = 0; + } + } + + if (!terrainProvider) { + terrainProvider = new EllipsoidTerrainProvider(iModel, modelId, id.wantSkirts); + bimElevationBias = id.mapGroundBias; + } + + const loader = new MapTileLoader(iModel, modelId, bimElevationBias, terrainProvider); + const ecefToDb = iModel.getMapEcefToDb(bimElevationBias); + + if (id.maskModelIds) + await iModel.models.load(CompressedId64Set.decompressSet(id.maskModelIds)); + + const treeProps = new MapTileTreeProps(modelId, loader, iModel, gcsConverterAvailable); + return new MapTileTree(treeProps, ecefToDb, bimElevationBias, geodeticOffset, terrainProvider.tilingScheme, id, applyTerrain); + } +} + +const mapTreeSupplier = new MapTreeSupplier(); + +/** @internal */ +type CheckTerrainDisplayOverride = () => TerrainDisplayOverrides | undefined; + +/** Specialization of tile tree that represents background map. + * @internal + */ +export class MapTileTreeReference extends TileTreeReference { + private _tileUserId: number; + private _settings: BackgroundMapSettings; + private readonly _iModel: IModelConnection; + private _baseImageryLayerIncluded = false; + private _baseColor?: ColorDef; + private readonly _layerTrees = new Array(); + private _baseTransparent = false; + private _symbologyOverrides: FeatureSymbology.Overrides | undefined; + private _planarClipMask?: PlanarClipMaskState; + + public constructor(settings: BackgroundMapSettings, private _baseLayerSettings: BaseLayerSettings | undefined, private _layerSettings: MapLayerSettings[], iModel: IModelConnection, tileUserId: number, public isOverlay: boolean, private _isDrape: boolean, private _overrideTerrainDisplay?: CheckTerrainDisplayOverride) { + super(); + this._tileUserId = tileUserId; + this._settings = settings; + this._iModel = iModel; + let tree; + if (!isOverlay && this._baseLayerSettings !== undefined) { + if (this._baseLayerSettings instanceof MapLayerSettings) { + tree = createMapLayerTreeReference(this._baseLayerSettings, 0, iModel); + this._baseTransparent = this._baseLayerSettings.transparency > 0; + } else { + this._baseColor = this._baseLayerSettings; + this._baseTransparent = this._baseColor?.getTransparency() > 0; + } + } + + if (this._baseImageryLayerIncluded = (undefined !== tree)) + this._layerTrees.push(tree); + + for (let i = 0; i < this._layerSettings.length; i++) + if (undefined !== (tree = createMapLayerTreeReference(this._layerSettings[i], i + 1, iModel))) + this._layerTrees.push(tree); + + if (this._settings.planarClipMask && this._settings.planarClipMask.isValid) + this._planarClipMask = PlanarClipMaskState.create(this._settings.planarClipMask); + + if (this._overrideTerrainDisplay && this._overrideTerrainDisplay()?.produceGeometry) + this.collectTileGeometry = (collector) => this._collectTileGeometry(collector); + } + + public override get isGlobal() { return true; } + public get baseColor(): ColorDef | undefined { return this._baseColor; } + public override get planarclipMaskPriority(): number { return PlanarClipMaskPriority.BackgroundMap; } + + protected override _createGeometryTreeReference(): GeometryTileTreeReference | undefined { + if (! this._settings.applyTerrain || this._isDrape) + return undefined; // Don't bother generating non-terrain (flat) geometry. + + const ref = new MapTileTreeReference(this._settings, undefined, [], this._iModel, this._tileUserId, false, false, () => { return { produceGeometry: true }; }); + assert(undefined !== ref.collectTileGeometry); + return ref as GeometryTileTreeReference; + } + + /** Terrain tiles do not contribute to the range used by "fit view". */ + public override unionFitRange(_range: Range3d): void { } + public get settings(): BackgroundMapSettings { return this._settings; } + public set settings(settings: BackgroundMapSettings) { + this._settings = settings; + this._planarClipMask = settings.planarClipMask ? PlanarClipMaskState.create(settings.planarClipMask) : undefined; + } + public setBaseLayerSettings(baseLayerSettings: BaseLayerSettings) { + assert(!this.isOverlay); + let tree; + this._baseLayerSettings = baseLayerSettings; + + if (baseLayerSettings instanceof MapLayerSettings) { + tree = createMapLayerTreeReference(baseLayerSettings, 0, this._iModel); + this._baseColor = undefined; + this._baseTransparent = baseLayerSettings.transparency > 0; + } else { + this._baseColor = baseLayerSettings; + this._baseTransparent = this._baseColor.getTransparency() > 0; + } + + if (tree) { + if (this._baseImageryLayerIncluded) + this._layerTrees[0] = tree; + else + this._layerTrees.splice(0, 0, tree); + } else { + if (this._baseImageryLayerIncluded) + this._layerTrees.shift(); + } + this._baseImageryLayerIncluded = tree !== undefined; + this.clearLayers(); + } + public get layerSettings(): MapLayerSettings[] { + return this._layerSettings; + } + + public setLayerSettings(layerSettings: MapLayerSettings[]) { + this._layerSettings = layerSettings; + const baseLayerIndex = this._baseImageryLayerIncluded ? 1 : 0; + + this._layerTrees.length = Math.min(layerSettings.length + baseLayerIndex, this._layerTrees.length); // Truncate if number of layers reduced. + for (let i = 0; i < layerSettings.length; i++) { + const treeIndex = i + baseLayerIndex; + if (treeIndex >= this._layerTrees.length || !this._layerTrees[treeIndex].layerSettings.displayMatches(layerSettings[i])) + this._layerTrees[treeIndex] = createMapLayerTreeReference(layerSettings[i], treeIndex, this._iModel)!; + } + this.clearLayers(); + } + + public clearLayers() { + const tree = this.treeOwner.tileTree as MapTileTree; + if (undefined !== tree) + tree.clearLayers(); + } + + public override get castsShadows() { + return false; + } + + protected override get _isLoadingComplete(): boolean { + // Wait until drape tree is fully loaded too. + for (const drapeTree of this._layerTrees) + if (!drapeTree.isLoadingComplete) + return false; + + return super._isLoadingComplete; + } + public get useDepthBuffer() { + return !this.isOverlay && (this.settings.applyTerrain || this.settings.useDepthBuffer); + } + + public get treeOwner(): TileTreeOwner { + let wantSkirts = (this.settings.applyTerrain || this.useDepthBuffer) && !this.settings.transparency && !this._baseTransparent; + if (wantSkirts) { + const maskTrans = this._planarClipMask?.settings.transparency; + wantSkirts = (undefined === maskTrans || maskTrans <= 0); + } + + const id: MapTreeId = { + tileUserId: this._tileUserId, + applyTerrain: this.settings.applyTerrain && !this.isOverlay && !this._isDrape, + terrainProviderName: this.settings.terrainSettings.providerName, + terrainHeightOrigin: this.settings.terrainSettings.heightOrigin, + terrainHeightOriginMode: this.settings.terrainSettings.heightOriginMode, + terrainExaggeration: this.settings.terrainSettings.exaggeration, + mapGroundBias: this.settings.groundBias, + wantSkirts, + // Can set to this.settings.terrainSettings.applyLighting if we want to ever apply lighting to terrain again so that normals are retrieved when lighting is on. + wantNormals: false, + globeMode: this._isDrape ? GlobeMode.Plane : this.settings.globeMode, + isOverlay: this.isOverlay, + useDepthBuffer: this.useDepthBuffer, + baseColor: this._baseColor, + baseTransparent: this._baseTransparent, + mapTransparent: this.settings.transparency > 0, + maskModelIds: this._planarClipMask?.settings.compressedModelIds, + produceGeometry: false, + }; + + if (undefined !== this._overrideTerrainDisplay) { + const ovr = this._overrideTerrainDisplay(); + if (undefined !== ovr) { + id.wantSkirts = ovr.wantSkirts ?? id.wantSkirts; + id.wantNormals = ovr.wantNormals ?? id.wantNormals; + id.produceGeometry = ovr.produceGeometry === true; + } + } + + return this._iModel.tiles.getTileTreeOwner(id, mapTreeSupplier); + } + public getLayerImageryTreeRef(index: number) { + const baseLayerIndex = this._baseImageryLayerIncluded ? 1 : 0; + const treeIndex = index + baseLayerIndex; + return index < 0 || treeIndex >= this._layerTrees.length ? undefined : this._layerTrees[treeIndex]; + } + + public initializeLayers(context: SceneContext): boolean { + const tree = this.treeOwner.load() as MapTileTree; + if (undefined === tree) + return false; // Not loaded yet. + + tree.imageryTrees.length = 0; + if (0 === this._layerTrees.length) + return !this.isOverlay; + + let treeIndex = this._layerTrees.length - 1; + // Start displaying at the highest completely opaque layer... + for (; treeIndex >= 1; treeIndex--) { + const layerTreeRef = this._layerTrees[treeIndex]; + if (layerTreeRef.isOpaque) + break; // This layer is completely opaque and will obscure all others so ignore lower ones. + } + for (; treeIndex < this._layerTrees.length; treeIndex++) { + const layerTreeRef = this._layerTrees[treeIndex]; + if (TileTreeLoadStatus.NotFound !== layerTreeRef.treeOwner.loadStatus && layerTreeRef.layerSettings.visible && !layerTreeRef.layerSettings.allSubLayersInvisible) { + const layerTree = layerTreeRef.treeOwner.load(); + if (undefined === layerTree) + return false; // Not loaded yet. + if (layerTree instanceof ImageryMapTileTree) { + tree.addImageryLayer(layerTree, layerTreeRef.layerSettings, treeIndex); + } else if (layerTreeRef instanceof ModelMapLayerTileTreeReference) + tree.addModelLayer(layerTreeRef, context); + } + } + return true; + } + + /** Adds this reference's graphics to the scene. By default this invokes [[TileTree.drawScene]] on the referenced TileTree, if it is loaded. */ + public override addToScene(context: SceneContext): void { + if (!context.viewFlags.backgroundMap) + return; + + const tree = this.treeOwner.load() as MapTileTree; + if (undefined === tree || !this.initializeLayers(context)) + return; // Not loaded yet. + + if (this._planarClipMask && this._planarClipMask.settings.isValid) + context.addPlanarClassifier(tree.modelId, undefined, this._planarClipMask); + + const nonLocatable = this.settings.locatable ? undefined : true; + const transparency = this.settings.transparency ? this.settings.transparency : undefined; + this._symbologyOverrides = new FeatureSymbology.Overrides(); + if (nonLocatable || transparency) { + this._symbologyOverrides.override({ + modelId: tree.modelId, + appearance: FeatureAppearance.fromJSON({ transparency, nonLocatable }), + }); + } + + const args = this.createDrawArgs(context); + if (undefined !== args) + tree.draw(args); + + tree.clearImageryTreesAndClassifiers(); + } + + public override createDrawArgs(context: SceneContext): TileDrawArgs | undefined { + const args = super.createDrawArgs(context); + if (undefined === args) + return undefined; + + const tree = this.treeOwner.load() as MapTileTree; + return new RealityTileDrawArgs(args, args.worldToViewMap, args.frustumPlanes, undefined, tree?.layerClassifiers); + } + + protected override getViewFlagOverrides(_tree: TileTree) { + return createViewFlagOverrides(false, this._settings.applyTerrain ? undefined : false); + } + + protected override getSymbologyOverrides(_tree: TileTree) { + return this._symbologyOverrides; + } + + public override discloseTileTrees(trees: DisclosedTileTreeSet): void { + super.discloseTileTrees(trees); + this._layerTrees.forEach((imageryTree) => trees.disclose(imageryTree)); + if (this._planarClipMask) + this._planarClipMask.discloseTileTrees(trees); + } + public imageryTreeFromTreeModelIds(mapTreeModelId: Id64String, layerTreeModelId: Id64String): ImageryMapLayerTreeReference | undefined { + const tree = this.treeOwner.tileTree as MapTileTree; + if (undefined === tree || tree.modelId !== mapTreeModelId) + return undefined; + + for (const imageryTree of this._layerTrees) + if (imageryTree.treeOwner.tileTree && imageryTree.treeOwner.tileTree.modelId === layerTreeModelId) + return imageryTree; + + return undefined; + } + public layerFromTreeModelIds(mapTreeModelId: Id64String, layerTreeModelId: Id64String): MapLayerSettings | undefined { + const imageryTree = this.imageryTreeFromTreeModelIds(mapTreeModelId, layerTreeModelId); + return imageryTree === undefined ? imageryTree : imageryTree.layerSettings; + } + + // Utility method that execute the provided function for every *imagery* tiles under a given HotDetail object. + private async forEachImageryTileHit(hit: HitDetail, func: (imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic,imageryTree: ImageryMapTileTree ) => Promise): Promise { + const tree = this.treeOwner.tileTree as MapTileTree; + if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.modelId || !hit.viewport || !hit.viewport.view.is3d) + return undefined; + + const backgroundMapGeometry = hit.viewport.displayStyle.getBackgroundMapGeometry(); + if (undefined === backgroundMapGeometry) + return undefined; + + const worldPoint = hit.hitPoint.clone(); + let cartoGraphic: Cartographic|undefined; + try { + cartoGraphic = await backgroundMapGeometry.dbToCartographicFromGcs(worldPoint); + } catch { + } + if (!cartoGraphic) { + return undefined; + } + + const strings = []; + const imageryTreeRef = this.imageryTreeFromTreeModelIds(hit.modelId, hit.sourceId); + if (imageryTreeRef !== undefined) { + strings.push(`Imagery Layer: ${imageryTreeRef.layerSettings.name}`); + if (hit.tileId !== undefined) { + const terrainQuadId = QuadId.createFromContentId(hit.tileId); + const terrainTile = tree.tileFromQuadId(terrainQuadId); + if (terrainTile && terrainTile.imageryTiles) { + const imageryTree = imageryTreeRef.treeOwner.tileTree as ImageryMapTileTree; + if (imageryTree) { + for (const imageryTile of terrainTile.imageryTiles) { + if (imageryTree === imageryTile.imageryTree && imageryTile.rectangle.containsCartographic(cartoGraphic)) { + try { + await func (imageryTreeRef, imageryTile.quadId, cartoGraphic, imageryTree); + } catch { + // continue iterating even though we got a failure. + } + + } + + } + } + } + } + } + } + + public override async getToolTip(hit: HitDetail): Promise { + const tree = this.treeOwner.tileTree as MapTileTree; + if (tree.modelId !== hit.modelId) + return undefined; + + let carto: Cartographic|undefined; + + const strings: string[] = []; + + const getTooltipFunc = async (imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic,imageryTree: ImageryMapTileTree ) => { + strings.push(`Imagery Layer: ${imageryTreeRef.layerSettings.name}`); + carto = cartoGraphic; + await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree); + }; + try { + await this.forEachImageryTileHit(hit, getTooltipFunc); + } catch { + // No results added + } + + if (carto) { + strings.push(`Latitude: ${carto.latitudeDegrees.toFixed(4)}`); + strings.push(`Longitude: ${carto.longitudeDegrees.toFixed(4)}`); + if (this.settings.applyTerrain && tree.terrainExaggeration !== 0.0) { + const geodeticHeight = (carto.height - tree.bimElevationBias) / tree.terrainExaggeration; + strings.push(`Height (Meters) Geodetic: ${geodeticHeight.toFixed(1)} Sea Level: ${(geodeticHeight - tree.geodeticOffset).toFixed(1)}`); + } + } + + const div = document.createElement("div"); + div.innerHTML = strings.join("
"); + return div; + } + + public override async getMapFeatureInfo(hit: HitDetail): Promise { + const tree = this.treeOwner.tileTree as MapTileTree; + if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.modelId || !hit.viewport || !hit.viewport.view.is3d) + return undefined; + + const info: MapLayerFeatureInfo[] = []; + const imageryTreeRef = this.imageryTreeFromTreeModelIds(hit.modelId, hit.sourceId); + if (imageryTreeRef !== undefined) { + + const getFeatureInfoFunc = async (_imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic,imageryTree: ImageryMapTileTree ) => { + try { + await imageryTree.imageryLoader.getMapFeatureInfo(info, quadId, cartoGraphic, imageryTree); + } catch { + } + }; + try { + await this.forEachImageryTileHit(hit, getFeatureInfoFunc); + } catch { + // No results added + } + + } + + return info; + } + + /** Add logo cards to logo div. */ + public override addLogoCards(cards: HTMLTableElement, vp: ScreenViewport): void { + const tree = this.treeOwner.tileTree as MapTileTree; + let logo; + if (tree) { + if (undefined !== (logo = tree.mapLoader.terrainProvider.getLogo())) + cards.appendChild(logo); + for (const imageryTreeRef of this._layerTrees) { + if (imageryTreeRef.layerSettings.visible) { + const imageryTree = imageryTreeRef.treeOwner.tileTree as ImageryMapTileTree; + if (imageryTree && (undefined !== (logo = imageryTree.getLogo(vp)))) + cards.appendChild(logo); + } + } + } + } +} + +/** Returns whether a GCS converter is available. + * @internal + */ +export async function getGcsConverterAvailable(iModel: IModelConnection) { + if (iModel.noGcsDefined) + return false; + + // Determine if we have a usable GCS. + const converter = iModel.geoServices.getConverter("WGS84"); + if (undefined === converter) + return false; + const requestProps: XYZProps[] = [{ x: 0, y: 0, z: 0 }]; + let haveConverter; + try { + const responseProps = await converter.getIModelCoordinatesFromGeoCoordinates(requestProps); + haveConverter = responseProps.iModelCoords.length === 1 && responseProps.iModelCoords[0].s !== GeoCoordStatus.NoGCSDefined; + } catch { + haveConverter = false; + } + return haveConverter; +} diff --git a/core/frontend/src/tools/PrimitiveTool.ts b/core/frontend/src/tools/PrimitiveTool.ts index 632d27efbbc0..a1de970ebba5 100644 --- a/core/frontend/src/tools/PrimitiveTool.ts +++ b/core/frontend/src/tools/PrimitiveTool.ts @@ -7,6 +7,7 @@ */ import { assert } from "@itwin/core-bentley"; +import {BriefcaseConnection} from "../BriefcaseConnection"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { NotifyMessageDetails, OutputMessagePriority } from "../NotificationManager"; @@ -36,6 +37,12 @@ export abstract class PrimitiveTool extends InteractiveTool { return this.targetView.view.iModel; } + /** Get the briefcase on which this tool operates, if the tool has successfully installed and the target [[iModel]] is a briefcase. */ + public get briefcase(): BriefcaseConnection | undefined { + const iModel = this.targetView?.view.iModel; + return iModel?.isBriefcaseConnection() ? iModel : undefined; + } + /** * Establish this tool as the active PrimitiveTool. * @return true if this tool was installed (though it may have exited too) diff --git a/core/frontend/src/tools/ToolAdmin.ts b/core/frontend/src/tools/ToolAdmin.ts index 86b938d195a0..ea9c864e1a4a 100644 --- a/core/frontend/src/tools/ToolAdmin.ts +++ b/core/frontend/src/tools/ToolAdmin.ts @@ -6,7 +6,7 @@ * @module Tools */ -import { AbandonedError, BeEvent, Id64String, IModelStatus, Logger } from "@itwin/core-bentley"; +import { AbandonedError, assert, BeEvent, IModelStatus, Logger } from "@itwin/core-bentley"; import { Matrix3d, Point2d, Point3d, Transform, Vector3d, XAndY } from "@itwin/core-geometry"; import { Easing, GeometryStreamProps, NpcCenter } from "@itwin/core-common"; import { DialogItemValue, DialogPropertyItem, DialogPropertySyncItem } from "@itwin/appui-abstract"; @@ -23,7 +23,6 @@ import { OnViewExtentsError, ViewChangeOptions } from "../ViewAnimation"; import { DecorateContext, DynamicsContext } from "../ViewContext"; import { ScreenViewport, Viewport } from "../Viewport"; import { ViewStatus } from "../ViewStatus"; -import { IdleTool } from "./IdleTool"; import { PrimitiveTool } from "./PrimitiveTool"; import { BeButton, BeButtonEvent, BeButtonState, BeModifierKeys, BeTouchEvent, BeWheelEvent, CoordinateLockOverrides, CoordSource, EventHandled, @@ -310,17 +309,12 @@ export class ToolAdmin { private _suspendedByInputCollector?: SuspendedToolState; private _viewTool?: ViewTool; private _primitiveTool?: PrimitiveTool; - private _idleTool?: IdleTool; + private _idleTool?: InteractiveTool; private _inputCollector?: InputCollector; private _saveCursor?: string; private _saveLocateCircle = false; private _defaultToolId = "Select"; private _defaultToolArgs?: any[]; - /** - * The active settings that placement tools will use. - * @alpha - */ - public readonly activeSettings = new ToolAdmin.ActiveSettings(); /** The name of the [[PrimitiveTool]] to use as the default tool. Defaults to "Select", referring to [[SelectionTool]]. * @see [[startDefaultTool]] to activate the default tool. @@ -449,7 +443,7 @@ export class ToolAdmin { if (typeof document === "undefined") return; // if document isn't defined, we're probably running in a test environment. At any rate, we can't have interactive tools. - this._idleTool = IModelApp.tools.create("Idle") as IdleTool; + this._idleTool = IModelApp.tools.create("Idle") as InteractiveTool; ["keydown", "keyup"].forEach((type) => { document.addEventListener(type, ToolAdmin._keyEventHandler as EventListener, false); @@ -788,8 +782,13 @@ export class ToolAdmin { } /** The idleTool handles events that are not otherwise processed. */ - public get idleTool(): IdleTool { return this._idleTool!; } - public set idleTool(idleTool: IdleTool) { this._idleTool = idleTool; } + public get idleTool(): InteractiveTool { + assert(undefined !== this._idleTool); + return this._idleTool; + } + public set idleTool(idleTool: InteractiveTool) { + this._idleTool = idleTool; + } /** Return true to filter (ignore) events to the given viewport */ protected filterViewport(vp: ScreenViewport) { @@ -1886,23 +1885,3 @@ export class WheelEventProcessor { return status; } } - -/** - * @public - */ -export namespace ToolAdmin { // eslint-disable-line no-redeclare - - /** - * Active settings that placement tools will use. - * @alpha - */ - export class ActiveSettings { - - /** The active category */ - public category?: Id64String; - - /** The target model */ - public model?: Id64String; - } - -} diff --git a/core/geometry/CHANGELOG.json b/core/geometry/CHANGELOG.json index 03f8ac7ae523..2001c7fdb4f9 100644 --- a/core/geometry/CHANGELOG.json +++ b/core/geometry/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-geometry", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-geometry_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-geometry_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-geometry_v3.0.0", diff --git a/core/geometry/CHANGELOG.md b/core/geometry/CHANGELOG.md index 949f53898ecc..e06d04f07a5e 100644 --- a/core/geometry/CHANGELOG.md +++ b/core/geometry/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-geometry -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/geometry/package.json b/core/geometry/package.json index c4a3af2232f3..d18ccb89ce9f 100644 --- a/core/geometry/package.json +++ b/core/geometry/package.json @@ -1,13 +1,14 @@ { "name": "@itwin/core-geometry", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js Core Geometry library", "main": "lib/cjs/core-geometry.js", "module": "lib/esm/core-geometry.js", "typings": "lib/cjs/core-geometry", - "imodeljsSharedLibrary": true, "license": "MIT", - "sideEffects": false, + "sideEffects": [ + "./lib/esm/core-geometry.js" + ], "scripts": { "build": "npm run -s build:cjs", "build:ci": "npm run -s build && npm run -s build:esm", diff --git a/core/geometry/src/bspline/AkimaCurve3d.ts b/core/geometry/src/bspline/AkimaCurve3d.ts index cfbfd67b2ce7..395ce86c6f0e 100644 --- a/core/geometry/src/bspline/AkimaCurve3d.ts +++ b/core/geometry/src/bspline/AkimaCurve3d.ts @@ -154,26 +154,13 @@ private constructor(properties: AkimaCurve3dOptions, proxyCurve: CurvePrimitive) } return proxyOk; } - /** - * Return a transformed clone. - */ - public cloneTransformed(transform: Transform): GeometryQuery | undefined { - const myClone = this.clone(); - if (myClone && myClone?.tryTransformInPlace(transform)) - return myClone; - return undefined; - } - /** - * Return a clone. - */ - public clone(): GeometryQuery | undefined { - const proxyClone = this._proxyCurve.clone(); - if (proxyClone) { - return new AkimaCurve3d(this._options.clone (), proxyClone as CurvePrimitive); - } - return undefined; + + /** Return a deep clone */ + public override clone(): AkimaCurve3d { + return new AkimaCurve3d(this._options.clone(), this._proxyCurve.clone()); } -/** Test if `other` is also an [[AkimaCurve3d]] */ + + /** Test if `other` is also an [[AkimaCurve3d]] */ public isSameGeometryClass(other: GeometryQuery): boolean { return other instanceof AkimaCurve3d; } public override isAlmostEqual(other: GeometryQuery): boolean{ diff --git a/core/geometry/src/bspline/BSpline1dNd.ts b/core/geometry/src/bspline/BSpline1dNd.ts index 06666e354e7d..dfd60b99af9b 100644 --- a/core/geometry/src/bspline/BSpline1dNd.ts +++ b/core/geometry/src/bspline/BSpline1dNd.ts @@ -15,7 +15,7 @@ import { BSplineWrapMode, KnotVector } from "./KnotVector"; /** Bspline knots and poles for 1d-to-Nd. * * The "pole" (aka control point) of this class is a block of `poleLength` numbers. * * Derived classes (not this class) assign meaning such as x,y,z,w. - * * for instance, an instance of this class with `poleLength===3` does not know if its poles are x,y,z or weighed 2D x,y,w + * * for instance, an instance of this class with `poleLength===3` does not know if its poles are x,y,z or weighted 2D x,y,w * @public */ export class BSpline1dNd { @@ -34,7 +34,7 @@ export class BSpline1dNd { /** (property accessor) Return the number of poles*/ public get numPoles(): number { return this.packedData.length / this.poleLength; } /** copy 3 values of pole `i` into a point. - * * The calling clas sis responsible for knowing if this is an appropriate access to the blocked data. + * * The calling class is responsible for knowing if this is an appropriate access to the blocked data. */ public getPoint3dPole(i: number, result?: Point3d): Point3d | undefined { return Point3d.createFromPacked(this.packedData, i, result); } /** preallocated array (length === `order`) used as temporary in evaluations */ @@ -108,14 +108,14 @@ export class BSpline1dNd { * * Evaluate the basis functions and one derivative at spanIndex and fraction. * * Evaluations are stored in the preallocated `this.basisBuffer` * * Immediately do the summations of the basis values times the respective control points - * * Summations are stored in the preallocated `this.poleBuffer` and `this.poleBuffer` + * * Summations are stored in the preallocated `this.poleBuffer` and `this.poleBuffer1` * */ public evaluateBuffersInSpan1(spanIndex: number, spanFraction: number) { this.evaluateBasisFunctionsInSpan(spanIndex, spanFraction, this.basisBuffer, this.basisBuffer1); this.sumPoleBufferForSpan(spanIndex); this.sumPoleBuffer1ForSpan(spanIndex); } - /** sum poles at span `spanIndex` by the weights in the `poleBuffer` */ + /** sum poles in `poleBuffer` at span `spanIndex` by the weights in the `basisBuffer` */ public sumPoleBufferForSpan(spanIndex: number) { this.poleBuffer.fill(0); let k = spanIndex * this.poleLength; @@ -123,7 +123,7 @@ export class BSpline1dNd { for (let j = 0; j < this.poleLength; j++) { this.poleBuffer[j] += f * this.packedData[k++]; } } } - /** sum poles at span `spanIndex` by the weights in the `poleBuffer1`, i.e. form first derivatives */ + /** sum poles in `poleBuffer1` at span `spanIndex` by the weights in the `basisBuffer1`, i.e. form first derivatives */ public sumPoleBuffer1ForSpan(spanIndex: number) { this.poleBuffer1.fill(0); let k = spanIndex * this.poleLength; @@ -133,7 +133,7 @@ export class BSpline1dNd { } } } - /** sum poles at span `spanIndex` by the weights in the `poleBuffer2`, i.e. form second derivatives */ + /** sum poles in `poleBuffer2` at span `spanIndex` by the weights in the `basisBuffer2`, i.e. form second derivatives */ public sumPoleBuffer2ForSpan(spanIndex: number) { this.poleBuffer2.fill(0); let k = spanIndex * this.poleLength; @@ -208,4 +208,68 @@ export class BSpline1dNd { return false; } + + /** Insert knot and resulting pole into the instance, optionally multiple times. + * @param knot the knot to be inserted (may already exist in the KnotVector) + * @param totalMultiplicity the total multiplicity of the knot on return + */ + public addKnot(knot: number, totalMultiplicity: number): boolean { + if (knot < this.knots.leftKnot || knot > this.knots.rightKnot) + return false; // invalid input + let iLeftKnot = this.knots.knotToLeftKnotIndex(knot); + + // snap input if too close to an existing knot + if (Math.abs(knot - this.knots.knots[iLeftKnot]) < KnotVector.knotTolerance) { + knot = this.knots.knots[iLeftKnot]; // snap to left knot of bracket + } else if (Math.abs(knot - this.knots.knots[iLeftKnot + 1]) < KnotVector.knotTolerance) { + iLeftKnot += this.knots.getKnotMultiplicityAtIndex(iLeftKnot + 1); + if (iLeftKnot > this.knots.rightKnotIndex) + return true; // nothing to do + knot = this.knots.knots[iLeftKnot]; // snap to left knot of next bracket + } + const numKnotsToAdd = Math.min(totalMultiplicity, this.degree) - this.knots.getKnotMultiplicity(knot); + if (numKnotsToAdd <= 0) + return true; // nothing to do + + // working arrays and pole buffer + let currKnotCount = this.knots.knots.length; + const newKnots = new Float64Array(currKnotCount + numKnotsToAdd); + for (let i = 0; i < currKnotCount; ++i) + newKnots[i] = this.knots.knots[i]; + let currPoleCount = this.numPoles; + const newPackedData = new Float64Array(this.packedData.length + (numKnotsToAdd * this.poleLength)); + for (let i = 0; i < this.packedData.length; ++i) + newPackedData[i] = this.packedData[i]; + const dataBuf = new Float64Array(this.degree * this.poleLength); // holds degree poles + + // each iteration adds one knot and one pole to the working arrays (cf. Farin 4e) + for (let iter = 0; iter < numKnotsToAdd; ++iter) { + // fill the buffer with new poles obtained from control polygon corner cutting + let iBuf = 0; + const iStart = iLeftKnot - this.degree + 2; + for (let i = iStart; i < iStart + this.degree; ++i) { + const fraction = (knot - newKnots[i - 1]) / (newKnots[i + this.degree - 1] - newKnots[i - 1]); + for (let j = i * this.poleLength; j < (i + 1) * this.poleLength; ++j) { + dataBuf[iBuf++] = Geometry.interpolate(newPackedData[j - this.poleLength], fraction, newPackedData[j]); + } + } + + // overwrite degree-1 poles with degree new poles, shifting tail to the right by one + newPackedData.copyWithin((iStart + this.degree) * this.poleLength, (iStart + this.degree - 1) * this.poleLength, currPoleCount * this.poleLength); + let iData = iStart * this.poleLength; + for (const d of dataBuf) + newPackedData[iData++] = d; // overwrite degree new poles + + // add the knot to newKnots in position, shifting tail to the right by one + newKnots.copyWithin(iLeftKnot + 2, iLeftKnot + 1, currKnotCount); + newKnots[iLeftKnot + 1] = knot; + + ++iLeftKnot; + ++currKnotCount; + ++currPoleCount; + } + this.knots.setKnotsCapture(newKnots); + this.packedData = newPackedData; + return true; + } } diff --git a/core/geometry/src/bspline/BSplineCurve.ts b/core/geometry/src/bspline/BSplineCurve.ts index 039d01011695..b22b6c69b73c 100644 --- a/core/geometry/src/bspline/BSplineCurve.ts +++ b/core/geometry/src/bspline/BSplineCurve.ts @@ -239,6 +239,52 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { } return result; } + + /** Return a deep clone. */ + public abstract override clone(): BSplineCurve3dBase; + + /** Return a transformed deep clone. */ + public override cloneTransformed(transform: Transform): BSplineCurve3dBase { + const curve1 = this.clone(); + curve1.tryTransformInPlace(transform); + return curve1; + } + + /** Return a curve primitive which is a portion of this curve. + * @param fractionA [in] start fraction + * @param fractionB [in] end fraction + */ + public override clonePartialCurve(fractionA: number, fractionB: number): BSplineCurve3dBase { + const clone = this.clone(); + const origNumKnots = clone._bcurve.knots.knots.length; + let knotA = clone._bcurve.knots.fractionToKnot(fractionA); + let knotB = clone._bcurve.knots.fractionToKnot(fractionB); + clone._bcurve.addKnot(knotA, clone.degree); + clone._bcurve.addKnot(knotB, clone.degree); + + if (origNumKnots === clone._bcurve.knots.knots.length) + return clone; // full curve + if (knotA > knotB) { + const tmp = knotA; knotA = knotB; knotB = tmp; + } + + // choose first/last knot and pole such that knotA/knotB has degree multiplicity in the new knot sequence + const iStartKnot = clone._bcurve.knots.knotToLeftKnotIndex(knotA) - clone.degree + 1; + const iStartPole = iStartKnot * clone._bcurve.poleLength; + const iLastKnot = clone._bcurve.knots.knotToLeftKnotIndex(knotB); + let iLastKnotLeftMultiple = iLastKnot - clone._bcurve.knots.getKnotMultiplicityAtIndex(iLastKnot) + 1; + if (clone._bcurve.knots.knots[iLastKnot] < knotB) + iLastKnotLeftMultiple = iLastKnot + 1; + const iEndPole = (iLastKnotLeftMultiple + 1) * clone._bcurve.poleLength; // one past last pole + const iEndKnot = iLastKnotLeftMultiple + clone.degree; // one past last knot + + // trim the arrays (leave knots unnormalized!) + clone._bcurve.knots.setKnotsCapture(clone._bcurve.knots.knots.slice(iStartKnot, iEndKnot)); + clone._bcurve.packedData = clone._bcurve.packedData.slice(iStartPole, iEndPole); + clone.setWrappable(BSplineWrapMode.None); // always open + return clone; + } + /** Implement `CurvePrimitive.appendPlaneIntersections` * @param plane A plane (e.g. specific type Plane3dByOriginAndUnitNormal or Point4d) * @param result growing array of plane intersections @@ -383,7 +429,7 @@ export class BSplineCurve3d extends BSplineCurve3dBase { } /** Create a smoothly closed B-spline curve with uniform knots. - * Note that the curve does not start at the first pole. + * Note that the curve does not start at the first pole, and first and last poles should be distinct. */ public static createPeriodicUniformKnots(poles: Point3d[] | Float64Array | GrowableXYZArray, order: number): BSplineCurve3d | undefined { const numPoles = poles instanceof Float64Array ? poles.length / 3 : poles.length; @@ -463,18 +509,13 @@ export class BSplineCurve3d extends BSplineCurve3dBase { return curve; } /** Return a deep clone */ - public clone(): BSplineCurve3d { + public override clone(): BSplineCurve3d { const knotVector1 = this._bcurve.knots.clone(); const curve1 = new BSplineCurve3d(this.numPoles, this.order, knotVector1); curve1._bcurve.packedData = this._bcurve.packedData.slice(); return curve1; } - /** Return a transformed deep clone. */ - public cloneTransformed(transform: Transform): BSplineCurve3d { - const curve1 = this.clone(); - curve1.tryTransformInPlace(transform); - return curve1; - } + /** Evaluate at a position given by fractional position within a span. */ public evaluatePointInSpan(spanIndex: number, spanFraction: number): Point3d { this._bcurve.evaluateBuffersInSpan(spanIndex, spanFraction); @@ -514,33 +555,7 @@ export class BSplineCurve3d extends BSplineCurve3dBase { this._bcurve.poleBuffer1[0], this._bcurve.poleBuffer1[1], this._bcurve.poleBuffer1[2], this._bcurve.poleBuffer2[0], this._bcurve.poleBuffer2[1], this._bcurve.poleBuffer2[2], result); } - /** Evaluate the curve point at a fractional of the entire knot range. */ - public override fractionToPoint(fraction: number, result?: Point3d): Point3d { - return this.knotToPoint(this._bcurve.knots.fractionToKnot(fraction), result); - } - - /** Evaluate the curve point at a fractional of the entire knot range. */ - public override fractionToPointAndDerivative(fraction: number, result?: Ray3d): Ray3d { - const knot = this._bcurve.knots.fractionToKnot(fraction); - result = this.knotToPointAndDerivative(knot, result); - result.direction.scaleInPlace(this._bcurve.knots.knotLength01); - return result; - } - /** Construct a plane with - * * origin at the fractional position along the arc - * * x axis is the first derivative, i.e. tangent along the arc - * * y axis is the second derivative, i.e. in the plane and on the center side of the tangent. - * If the arc is circular, the second derivative is directly towards the center - */ - public override fractionToPointAnd2Derivatives(fraction: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { - const knot = this._bcurve.knots.fractionToKnot(fraction); - result = this.knotToPointAnd2Derivatives(knot, result); - const a = this._bcurve.knots.knotLength01; - result.vectorU.scaleInPlace(a); - result.vectorV.scaleInPlace(a * a); - return result; - } /** test if almost the same curve as `other` */ public override isAlmostEqual(other: any): boolean { if (other instanceof BSplineCurve3d) { diff --git a/core/geometry/src/bspline/BSplineCurve3dH.ts b/core/geometry/src/bspline/BSplineCurve3dH.ts index 4097de723195..5abba4ad45cf 100644 --- a/core/geometry/src/bspline/BSplineCurve3dH.ts +++ b/core/geometry/src/bspline/BSplineCurve3dH.ts @@ -218,18 +218,13 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { return undefined; } /** Return a deep clone of this curve. */ - public clone(): BSplineCurve3dH { + public override clone(): BSplineCurve3dH { const knotVector1 = this._bcurve.knots.clone(); const curve1 = new BSplineCurve3dH(this.numPoles, this.order, knotVector1); curve1._bcurve.packedData = this._bcurve.packedData.slice(); return curve1; } - /** Clone the curve and apply a transform to the clone. */ - public cloneTransformed(transform: Transform): BSplineCurve3dH { - const curve1 = this.clone(); - curve1.tryTransformInPlace(transform); - return curve1; - } + /** Evaluate at a position given by fractional position within a span. */ public evaluatePointInSpan(spanIndex: number, spanFraction: number, result?: Point3d): Point3d { this._bcurve.evaluateBuffersInSpan(spanIndex, spanFraction); diff --git a/core/geometry/src/bspline/BSplineCurveOps.ts b/core/geometry/src/bspline/BSplineCurveOps.ts index 1dc14b8e5171..7270b5142c47 100644 --- a/core/geometry/src/bspline/BSplineCurveOps.ts +++ b/core/geometry/src/bspline/BSplineCurveOps.ts @@ -116,15 +116,13 @@ export namespace BSplineCurveOps { knots = undefined; return false; } - const myKnots = KnotVector.create(knots, 1, false); - if (myKnots.knotLength01 < KnotVector.knotTolerance) { + const myKnots = KnotVector.create(knots, 1, false); // no extra knots at start/end + if (!myKnots.normalize()) { knots = undefined; return false; } - for (let i = 0; i < myKnots.numSpans; ++i) { - knots[i] = myKnots.spanFractionToFraction(i, 0.0); - } - knots[knots.length - 1] = 1.0; + for (let i = 0; i < knots.length; ++i) + knots[i] = myKnots.knots[i]; return true; } diff --git a/core/geometry/src/bspline/Bezier1dNd.ts b/core/geometry/src/bspline/Bezier1dNd.ts index b6386343787e..8ca8f42d8310 100644 --- a/core/geometry/src/bspline/Bezier1dNd.ts +++ b/core/geometry/src/bspline/Bezier1dNd.ts @@ -173,7 +173,7 @@ export class Bezier1dNd { } } } - // + /** * interpolate at `fraction` between poleA and poleB. * * Data is left "in place" in poleIndexA @@ -189,14 +189,13 @@ export class Bezier1dNd { data[i0] += fraction * (data[i1] - data[i0]); } } - private static _knotTolerance = 1.0e-8; + /** * Compute new control points to "clamp" bspline unsaturated support to saturated form. * * At input time, the control points are associated with the input knots (unsaturated) - * * At output, they control points are modified by repeated knot insertion to be fully clamped. + * * At output, the control points are modified by repeated knot insertion to be fully clamped. * @param knots knot values for the current (unsaturated) pole set * @param spanIndex index of span whose (unsaturated) poles are in the bezier. - * @param optional function for `setInterval (knotA, knotB)` call to announce knot limits. */ public saturateInPlace(knots: KnotVector, spanIndex: number): boolean { const degree = knots.degree; @@ -208,7 +207,7 @@ export class Bezier1dNd { const knotA = knotArray[kA]; const knotB = knotArray[kB]; this.setInterval(knotA, knotB); - if (knotB <= knotA + Bezier1dNd._knotTolerance) + if (knotB <= knotA + KnotVector.knotTolerance) return false; for (let numInsert = degree - 1; numInsert > 0; numInsert--) { // left numInsert poles are pulled forward @@ -238,12 +237,11 @@ export class Bezier1dNd { } /** * Saturate a univariate bspline coefficient array in place - * * On input, the array is the coefficients one span of a bspline, packed in an array of `(knots.order)` values. + * * On input, the array is the coefficients of one span of a bspline, packed in an array of `(knots.order)` values. * * These are modified in place, and on return are a bezier for the same knot interval. * @param coffs input as bspline coefficients, returned as bezier coefficients * @param knots knot vector * @param spanIndex index of span whose (unsaturated) poles are in the coefficients. - * @param optional function for `setInterval (knotA, knotB)` call to announce knot limits. */ public static saturate1dInPlace(coffs: Float64Array, knots: KnotVector, spanIndex: number): boolean { const degree = knots.degree; @@ -254,6 +252,8 @@ export class Bezier1dNd { const knotArray = knots.knots; const knotA = knotArray[kA]; const knotB = knotArray[kB]; + if (knotB <= knotA + KnotVector.knotTolerance) + return false; for (let numInsert = degree - 1; numInsert > 0; numInsert--) { // left numInsert poles are pulled forward let k0 = kA - numInsert; @@ -273,7 +273,7 @@ export class Bezier1dNd { if (knotArray[k2] > knotB) { for (let i = 0; i < numInsert; i++ , k2--) { const knot2 = knotArray[k2]; // right side of moving window - // left side of window ia always the (previously saturated) knotA + // left side of window is always the (previously saturated) knotA const fraction = (knotB - knot2) / (knotA - knot2); k = degree - i; coffs[k] += fraction * (coffs[k - 1] - coffs[k]); @@ -283,9 +283,9 @@ export class Bezier1dNd { return true; } /** - * Apply deCasteljou interpolations to isolate a smaller bezier polygon, representing interval 0..fraction of the original + * Apply deCasteljau interpolations to isolate a smaller bezier polygon, representing interval 0..fraction of the original * @param fraction "end" fraction for split. - * @returns false if fraction is 0 -- no changes applied. + * @returns false if fraction is 0 or 1 -- no changes applied. */ public subdivideInPlaceKeepLeft(fraction: number): boolean { if (Geometry.isAlmostEqualNumber(fraction, 1.0)) @@ -303,9 +303,9 @@ export class Bezier1dNd { } /** - * Apply deCasteljou interpolations to isolate a smaller bezier polygon, representing interval 0..fraction of the original - * @param fraction "end" fraction for split. - * @returns false if fraction is 0 -- no changes applied. + * Apply deCasteljau interpolations to isolate a smaller bezier polygon, representing interval fraction..1 of the original + * @param fraction "start" fraction for split. + * @returns false if fraction is 0 or 1 -- no changes applied. */ public subdivideInPlaceKeepRight(fraction: number): boolean { if (Geometry.isAlmostEqualNumber(fraction, 0.0)) @@ -323,7 +323,7 @@ export class Bezier1dNd { /** * Saturate a univariate bspline coefficient array in place * @param fraction0 fraction for first split. This is the start of the output polygon - * @param fraction1 fraction for first split. This is the start of the output polygon + * @param fraction1 fraction for second split. This is the end of the output polygon * @return false if fractions are (almost) identical. */ public subdivideToIntervalInPlace(fraction0: number, fraction1: number): boolean { diff --git a/core/geometry/src/bspline/BezierCurve3d.ts b/core/geometry/src/bspline/BezierCurve3d.ts index 719a997a2e85..f051c5b89802 100644 --- a/core/geometry/src/bspline/BezierCurve3d.ts +++ b/core/geometry/src/bspline/BezierCurve3d.ts @@ -110,24 +110,9 @@ export class BezierCurve3d extends BezierCurveBase { this._polygon.loadSpanPoles(data, spanIndex); } /** Clone as a bezier 3d. */ - public clone(): BezierCurve3d { + public override clone(): BezierCurve3d { return new BezierCurve3d(this._polygon.clonePolygon()); } - /** Clone the interval from f0 to f1. */ - public override clonePartialCurve(f0: number, f1: number): BezierCurve3d | undefined { - const partialCurve = new BezierCurve3d(this._polygon.clonePolygon()); - partialCurve._polygon.subdivideToIntervalInPlace(f0, f1); - return partialCurve; - } - - /** - * Return a curve after transform. - */ - public cloneTransformed(transform: Transform): BezierCurve3d { - const curve1 = this.clone(); - curve1.tryTransformInPlace(transform); - return curve1; - } /** Return a (de-weighted) point on the curve. If de-weight fails, returns 000 */ public fractionToPoint(fraction: number, result?: Point3d): Point3d { this._polygon.evaluate(fraction, this._workData0); diff --git a/core/geometry/src/bspline/BezierCurve3dH.ts b/core/geometry/src/bspline/BezierCurve3dH.ts index 773d58ffeff8..fd92e5c3e4db 100644 --- a/core/geometry/src/bspline/BezierCurve3dH.ts +++ b/core/geometry/src/bspline/BezierCurve3dH.ts @@ -145,17 +145,9 @@ export class BezierCurve3dH extends BezierCurveBase { this._polygon.loadSpanPoles(data, spanIndex); } /** Clone the entire curve. */ - public clone(): BezierCurve3dH { + public override clone(): BezierCurve3dH { return new BezierCurve3dH(this._polygon.clonePolygon()); } - /** - * Return a curve after transform. - */ - public cloneTransformed(transform: Transform): BezierCurve3dH { - const curve1 = this.clone(); - curve1.tryTransformInPlace(transform); - return curve1; - } /** Return a (deweighted) point on the curve. If deweight fails, returns 000 */ public fractionToPoint(fraction: number, result?: Point3d): Point3d { this._polygon.evaluate(fraction, this._workData0); diff --git a/core/geometry/src/bspline/BezierCurveBase.ts b/core/geometry/src/bspline/BezierCurveBase.ts index 05de708fc1c8..891b08d52756 100644 --- a/core/geometry/src/bspline/BezierCurveBase.ts +++ b/core/geometry/src/bspline/BezierCurveBase.ts @@ -246,6 +246,16 @@ export abstract class BezierCurveBase extends CurvePrimitive { return numStrokes; } + /** Return a deep clone. */ + public abstract override clone(): BezierCurveBase; + + /** Return a transformed deep clone. */ + public override cloneTransformed(transform: Transform): BezierCurveBase { + const curve1 = this.clone(); + curve1.tryTransformInPlace(transform); + return curve1; + } + /** * Construct an offset of the instance curve as viewed in the xy-plane (ignoring z). * * No attempt is made to join the offsets of smaller constituent primitives. To construct a fully joined offset @@ -258,4 +268,14 @@ export abstract class BezierCurveBase extends CurvePrimitive { this.emitStrokableParts(handler, options.strokeOptions); return handler.claimResult(); } + + /** Return a curve primitive which is a portion of this curve. + * @param fractionA [in] start fraction + * @param fractionB [in] end fraction + */ + public override clonePartialCurve(fractionA: number, fractionB: number): BezierCurveBase { + const partialCurve = this.clone(); + partialCurve._polygon.subdivideToIntervalInPlace(fractionA, fractionB); + return partialCurve; + } } diff --git a/core/geometry/src/bspline/InterpolationCurve3d.ts b/core/geometry/src/bspline/InterpolationCurve3d.ts index 8a762ff82976..806a3c9d693c 100644 --- a/core/geometry/src/bspline/InterpolationCurve3d.ts +++ b/core/geometry/src/bspline/InterpolationCurve3d.ts @@ -317,31 +317,19 @@ export class InterpolationCurve3d extends ProxyCurve { } return proxyOk; } - /** - * Return a transformed clone. - */ - public cloneTransformed(transform: Transform): GeometryQuery | undefined { - const myClone = this.clone(); - if (myClone && myClone?.tryTransformInPlace(transform)) - return myClone; - return undefined; - } - /** - * Return a clone. - */ - public clone(): GeometryQuery | undefined { - const proxyClone = this._proxyCurve.clone(); - if (proxyClone) { - return new InterpolationCurve3d(this._options.clone(), proxyClone as CurvePrimitive); - } - return undefined; + + /** Return a deep clone */ + public override clone(): InterpolationCurve3d { + return new InterpolationCurve3d(this._options.clone(), this._proxyCurve.clone()); } + public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof InterpolationCurve3d) { return InterpolationCurve3dOptions.areAlmostEqual(this._options, other._options); } return false; } + /** Test if `other` is also an [[InterpolationCurve3d]] */ public isSameGeometryClass(other: GeometryQuery): boolean { return other instanceof InterpolationCurve3d; } diff --git a/core/geometry/src/bspline/KnotVector.ts b/core/geometry/src/bspline/KnotVector.ts index 125f55229608..0bf6c0b9cb87 100644 --- a/core/geometry/src/bspline/KnotVector.ts +++ b/core/geometry/src/bspline/KnotVector.ts @@ -35,7 +35,7 @@ export enum BSplineWrapMode { /** * Array of non-decreasing numbers acting as a knot array for bsplines. * - * * Essential identity: numKnots = numPoles + order = numPoles + degree - 1 + * * Essential identity: numKnots = numPoles + order - 2 = numPoles + degree - 1 * * Various bspline libraries have confusion over how many "end knots" are needed. "Many" libraries (including MicroStation) * incorrectly demand "order" knots at each end for clamping. But only "order - 1" are really needed. * * This class uses the "order-1" convention. @@ -43,7 +43,7 @@ export enum BSplineWrapMode { * * A span is a single interval of the knots. * * The left knot of span {k} is knot {k+degree-1} * * This class provides queries to convert among spanFraction, fraction of knot range, and knot - * * core computations (evaluateBasisFunctions) have leftKnotIndex and global knot value as inputs. Caller's need to + * * core computations (evaluateBasisFunctions) have leftKnotIndex and global knot value as inputs. Callers need to * know their primary values (global knot, spanFraction). * @public */ @@ -148,6 +148,61 @@ export class KnotVector { if (this.degree !== other.degree) return false; return NumberArray.isAlmostEqual(this.knots, other.knots, KnotVector.knotTolerance); } + + /** Compute the multiplicity of the input knot, or zero if not a knot. */ + public getKnotMultiplicity(knot: number): number { + let m = 0; + for (const k of this.knots) { + if (Math.abs(k - knot) < KnotVector.knotTolerance) + ++m; + else if (knot < k) + break; + } + return m; + } + + /** Compute the multiplicity of the knot at the given index. */ + public getKnotMultiplicityAtIndex(knotIndex: number): number { + let m = 0; + if (knotIndex >= 0 && knotIndex < this.knots.length) { + const knot = this.knots[knotIndex]; + ++m; // count this knot + for (let i = knotIndex - 1; i >= 0; --i) { + const k = this.knots[i]; + if (Math.abs(k - knot) < KnotVector.knotTolerance) + ++m; // found multiple to left of knot + else if (knot > k) + break; + } + for (let i = knotIndex + 1; i < this.knots.length; ++i) { + const k = this.knots[i]; + if (Math.abs(k - knot) < KnotVector.knotTolerance) + ++m; // found multiple to right of knot + else if (knot < k) + break; + } + } + return m; + } + + /** Transform knots to span [0,1]. + * @returns false if and only if this.knotLength01 is trivial + */ + public normalize(): boolean { + if (this.knotLength01 < KnotVector.knotTolerance) + return false; + const divisor = 1.0 / this.knotLength01; + const leftKnot = this.leftKnot; + for (let i = 0; i < this.knots.length; ++i) + this.knots[i] = (this.knots[i] - leftKnot) * divisor; + // explicitly set rightKnot and its multiples to 1.0 to avoid round-off + for (let i = this.rightKnotIndex - 1; i > this.leftKnotIndex && (this.knots[i] === this.knots[this.rightKnotIndex]); --i) this.knots[i] = 1.0; + for (let i = this.rightKnotIndex + 1; i < this.knots.length && (this.knots[i] === this.knots[this.rightKnotIndex]); ++i) this.knots[i] = 1.0; + this.knots[this.rightKnotIndex] = 1.0; + this.setupFixedValues(); + return true; + } + /** install knot values from an array, optionally ignoring first and last. */ public setKnots(knots: number[] | Float64Array, skipFirstAndLast?: boolean) { @@ -164,6 +219,13 @@ export class KnotVector { } this.setupFixedValues(); } + + /** install knot values from an array, optionally ignoring first and last. */ + public setKnotsCapture(knots: Float64Array) { + this.knots = knots; + this.setupFixedValues(); + } + /** * Create knot vector with {degree-1} replicated knots at start and end, and uniform knots between. * @param numPoles Number of poles @@ -203,7 +265,7 @@ export class KnotVector { * Create knot vector with given knot values and degree. * @param knotArray knot values * @param degree degree of polynomial - * @param skipFirstAndLast true to skip class overclamped end knots. + * @param skipFirstAndLast true to skip copying the first and last knot values. */ public static create(knotArray: number[] | Float64Array, degree: number, skipFirstAndLast?: boolean): KnotVector { const numAllocate = skipFirstAndLast ? knotArray.length - 2 : knotArray.length; @@ -213,13 +275,13 @@ export class KnotVector { } /** - * Return the average of degree consecutive knots beginning at spanIndex. + * Return the average of degree consecutive knots beginning at knotIndex. */ - public grevilleKnot(spanIndex: number): number { - if (spanIndex < 0) return this.leftKnot; - if (spanIndex > this.rightKnotIndex) return this.rightKnot; + public grevilleKnot(knotIndex: number): number { + if (knotIndex < 0) return this.leftKnot; + if (knotIndex > this.rightKnotIndex) return this.rightKnot; let sum = 0.0; - for (let i = spanIndex; i < spanIndex + this.degree; i++) + for (let i = knotIndex; i < knotIndex + this.degree; i++) sum += this.knots[i]; return sum / this.degree; } @@ -248,7 +310,7 @@ export class KnotVector { * Evaluate basis functions f[] at knot value u. * * @param u knot value for evaluation - * @param f array of basis values. ASSUMED PROPER LENGTH + * @param f array of order basis function values */ public evaluateBasisFunctions(knotIndex0: number, u: number, f: Float64Array) { f[0] = 1.0; @@ -278,10 +340,12 @@ export class KnotVector { } /** - * Evaluate basis fucntions f[] at knot value u. + * Evaluate basis functions f[], derivatives df[], and optional second derivatives ddf[] at knot value u. * * @param u knot value for evaluation - * @param f array of basis values. ASSUMED PROPER LENGTH + * @param f array of order basis function values + * @param df array of order basis derivative values + * @param ddf array of order basis second derivative values */ public evaluateBasisFunctions1(knotIndex0: number, u: number, f: Float64Array, df: Float64Array, ddf?: Float64Array) { f[0] = 1.0; df[0] = 0.0; @@ -341,18 +405,21 @@ export class KnotVector { ddf[depth + 1] = ddgCarry; } } - /** Return the (highest) index of the knot less than or equal to u */ + /** Find the knot span bracketing knots[i] <= u < knots[i+1] and return i. + * * If u has no such bracket, return the smaller index of the closest nontrivial bracket. + * @param u value to bracket + */ public knotToLeftKnotIndex(u: number): number { - // Anything to left is in the first span . . - const firstLeftKnot = this.degree - 1; - if (u < this.knots[firstLeftKnot + 1]) return firstLeftKnot; - // Anything to right is in the last span ... - const lastLeftKnot = this.knots.length - this.degree - 1; - if (u >= this.knots.length - this.degree) return this.knots[lastLeftKnot]; - // ugh ... linear search ... - for (let i = firstLeftKnot + 1; i < lastLeftKnot; i++) - if (u < this.knots[i + 1]) return i; // testing against right side skips over multiple knot cases??? - return lastLeftKnot; + for (let i = this.leftKnotIndex; i < this.rightKnotIndex; ++i) { + if (u < this.knots[i + 1]) + return i; + } + // for u >= rightKnot, return left index of last nontrivial span + for (let i = this.rightKnotIndex; i > this.leftKnotIndex; --i) { + if (this.knots[i] - this.knots[i - 1] >= KnotVector.knotTolerance) + return i - 1; + } + return this.rightKnotIndex - 1; // shouldn't get here } /** * Given a span index, return the index of the knot at its left. @@ -361,7 +428,7 @@ export class KnotVector { public spanIndexToLeftKnotIndex(spanIndex: number): number { const d = this.degree; if (spanIndex <= 0.0) return d - 1; - return Math.min(spanIndex + d - 1, this.knots.length - d); + return Math.min(spanIndex + d - 1, this.knots.length - d - 1); } /** Return the knot interval length of indexed bezier span. */ public spanIndexToSpanLength(spanIndex: number): number { @@ -374,7 +441,7 @@ export class KnotVector { * @param spanIndex index of span to test. */ public isIndexOfRealSpan(spanIndex: number): boolean { - if (spanIndex >= 0 && spanIndex < this.knots.length - this.degree) + if (spanIndex >= 0 && spanIndex < this.numSpans) return !Geometry.isSmallMetricDistance(this.spanIndexToSpanLength(spanIndex)); return false; } diff --git a/core/geometry/src/curve/Arc3d.ts b/core/geometry/src/curve/Arc3d.ts index b48ecb261bc8..c630b1bff54f 100644 --- a/core/geometry/src/curve/Arc3d.ts +++ b/core/geometry/src/curve/Arc3d.ts @@ -124,7 +124,7 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * Return a clone of the arc, with transform applied * @param transform */ - public cloneTransformed(transform: Transform): CurvePrimitive { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): Arc3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -883,15 +883,13 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param fractionA [in] start fraction * @param fractionB [in] end fraction */ - public override clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined { + public override clonePartialCurve(fractionA: number, fractionB: number): Arc3d { if (fractionB < fractionA) { const arcA = this.clonePartialCurve(fractionB, fractionA); - if (arcA) - arcA.reverseInPlace(); + arcA.reverseInPlace(); return arcA; } const arcB = this.clone(); - arcB.sweep.setStartEndRadians( this.sweep.fractionToRadians(fractionA), this.sweep.fractionToRadians(fractionB)); diff --git a/core/geometry/src/curve/CurveChainWithDistanceIndex.ts b/core/geometry/src/curve/CurveChainWithDistanceIndex.ts index e6a9fece067f..23d8f7bb0ef5 100644 --- a/core/geometry/src/curve/CurveChainWithDistanceIndex.ts +++ b/core/geometry/src/curve/CurveChainWithDistanceIndex.ts @@ -198,15 +198,15 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { super(); this._path = path; this._fragments = fragments; - this._totalLength = fragments[fragments.length - 1].chainDistance1; + this._totalLength = fragments.length > 0 ? fragments[fragments.length - 1].chainDistance1 : 0; } /** * Create a clone, transformed and with its own distance index. * @param transform transform to apply in the clone. */ - public cloneTransformed(transform: Transform): CurvePrimitive | undefined { + public cloneTransformed(transform: Transform): CurveChainWithDistanceIndex | undefined { const c = this._path.clone(); - if (c !== undefined && c instanceof CurveChain && c.tryTransformInPlace(transform)) + if (c instanceof CurveChain && c.tryTransformInPlace(transform)) return CurveChainWithDistanceIndex.createCapture(c); return undefined; } @@ -216,11 +216,9 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { public get path(): CurveChain { return this._path; } /** Return a deep clone */ - public clone(): CurvePrimitive | undefined { - const c = this._path.clone(); - if (c !== undefined && c instanceof CurveChain) - return CurveChainWithDistanceIndex.createCapture(c); - return undefined; + public clone(): CurveChainWithDistanceIndex { + const c = this._path.clone() as CurveChain; + return CurveChainWithDistanceIndex.createCapture(c); } /** Ask if the curve is within tolerance of a plane. * @returns Returns true if the curve is completely within tolerance of the plane. @@ -325,9 +323,7 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * Capture (not clone) a path into a new `CurveChainWithDistanceIndex` * @param primitives primitive array to be CAPTURED (not cloned) */ - public static createCapture(path: CurveChain, options?: StrokeOptions): CurveChainWithDistanceIndex | undefined { - if (path.children.length === 0) - return undefined; + public static createCapture(path: CurveChain, options?: StrokeOptions): CurveChainWithDistanceIndex { const fragments = DistanceIndexConstructionContext.createPathFragmentIndex(path, options); const result = new CurveChainWithDistanceIndex(path, fragments); return result; diff --git a/core/geometry/src/curve/CurveCollection.ts b/core/geometry/src/curve/CurveCollection.ts index 94cf52500404..271866fdb9c2 100644 --- a/core/geometry/src/curve/CurveCollection.ts +++ b/core/geometry/src/curve/CurveCollection.ts @@ -88,15 +88,15 @@ export abstract class CurveCollection extends GeometryQuery { /** Apply transform recursively to children */ public tryTransformInPlace(transform: Transform): boolean { return TransformInPlaceContext.tryTransformInPlace(this, transform); } /** Return a deep copy. */ - public clone(): CurveCollection | undefined { - return CloneCurvesContext.clone(this); + public override clone(): CurveCollection { + return CloneCurvesContext.clone(this) as CurveCollection; } /** Create a deep copy of transformed curves. */ - public cloneTransformed(transform: Transform): CurveCollection | undefined { + public override cloneTransformed(transform: Transform): CurveCollection | undefined { return CloneCurvesContext.clone(this, transform); } /** Create a deep copy with all linestrings expanded to multiple LineSegment3d. */ - public cloneWithExpandedLineStrings(): CurveCollection | undefined { + public cloneWithExpandedLineStrings(): CurveCollection { return CloneWithExpandedLineStrings.clone(this); } /** Recurse through children to collect CurvePrimitive's in flat array. */ diff --git a/core/geometry/src/curve/CurveCurveIntersectXY.ts b/core/geometry/src/curve/CurveCurveIntersectXY.ts index 9fab5b04f21a..c4685a110aeb 100644 --- a/core/geometry/src/curve/CurveCurveIntersectXY.ts +++ b/core/geometry/src/curve/CurveCurveIntersectXY.ts @@ -719,9 +719,9 @@ export class CurveCurveIntersectXY extends NullGeometryHandler { const strokeCountA = bezierSpanA[a].computeStrokeCountForOptions(); const strokeCountB = bezierSpanB[b].computeStrokeCountForOptions(); if (strokeCountA < strokeCountB) - this.dispatchBezierBezierStrokeFirst(bezierSpanA[a], bcurveA, strokeCountA, bezierSpanB[b], bcurveB, strokeCountB, univariateCoffsB, !_reversed); + this.dispatchBezierBezierStrokeFirst(bezierSpanA[a], bcurveA, strokeCountA, bezierSpanB[b], bcurveB, strokeCountB, univariateCoffsB, _reversed); else - this.dispatchBezierBezierStrokeFirst(bezierSpanB[b], bcurveB, strokeCountB, bezierSpanA[a], bcurveA, strokeCountA, univariateCoffsA, _reversed); + this.dispatchBezierBezierStrokeFirst(bezierSpanB[b], bcurveB, strokeCountB, bezierSpanA[a], bcurveA, strokeCountA, univariateCoffsA, !_reversed); } } } diff --git a/core/geometry/src/curve/CurvePrimitive.ts b/core/geometry/src/curve/CurvePrimitive.ts index 5f5a7868fb59..559761b681c0 100644 --- a/core/geometry/src/curve/CurvePrimitive.ts +++ b/core/geometry/src/curve/CurvePrimitive.ts @@ -414,6 +414,12 @@ export abstract class CurvePrimitive extends GeometryQuery { return false; } + /** Return a deep clone. */ + public abstract override clone(): CurvePrimitive; + + /** Return a transformed deep clone. */ + public abstract override cloneTransformed(transform: Transform): CurvePrimitive | undefined; + /** Return (if possible) a curve primitive which is a portion of this curve. * @param _fractionA [in] start fraction * @param _fractionB [in] end fraction diff --git a/core/geometry/src/curve/LineSegment3d.ts b/core/geometry/src/curve/LineSegment3d.ts index f3b137174f43..7a51b8d58b77 100644 --- a/core/geometry/src/curve/LineSegment3d.ts +++ b/core/geometry/src/curve/LineSegment3d.ts @@ -105,7 +105,7 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { /** Clone the LineSegment3d */ public clone(): LineSegment3d { return LineSegment3d.create(this._point0, this._point1); } /** Clone and apply transform to the clone. */ - public cloneTransformed(transform: Transform): CurvePrimitive { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): LineSegment3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -323,7 +323,7 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { * @param fractionA [in] start fraction * @param fractionB [in] end fraction */ - public override clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined { + public override clonePartialCurve(fractionA: number, fractionB: number): LineSegment3d { return LineSegment3d.create(this.fractionToPoint(fractionA), this.fractionToPoint(fractionB)); } diff --git a/core/geometry/src/curve/LineString3d.ts b/core/geometry/src/curve/LineString3d.ts index 0e08c3eb2f9a..8d43a4298f6b 100644 --- a/core/geometry/src/curve/LineString3d.ts +++ b/core/geometry/src/curve/LineString3d.ts @@ -135,7 +135,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { this._points = new GrowableXYZArray(); } /** Clone this linestring and apply the transform to the clone points. */ - public cloneTransformed(transform: Transform): CurvePrimitive { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): LineString3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -1141,19 +1141,19 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { } if (index < 0) index = 0; - if (index >= n) { - index = n - 1; + if (index > n - 2) { + index = n - 2; fraction += 1; } this._points.interpolate(index, fraction, index + 1, LineString3d._indexPoint); dest.push(LineString3d._indexPoint); } - /** Return (if possible) a LineString which is a portion of this curve. - * * This implementation does NOT extrapolate the linestring -- fractions are capped at 0 and 1. + /** Return a LineString which is a portion of this curve. + * * Fractions outside [0,1] extend the relevant end segment. * @param fractionA [in] start fraction * @param fractionB [in] end fraction */ - public override clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined { + public override clonePartialCurve(fractionA: number, fractionB: number): LineString3d { if (fractionB < fractionA) { const linestringA = this.clonePartialCurve(fractionB, fractionA); if (linestringA) @@ -1161,28 +1161,54 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { return linestringA; } const n = this._points.length; + if (n < 2) + return this.clone(); + if (n > 2 && this.isPhysicallyClosed) { + // don't extend a closed linestring + if (fractionA < 0) + fractionA = 0; + if (fractionB > 1) + fractionB = 1; + } const numEdge = n - 1; - if (n < 2 || fractionA >= 1.0 || fractionB <= 0.0) - return undefined; - if (fractionA < 0) - fractionA = 0; - if (fractionB > 1) - fractionB = 1; - const gA = fractionA * numEdge; - const gB = fractionB * numEdge; - const indexA = Math.floor(gA); - const indexB = Math.floor(gB); - const localFractionA = gA - indexA; - const localFractionB = gB - indexB; + let indexA: number; // left index of first extended/partial segment of clone + let indexB: number; // left index of last extended/partial segment of clone + let index0, index1: number; // range of original vertices to copy into clone + let localFractionA = fractionA; + let localFractionB = fractionB; + if (fractionA < 0) { + indexA = 0; + index0 = 1; // first original vertex is not in clone + } else if (0 <= fractionA && fractionA <= 1) { + const gA = fractionA * numEdge; + indexA = Math.floor(gA); + localFractionA = gA - indexA; + index0 = Geometry.isSmallRelative(1 - localFractionA) ? indexA + 2 : indexA + 1; + } else { // 1 < fractionA + indexA = n - 2; + index0 = n; // no original vertices in clone + } + if (fractionB < 0) { + indexB = 0; + index1 = -1; // no original vertices in clone + } else if (0 <= fractionB && fractionB <= 1) { + const gB = fractionB * numEdge; + indexB = Math.floor(gB); + localFractionB = gB - indexB; + index1 = Geometry.isSmallRelative(localFractionB) ? indexB - 1: indexB; + } else { // 1 < fractionB + indexB = n - 2; + index1 = n - 2; // last original vertex is not in clone + } const result = LineString3d.create(); this.addResolvedPoint(indexA, localFractionA, result._points); - for (let index = indexA + 1; index <= indexB; index++) { - this._points.getPoint3dAtUncheckedPointIndex(index, LineString3d._workPointA); - result._points.push(LineString3d._workPointA); - } - if (!Geometry.isSmallRelative(localFractionB)) { - this.addResolvedPoint(indexB, localFractionB, result._points); + for (let index = index0; index <= index1; index++) { + if (this._points.isIndexValid(index)) { + this._points.getPoint3dAtUncheckedPointIndex(index, LineString3d._workPointA); + result._points.push(LineString3d._workPointA); + } } + this.addResolvedPoint(indexB, localFractionB, result._points); return result; } /** Return (if possible) a specific segment of the linestring */ diff --git a/core/geometry/src/curve/ProxyCurve.ts b/core/geometry/src/curve/ProxyCurve.ts index 91b1264f880a..683d5aa8b8e8 100644 --- a/core/geometry/src/curve/ProxyCurve.ts +++ b/core/geometry/src/curve/ProxyCurve.ts @@ -27,8 +27,6 @@ import type { StrokeOptions } from "./StrokeOptions"; * to the proxy. * * These methods presumably require support from the application class and are left abstract: * * clone - * * clonePartialCurve - * * cloneTransformed * * curvePrimitiveType * * isSameCurvePrimitiveType * * isSameGeometryClass @@ -63,6 +61,22 @@ export abstract class ProxyCurve extends CurvePrimitive{ this._proxyCurve.emitStrokableParts(dest, options); } + /** Return a deep clone. This override removes the undefined variant return. */ + public abstract override clone(): ProxyCurve; + + /** Return a transformed clone. */ + public override cloneTransformed(transform: Transform): ProxyCurve | undefined { + const myClone = this.clone(); + if (myClone.tryTransformInPlace(transform)) + return myClone; + return undefined; + } + + /** Implement by proxyCurve. Subclasses may eventually override this default implementation. */ + public override clonePartialCurve(fractionA: number, fractionB: number): CurvePrimitive | undefined { + return this._proxyCurve.clonePartialCurve(fractionA, fractionB); + } + /** Implement by proxyCurve */ public emitStrokes(dest: LineString3d, options?: StrokeOptions): void{ this._proxyCurve.emitStrokes(dest, options); diff --git a/core/geometry/src/curve/Query/CurveSplitContext.ts b/core/geometry/src/curve/Query/CurveSplitContext.ts index e2b1952e7de0..fd8e1874c54e 100644 --- a/core/geometry/src/curve/Query/CurveSplitContext.ts +++ b/core/geometry/src/curve/Query/CurveSplitContext.ts @@ -76,9 +76,7 @@ export class CurveSplitContext { private collectSinglePrimitiveFragments(curveToCut: CurvePrimitive, intersections: CurveLocationDetailPair[] | undefined, fragments: CurvePrimitive[]) { if (intersections === undefined || !CurveSplitContext.hasInteriorDetailAIntersections(intersections)) { - const fragment = curveToCut.clone(); - if (fragment) - fragments.push(fragment as CurvePrimitive); + fragments.push(curveToCut.clone()); return; } intersections.sort((pairA: CurveLocationDetailPair, pairB: CurveLocationDetailPair) => (pairA.detailA.fraction - pairB.detailA.fraction)); diff --git a/core/geometry/src/curve/StrokeOptions.ts b/core/geometry/src/curve/StrokeOptions.ts index 5c615bf3d5ff..2553e1e413be 100644 --- a/core/geometry/src/curve/StrokeOptions.ts +++ b/core/geometry/src/curve/StrokeOptions.ts @@ -74,7 +74,7 @@ export class StrokeOptions { public clone(): StrokeOptions { const options = new StrokeOptions(); options.chordTol = this.chordTol; - options.angleTol = this.angleTol; + options.angleTol = this.angleTol?.clone(); options.maxEdgeLength = this.maxEdgeLength; options.needConvexFacets = this.needConvexFacets; options.minStrokesPerPrimitive = this.minStrokesPerPrimitive; diff --git a/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts b/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts index e51e7aba2c06..47000a0f0c6a 100644 --- a/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts +++ b/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts @@ -37,7 +37,7 @@ export class CloneCurvesContext extends RecursiveCurveProcessorWithStack { const result = super.leave(); if (result) { if (this._stack.length === 0) // this should only happen once !!! - this._result = result as BagOfCurves; + this._result = result; else // push this result to top of stack. this._stack[this._stack.length - 1].tryAddChild(result); } @@ -46,8 +46,8 @@ export class CloneCurvesContext extends RecursiveCurveProcessorWithStack { // specialized clone methods override this (and allow announceCurvePrimitive to insert to parent) protected doClone(primitive: CurvePrimitive): CurvePrimitive | CurvePrimitive[] | undefined { if (this._transform) - return primitive.cloneTransformed(this._transform) as CurvePrimitive; - return primitive.clone() as CurvePrimitive; + return primitive.cloneTransformed(this._transform); + return primitive.clone(); } public override announceCurvePrimitive(primitive: CurvePrimitive, _indexInParent: number): void { const c = this.doClone(primitive); diff --git a/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts b/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts index fc5af670750f..048812ce2d09 100644 --- a/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts +++ b/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts @@ -23,7 +23,7 @@ export class CloneWithExpandedLineStrings extends CloneCurvesContext { super(undefined); } // We know we have no transform !!! - protected override doClone(primitive: CurvePrimitive): CurvePrimitive | CurvePrimitive[] | undefined { + protected override doClone(primitive: CurvePrimitive): CurvePrimitive | CurvePrimitive[] { if (primitive instanceof LineString3d && primitive.numPoints() > 1) { const packedPoints = primitive.packedPoints; const n = packedPoints.length; @@ -33,11 +33,11 @@ export class CloneWithExpandedLineStrings extends CloneCurvesContext { } return segments; } - return primitive.clone() as CurvePrimitive; + return primitive.clone(); } - public static override clone(target: CurveCollection): CurveCollection | undefined { + public static override clone(target: CurveCollection): CurveCollection { const context = new CloneWithExpandedLineStrings(); target.announceToCurveProcessor(context); - return context._result; + return context._result as CurveCollection; } } diff --git a/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts b/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts index 7632631f6719..2a7bc4387f02 100644 --- a/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts +++ b/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts @@ -242,7 +242,7 @@ class Joint { const fB = joint.nextJointFraction0(1.0); let curve1; if (fA === 0.0 && fB === 1.0) - curve1 = joint.curve1.clone() as CurvePrimitive; + curve1 = joint.curve1.clone(); else if (fA < fB) curve1 = joint.curve1.clonePartialCurve(fA, fB); if (curve1) { @@ -300,7 +300,7 @@ class Joint { const fB = joint.nextJointFraction0(1.0); let curve1; if (fA === 0.0 && fB === 1.0) - curve1 = joint.curve1.clone() as CurvePrimitive; + curve1 = joint.curve1.clone(); else if (fA < fB) curve1 = joint.curve1.clonePartialCurve(fA, fB); this.collectPrimitive(destination, curve1); diff --git a/core/geometry/src/curve/spiral/DirectSpiral3d.ts b/core/geometry/src/curve/spiral/DirectSpiral3d.ts index 60f9e166bc6d..3ff6876484ce 100644 --- a/core/geometry/src/curve/spiral/DirectSpiral3d.ts +++ b/core/geometry/src/curve/spiral/DirectSpiral3d.ts @@ -127,7 +127,7 @@ export class DirectSpiral3d extends TransitionSpiral3d { } /** Recompute strokes */ - public refreshComputedProperties() { + public override refreshComputedProperties() { const sweepRadians = this.nominalL1 / (2.0 * this.nominalR1); const radiansStep = 0.02; const numInterval = StrokeOptions.applyAngleTol(undefined, 4, sweepRadians, radiansStep); @@ -442,7 +442,7 @@ export class DirectSpiral3d extends TransitionSpiral3d { return undefined; } /** Deep clone of this spiral */ - public clone(): DirectSpiral3d { + public override clone(): DirectSpiral3d { return new DirectSpiral3d( this.localToWorld.clone(), this._spiralType, @@ -453,16 +453,6 @@ export class DirectSpiral3d extends TransitionSpiral3d { this._evaluator.clone()); } - /** Return (if possible) a spiral which is a portion of this curve. */ - public override clonePartialCurve(fractionA: number, fractionB: number): DirectSpiral3d | undefined { - const spiralB = this.clone(); - const globalFractionA = this._activeFractionInterval.fractionToPoint(fractionA); - const globalFractionB = this._activeFractionInterval.fractionToPoint(fractionB); - spiralB._activeFractionInterval.set(globalFractionA, globalFractionB); - spiralB.refreshComputedProperties(); - return spiralB; - } - /** apply `transform` to this spiral's local to world transform. */ public tryTransformInPlace(transformA: Transform): boolean { const rigidData = this.applyRigidPartOfTransform(transformA); @@ -474,12 +464,7 @@ export class DirectSpiral3d extends TransitionSpiral3d { this.refreshComputedProperties(); return true; } - /** Clone with a transform applied */ - public cloneTransformed(transform: Transform): DirectSpiral3d { - const result = this.clone(); - result.tryTransformInPlace(transform); // ok, we're confident it will always work. - return result; - } + /** Return the spiral start point. */ public override startPoint(): Point3d { return this.localToWorld.multiplyPoint3d(this.activeStrokes.startPoint()); } /** return the spiral end point. */ diff --git a/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts b/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts index 37f6aa293c99..8bea09a384f7 100644 --- a/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts +++ b/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts @@ -146,7 +146,7 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { } /** Recompute strokes */ - public refreshComputedProperties() { + public override refreshComputedProperties() { this._curvature01 = Segment1d.create( TransitionSpiral3d.radiusToCurvature(this.radius01.x0), TransitionSpiral3d.radiusToCurvature(this.radius01.x1)); @@ -247,23 +247,13 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { return this; } /** Deep clone of this spiral */ - public clone(): IntegratedSpiral3d { + public override clone(): IntegratedSpiral3d { return new IntegratedSpiral3d(this._spiralType, this._evaluator, this.radius01.clone(), this.bearing01.clone(), this.activeFractionInterval.clone(), this.localToWorld.clone(), this._arcLength01, this._designProperties?.clone()); } - /** Return (if possible) a spiral which is a portion of this curve. */ - public override clonePartialCurve(fractionA: number, fractionB: number): IntegratedSpiral3d | undefined { - const spiralB = this.clone(); - const globalFractionA = this._activeFractionInterval.fractionToPoint(fractionA); - const globalFractionB = this._activeFractionInterval.fractionToPoint(fractionB); - spiralB._activeFractionInterval.set(globalFractionA, globalFractionB); - spiralB.refreshComputedProperties(); - return spiralB; - } - /** apply `transform` to this spiral's local to world transform. */ public tryTransformInPlace(transformA: Transform): boolean { @@ -278,12 +268,7 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { this.refreshComputedProperties(); return true; } - /** Clone with a transform applied */ - public cloneTransformed(transform: Transform): TransitionSpiral3d { - const result = this.clone(); - result.tryTransformInPlace(transform); // ok, we're confident it will always work. - return result; - } + /** Return the spiral start point. */ public override startPoint(): Point3d { return this.activeStrokes.startPoint(); } /** return the spiral end point. */ diff --git a/core/geometry/src/curve/spiral/TransitionSpiral3d.ts b/core/geometry/src/curve/spiral/TransitionSpiral3d.ts index bbef84d1c4d6..8ba89cb6cd11 100644 --- a/core/geometry/src/curve/spiral/TransitionSpiral3d.ts +++ b/core/geometry/src/curve/spiral/TransitionSpiral3d.ts @@ -100,6 +100,29 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { return 1.0 / curvature; } + /** Return a deep clone. */ + public abstract override clone(): TransitionSpiral3d; + + /** Recompute strokes */ + public abstract refreshComputedProperties(): void; + + /** Return (if possible) a spiral which is a portion of this curve. */ + public override clonePartialCurve(fractionA: number, fractionB: number): TransitionSpiral3d { + const spiralB = this.clone(); + const globalFractionA = this._activeFractionInterval.fractionToPoint(fractionA); + const globalFractionB = this._activeFractionInterval.fractionToPoint(fractionB); + spiralB._activeFractionInterval.set(globalFractionA, globalFractionB); + spiralB.refreshComputedProperties(); + return spiralB; + } + + /** Clone with a transform applied */ + public override cloneTransformed(transform: Transform): TransitionSpiral3d { + const result = this.clone(); + result.tryTransformInPlace(transform); // ok, we're confident it will always work. + return result; + } + /** Return the average of the start and end curvatures. */ public static averageCurvature(radiusLimits: Segment1d): number { return 0.5 * (TransitionSpiral3d.radiusToCurvature(radiusLimits.x0) + TransitionSpiral3d.radiusToCurvature(radiusLimits.x1)); diff --git a/core/geometry/src/polyface/PolyfaceBuilder.ts b/core/geometry/src/polyface/PolyfaceBuilder.ts index e1caa25235ec..7973755b0ff7 100644 --- a/core/geometry/src/polyface/PolyfaceBuilder.ts +++ b/core/geometry/src/polyface/PolyfaceBuilder.ts @@ -1108,9 +1108,9 @@ export class PolyfaceBuilder extends NullGeometryHandler { private addBetweenRotatedStrokeSets(stroke0: AnyCurve, transformA: Transform, vA: number, transformB: Transform, vB: number) { if (stroke0 instanceof LineString3d) { - const strokeA = stroke0.cloneTransformed(transformA) as LineString3d; + const strokeA = stroke0.cloneTransformed(transformA); this.createIndicesInLineString(strokeA, vA); - const strokeB = stroke0.cloneTransformed(transformB) as LineString3d; + const strokeB = stroke0.cloneTransformed(transformB); this.createIndicesInLineString(strokeB, vB); this.addBetweenLineStringsWithStoredIndices(strokeA, strokeB); } else if (stroke0 instanceof ParityRegion) { diff --git a/core/geometry/src/serialization/IModelJsonSchema.ts b/core/geometry/src/serialization/IModelJsonSchema.ts index bdbfbea38bd9..88e7973f8a34 100644 --- a/core/geometry/src/serialization/IModelJsonSchema.ts +++ b/core/geometry/src/serialization/IModelJsonSchema.ts @@ -117,6 +117,10 @@ export namespace IModelJson { uKnots: [number]; /** Array of knots for the v direction bspline */ vKnots: [number]; + /** optional flag for periodic data in the u parameter direction */ + closedU?: boolean; + /** optional flag for periodic data in the v parameter direction */ + closedV?: boolean; } /** diff --git a/core/geometry/src/solid/RuledSweep.ts b/core/geometry/src/solid/RuledSweep.ts index 4ea4af7993a4..6c3531012a87 100644 --- a/core/geometry/src/solid/RuledSweep.ts +++ b/core/geometry/src/solid/RuledSweep.ts @@ -69,7 +69,7 @@ export class RuledSweep extends SolidPrimitive { public cloneContours(): CurveCollection[] { const result = []; for (const sweepable of this._contours) { - result.push(sweepable.curves.clone() as CurveCollection); + result.push(sweepable.curves.clone()); } return result; } diff --git a/core/geometry/src/solid/SweepContour.ts b/core/geometry/src/solid/SweepContour.ts index 63b326775fc3..0ba7efa90491 100644 --- a/core/geometry/src/solid/SweepContour.ts +++ b/core/geometry/src/solid/SweepContour.ts @@ -117,7 +117,7 @@ export class SweepContour { } /** Return a deep clone. */ public clone(): SweepContour { - return new SweepContour(this.curves.clone() as CurveCollection, this.localToWorld.clone(), this.axis); + return new SweepContour(this.curves.clone(), this.localToWorld.clone(), this.axis); } /** Return a transformed clone. */ public cloneTransformed(transform: Transform): SweepContour | undefined { diff --git a/core/geometry/src/test/curve/Arc3d.test.ts b/core/geometry/src/test/curve/Arc3d.test.ts index 63403087ff8e..d00b16f31c58 100644 --- a/core/geometry/src/test/curve/Arc3d.test.ts +++ b/core/geometry/src/test/curve/Arc3d.test.ts @@ -66,7 +66,7 @@ function exerciseArc3d(ck: Checker, arc: Arc3d) { const a = 4.2; const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), Matrix3d.createScale(a, a, a)); - const arc1 = arc.cloneTransformed(scaleTransform) as Arc3d; + const arc1 = arc.cloneTransformed(scaleTransform); ck.testFalse(arc.isAlmostEqual(arc1), "scale changes arc"); ck.testPointer(arc1); ck.testBoolean(arc1.isCircular, arc.isCircular, "scaled clone retains circular"); diff --git a/core/geometry/src/test/curve/Curve.test.ts b/core/geometry/src/test/curve/Curve.test.ts index a241ae108c95..a5f8d59116fe 100644 --- a/core/geometry/src/test/curve/Curve.test.ts +++ b/core/geometry/src/test/curve/Curve.test.ts @@ -102,7 +102,7 @@ class StrokeCountSearch extends NullGeometryHandler { class ExerciseCurve { public static exerciseStrokeData(ck: Checker, curve: CurvePrimitive) { - const curveA = curve.clone() as CurvePrimitive; + const curveA = curve.clone(); const count0 = curveA.computeStrokeCountForOptions(); curveA.computeAndAttachRecursiveStrokeCounts(); // console.log("strokes by count", count0); @@ -156,7 +156,7 @@ class ExerciseCurve { } public static exerciseReverseInPlace(ck: Checker, curve: CurvePrimitive) { - const curveA = curve.clone() as CurvePrimitive; + const curveA = curve.clone(); curveA.reverseInPlace(); for (const f of [0, 0.2, 0.6, 0.92, 1]) { let point = curve.fractionToPoint(f); @@ -719,11 +719,8 @@ describe("Curves", () => { // const indexedPathC = CurveChainWithDistanceIndex.createCapture(pathC); // const indexedPathD = CurveChainWithDistanceIndex.createCapture(pathD); const returnUndefined = (_a: CurvePrimitive, _b: CurvePrimitive): CurvePrimitive | undefined => undefined; - const returnCloneA = (a: CurvePrimitive, _b: CurvePrimitive): CurvePrimitive | undefined => { - const c = a.clone(); - if (c) - return c as CurvePrimitive; - return undefined; + const returnCloneA = (a: CurvePrimitive, _b: CurvePrimitive): CurvePrimitive => { + return a.clone(); }; ck.testUndefined(RuledSweep.mutatePartners(pathA, emptyBag, returnCloneA), "mutatePartners rejects mismatched collection types"); ck.testUndefined(RuledSweep.mutatePartners(pathA, pathD, returnCloneA), "mutatePartners rejects mismatched collection lengths"); diff --git a/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts b/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts index 56edac361003..15348af91177 100644 --- a/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts +++ b/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts @@ -68,10 +68,9 @@ function testVaryingSubsets(_ck: Checker, allGeometry: GeometryQuery[], geometry let y0 = 0; for (const f1 of fractions) { if (f0 !== f1) { - // PROBLEM: bspline does not implement clone partial !!! let partialB: CurvePrimitive | undefined; if (f0 === 0 && f1 === 1) { - partialB = geometryB.clone() as CurvePrimitive; + partialB = geometryB.clone(); } else { partialB = geometryB.clonePartialCurve(f0, f1); } diff --git a/core/geometry/src/test/curve/LineString3d.test.ts b/core/geometry/src/test/curve/LineString3d.test.ts index a52808432658..f350e56fe023 100644 --- a/core/geometry/src/test/curve/LineString3d.test.ts +++ b/core/geometry/src/test/curve/LineString3d.test.ts @@ -7,6 +7,7 @@ import { expect } from "chai"; import { ClipPlane } from "../../clipping/ClipPlane"; import { CurveLocationDetail } from "../../curve/CurveLocationDetail"; import { CurvePrimitive } from "../../curve/CurvePrimitive"; +import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; import { StrokeOptions } from "../../curve/StrokeOptions"; @@ -17,9 +18,68 @@ import { Point2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Transform } from "../../geometry3d/Transform"; import { Checker } from "../Checker"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; /* eslint-disable no-console */ +function exerciseClonePartialLineString3d(ck: Checker, allGeometry: GeometryQuery[], lsA: LineString3d, delta: Point3d) { + const expectValidResults = lsA.numPoints() > 1; + const yInc = 1.2 * lsA.range().yLength(); + delta.x += 1.2 * lsA.range().xLength(); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, lsA, delta.x, delta.y = 0); + for (const extendFraction of [0.05, 0.721, 1.4, 3.96]) { + const cee0 = lsA.clonePartialCurve(-extendFraction, -extendFraction / 2); // does not contain [0,1] + const ce0 = lsA.clonePartialCurve(-extendFraction, 0); // contains [0] + const ce01 = lsA.clonePartialCurve(-extendFraction, 1); // contains [0,1] + const ce01e = lsA.clonePartialCurve(-extendFraction, 1 + extendFraction); // contains [0,1] + const c01e = lsA.clonePartialCurve(0, 1 + extendFraction); // contains [0,1] + const c1e = lsA.clonePartialCurve(1, 1 + extendFraction); // contains [1] + const c1ee = lsA.clonePartialCurve(1 + extendFraction / 2, 1 + extendFraction); // does not contain [0,1] + if (ck.testPointer(cee0) && expectValidResults) { + ck.testExactNumber(cee0.numPoints(), 2, "isolated pre-extension is a segment"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(cee0.curveLength(), (extendFraction - (extendFraction / 2)) * lsA.points[0].distance(lsA.points[1]), "isolated pre-extension length is fraction of first segment"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, cee0, delta.x, delta.y += yInc); + } + if (ck.testPointer(ce0) && expectValidResults) { + ck.testExactNumber(ce0.numPoints(), 2, "pre-extension is a segment"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(ce0.curveLength(), extendFraction * lsA.points[0].distance(lsA.points[1]), "pre-extension length is fraction of first segment"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce0, delta.x, delta.y += yInc); + } + if (ck.testPointer(ce01) && expectValidResults) { + ck.testExactNumber(ce01.numPoints(), lsA.numPoints(), "pre-extended linestring has same point count"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(ce01.curveLength(), lsA.curveLength() + extendFraction * lsA.points[0].distance(lsA.points[1]), "pre-extended linestring has expected length"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce01, delta.x, delta.y += yInc); + } + if (ck.testPointer(ce01e) && expectValidResults) { + ck.testExactNumber(ce01e.numPoints(), lsA.numPoints(), "bi-extended linestring has same point count"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(ce01e.curveLength(), extendFraction * lsA.points[0].distance(lsA.points[1]) + lsA.curveLength() + extendFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "bi-extended linestring has expected length"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce01e, delta.x, delta.y += yInc); + } + if (ck.testPointer(c01e) && expectValidResults) { + ck.testExactNumber(c01e.numPoints(), lsA.numPoints(), "post-extended linestring has same point count"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(c01e.curveLength(), lsA.curveLength() + extendFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "post-extended linestring has expected length"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, c01e, delta.x, delta.y += yInc); + } + if (ck.testPointer(c1e) && expectValidResults) { + ck.testExactNumber(c1e.numPoints(), 2, "post-extension is a segment"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(c1e.curveLength(), extendFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "post-extension length is fraction of last segment"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, c1e, delta.x, delta.y += yInc); + } + if (ck.testPointer(c1ee) && expectValidResults) { + ck.testExactNumber(c1ee.numPoints(), 2, "isolated post-extension is a segment"); + if (!lsA.isPhysicallyClosed) + ck.testCoordinate(c1ee.curveLength(), (extendFraction - (extendFraction / 2)) * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "isolated post-extension length is fraction of last segment"); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, c1ee, delta.x, delta.y += yInc); + } + } +} + function exerciseLineString3d(ck: Checker, lsA: LineString3d) { const expectValidResults = lsA.numPoints() > 1; const a = 4.2; @@ -46,15 +106,14 @@ function exerciseLineString3d(ck: Checker, lsA: LineString3d) { } } } + const splitFraction = 0.4203; const partA = lsA.clonePartialCurve(0.0, splitFraction); const partB = lsA.clonePartialCurve(1.0, splitFraction); // reversed to exercise more code. But length is absolute so it will add. - if (expectValidResults - && ck.testPointer(partA, "forward partial") && partA - && ck.testPointer(partA, "forward partial") && partB) { + if (ck.testPointer(partA, "forward partial") && ck.testPointer(partB, "backward partial")) ck.testCoordinate(lsA.curveLength(), partA.curveLength() + partB.curveLength(), "Partial curves sum to length", lsA, partA, partB); - } } + describe("LineString3d", () => { it("HelloWorld", () => { const ck = new Checker(); @@ -68,9 +127,7 @@ describe("LineString3d", () => { const point150 = Point3d.create(1, 5, 0); const lsA = LineString3d.create([point100, point420, point450, point150]); exerciseLineString3d(ck, lsA); - const lsB = LineString3d.createRectangleXY( - Point3d.create(1, 1), - 3, 2, true); + const lsB = LineString3d.createRectangleXY(Point3d.create(1, 1), 3, 2, true); exerciseLineString3d(ck, lsB); const lsC = LineString3d.create([point100]); ck.testUndefined(lsC.quickUnitNormal(), "quickUnitNormal expected failure 1 point"); @@ -81,7 +138,6 @@ describe("LineString3d", () => { const normalA = lsA.quickUnitNormal(); if (ck.testPointer(normalA, "quickUnitNormal") && normalA) ck.testCoordinate(1.0, normalA.magnitude(), "unit normal magnitude"); - ck.checkpoint("LineString3d.HelloWorld"); expect(ck.getNumErrors()).equals(0); }); @@ -118,16 +174,11 @@ describe("LineString3d", () => { it("clonePartial", () => { const ck = new Checker(); - // we know the length of this linestring is 'a'. - // make partials - const a = 5.0; - const interiorFraction = 0.24324; - const ls = LineString3d.createXY([Point2d.create(0, 1), Point2d.create(0.5 * a, 1), Point2d.create(a, 1)], 0); - ck.testExactNumber(3, ls.numPoints()); - const ls1 = ls.clonePartialCurve(interiorFraction, 3.0)!; - const ls2 = ls.clonePartialCurve(-4, interiorFraction)!; - ck.testCoordinate(ls1.curveLength(), (1.0 - interiorFraction) * a, "clonePartial does not extrapolate up"); - ck.testCoordinate(ls2.curveLength(), (interiorFraction) * a, "clonePartial does not extrapolate down"); + const allGeometry: GeometryQuery[] = []; + const delta = Point3d.createZero(); + const lsA = LineString3d.create([Point3d.create(1, 0, 0), Point3d.create(4, 2, 0), Point3d.create(4, 5, 0), Point3d.create(1, 5, 0)]); + exerciseClonePartialLineString3d(ck, allGeometry, lsA, delta); + GeometryCoreTestIO.saveGeometry(allGeometry, "LineString3d", "ClonePartial"); expect(ck.getNumErrors()).equals(0); }); diff --git a/core/geometry/src/test/curve/TransitionSpiral3d.test.ts b/core/geometry/src/test/curve/TransitionSpiral3d.test.ts index 38e2e62f679d..1d89452f621e 100644 --- a/core/geometry/src/test/curve/TransitionSpiral3d.test.ts +++ b/core/geometry/src/test/curve/TransitionSpiral3d.test.ts @@ -945,7 +945,7 @@ describe("TransitionSpiral3d", () => { ck.testTightNumber(partial.curveLength(), 0.6 * spiral.curveLength()); ck.testTrue((partial as IntegratedSpiral3d).bearing01.isAlmostEqual(spiral.bearing01)); ck.testTrue((partial as IntegratedSpiral3d).radius01.isAlmostEqual(spiral.radius01)); - } else { + } else if (spiral instanceof DirectSpiral3d) { ck.testExactNumber((partial as DirectSpiral3d).nominalL1, spiral.nominalL1); ck.testExactNumber((partial as DirectSpiral3d).nominalR1, spiral.nominalR1); } diff --git a/core/geometry/src/test/testInputs/curve/offsetCurve.imjs b/core/geometry/src/test/testInputs/curve/offsetCurve.imjs index 658307312158..918f5b6f54e2 100644 --- a/core/geometry/src/test/testInputs/curve/offsetCurve.imjs +++ b/core/geometry/src/test/testInputs/curve/offsetCurve.imjs @@ -1 +1 @@ -[{"loop":[{"arc":{"center":[0.0,0.0,0.0],"sweepStartEnd":[0.0,360.0],"vectorX":[3.6038923553025408,3.4658274468576615,0.0],"vectorY":[-3.4658274468576615,3.6038923553025408,0.0]}}]},{"loop":[{"arc":{"center":[0.0,0.0,0.0],"sweepStartEnd":[0.0,360.0],"vectorX":[3.9580865483760173,5.0967685902004787,0.0],"vectorY":[-1.8311453802205018,1.4220445306280947,0.0]}}]},{"path":[{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.0,0.10000000000000001,0.20000000000000001,0.30000000000000004,0.40000000000000002,0.50,0.59999999999999998,0.69999999999999996,0.79999999999999993,0.89999999999999991,1.0,1.0,1.0,1.0],"order":4,"points":[[0.0,0.0,0.0],[-3.2813866761483652,6.6477809007697477,0.0],[2.8956286471887935,8.5276913788687114,0.0],[9.6152196408190846,1.3840315620926447,0.0],[13.340210300331535,6.5746732710659002,0.0],[16.919122894765053,2.4075383779465280,0.0],[10.856883193989908,-2.7831033310267266,0.0],[14.362756755883964,-7.4619916320730404,0.0],[1.6539650940179911,-12.579525711342445,0.0],[-18.796964017030714,-3.4410719983613625,0.0],[-9.0827726892825780,5.9167046037312625,0.0],[-6.4533675178620342,0.50674000564646349,0.0],[-4.7734697694544579,10.156947126554483,0.0]]}}]},{"path":[{"lineString":[[0.0,0.0,0.0],[7.0901559444549278,0.0,0.0],[7.0901559444549278,11.193508876284058,0.0],[-6.9333383031213245,6.2221900564223507,0.0],[-0.72502053726725535,-8.0337977358281343,0.0],[8.2764877048335119,-4.1137450286215156,0.0],[11.910732092059270,-8.8379816625704670,0.0],[11.764654026980345,8.7078494663532044,0.0]]}]},{"path":[{"lineSegment":[[0.0,0.0,0.0],[-6.3371358144912637,-1.5619722468588617,0.0]]},{"arc":{"center":[-7.5337203132944577,3.2927353176834049,0.0],"sweepStartEnd":[0.0,-44.292056097662488],"vectorX":[1.1965844988031948,-4.8547075645422666,0.0],"vectorY":[4.8547075645422666,1.1965844988031948,0.0]}},{"lineSegment":[[-10.067337831006647,-1.0178078353243367,0.0],[-10.299795439141302,-0.88117571097488323,0.0]]},{"arc":{"center":[-7.7661779214291062,3.4293674420328548,0.0],"sweepStartEnd":[0.0,-37.247266668392840],"vectorX":[-2.5336175177121967,-4.3105431530077372,0.0],"vectorY":[4.3105431530077372,-2.5336175177121967,0.0]}},{"lineString":[[-12.391997862584658,1.5315292318559042,0.0],[-13.203897768630647,3.5104665066300731,0.0]]},{"arc":{"center":[-11.318694100384164,8.1414498934746007,0.0],"sweepStartEnd":[0.21128834236126062,90.0],"vectorX":[-1.9022683832058764,-4.6239998916798539,0.0],"vectorY":[4.6239998916798539,-1.9022683832058764,0.0]}},{"lineString":[[-6.694694208704310,6.2391815102687245,0.0],[-6.6946942087051866,6.2391815102691908,0.0],[-5.2254016746519483,9.8107114680251470,0.0]]},{"arc":{"center":[-0.60140178297264546,7.9084430848204477,0.0],"sweepStartEnd":[0.0,49.871852040703828],"vectorX":[-4.6239998916783627,1.9022683832042588,0.0],"vectorY":[1.9022683832042588,4.6239998916783627,0.0]}},{"lineString":[[-2.1270829898728163,12.669986621835697,0.0],[1.3442264429982971,10.279897143946570,0.0]]},{"arc":{"center":[-1.4912883171535904,6.1616625652756545,0.0],"sweepStartEnd":[0.0,-72.073871644914178],"vectorX":[2.8355147601518880,4.1182345786709158,0.0],"vectorY":[-4.1182345786709140,2.8355147601518871,-0.0]}},{"lineString":[[3.2997676439965966,4.7313539352495066,0.0],[2.6995263278276980,2.7207461016751040,0.0],[7.0878615671917942,2.3926426193547741,0.0]]},{"arc":{"center":[6.3519072878824367,-7.4506363230520716,0.0],"sweepStartEnd":[0.0,53.163685868306068],"vectorX":[0.73595427930935819,9.8432789424068474,0.0],"vectorY":[9.8432789424068474,-0.73595427930935819,0.0]}},{"lineSegment":[[14.671218221963304,-2.1383077732213733,0.0],[14.064465710401620,2.2963301780734930,0.0]]}]},{"loop":[{"lineString":[[0.0,0.0,0.0],[0.0,-1.1099127396475472,0.0],[-2.7845841505570910,-1.1099127396475472,0.0],[-2.7845841505570910,0.66773336508352088,0.0],[-1.0691118128924550,1.3000392028327798,0.0],[5.7273356393959105,0.66773336508352088,0.0],[1.2624942771813004,-0.79621048587147758,0.0],[0.0,0.0,0.0]]}]},{"loop":[{"lineString":[[0.0,0.0,0.0],[-0.61584713540328018,3.6896823785790831,0.0],[-2.1046386024192785,3.5546727122894772,0.0],[-4.5339664386762699,4.3668057741930220,0.0]]},{"lineSegment":[[-4.5339664386762699,4.3668057741930220,0.0],[-3.4830315566345291,8.8043855724003581,0.0]]},{"arc":{"center":[5.4583975482485450,6.6868214566134254,0.0],"sweepStartEnd":[0.0,90.0],"vectorX":[-8.9414291048830723,2.1175641157869345,0.0],"vectorY":[0.70355605406719779,2.9707702977462520,0.0]}},{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.0,0.33333333333333331,0.66666666666666663,1.0,1.0,1.0,1.0],"order":4,"points":[[6.1619536023157417,9.6575917543596770,0.0],[7.6970225999927528,7.6512847098875341,0.0],[5.6865384778259411,6.1350571499698576,0.0],[8.1931160846832682,4.9325318438282526,0.0],[12.187974145612131,6.6317523851153037,0.0],[5.1088506699955403,-3.7825088938882185,0.0]]}},{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.33333333333333331,0.66666666666666663,1.0,1.0,1.0],"order":3,"points":[[5.1088506699955403,-3.7825088938882185,0.0],[3.4639091154954258,-2.1355720615638454,0.0],[-0.60275194979654145,-6.0241729156630566,0.0],[-1.7450724737549592,-2.5015580243025948,0.0],[-7.5023679145053777,-2.5015580243025948,0.0]]}},{"arc":{"center":[-7.5023679145053777,0.24333669623802656,0.0],"sweepStartEnd":[0.0,-137.47124911458326],"vectorX":[0.0,-2.7448947205406213,0.0],"vectorY":[2.7448947205406213,0.0,0.0]}},{"lineString":[[-9.3578071873755597,2.2661545653361688,0.0],[-5.6289622552135761,0.86420574016983043,0.0],[-4.7515480756461290,3.1979153293903608,0.0],[-3.6212763391345097,2.4372130792977615,0.0],[-3.6656470266960799,0.33545973814295671,0.0],[0.0,0.0,0.0]]}]}] +[{"loop":[{"arc":{"center":[0.0,0.0,0.0],"sweepStartEnd":[0.0,360.0],"vectorX":[3.6038923553025408,3.4658274468576615,0.0],"vectorY":[-3.4658274468576615,3.6038923553025408,0.0]}}]},{"loop":[{"arc":{"center":[0.0,0.0,0.0],"sweepStartEnd":[0.0,360.0],"vectorX":[3.9580865483760173,5.0967685902004787,0.0],"vectorY":[-1.8311453802205018,1.4220445306280947,0.0]}}]},{"path":[{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.0,0.10000000000000001,0.20000000000000001,0.30000000000000004,0.40000000000000002,0.50,0.59999999999999998,0.69999999999999996,0.79999999999999993,0.89999999999999991,1.0,1.0,1.0,1.0],"order":4,"points":[[0.0,0.0,0.0],[-3.2813866761483652,6.6477809007697477,0.0],[2.8956286471887935,8.5276913788687114,0.0],[9.6152196408190846,1.3840315620926447,0.0],[13.340210300331535,6.5746732710659002,0.0],[16.919122894765053,2.4075383779465280,0.0],[10.856883193989908,-2.7831033310267266,0.0],[14.362756755883964,-7.4619916320730404,0.0],[1.6539650940179911,-12.579525711342445,0.0],[-18.796964017030714,-3.4410719983613625,0.0],[-9.0827726892825780,5.9167046037312625,0.0],[-6.4533675178620342,0.50674000564646349,0.0],[-4.7734697694544579,10.156947126554483,0.0]]}}]},{"path":[{"lineString":[[0.0,0.0,0.0],[7.0901559444549278,0.0,0.0],[7.0901559444549278,11.193508876284058,0.0],[-6.9333383031213245,6.2221900564223507,0.0],[-0.72502053726725535,-8.0337977358281343,0.0],[8.2764877048335119,-4.1137450286215156,0.0],[11.910732092059270,-8.8379816625704670,0.0],[11.764654026980345,8.7078494663532044,0.0]]}]},{"path":[{"lineSegment":[[0.0,0.0,0.0],[-6.3371358144912637,-1.5619722468588617,0.0]]},{"arc":{"center":[-7.5337203132944577,3.2927353176834049,0.0],"sweepStartEnd":[0.0,-44.292056097662488],"vectorX":[1.1965844988031948,-4.8547075645422666,0.0],"vectorY":[4.8547075645422666,1.1965844988031948,0.0]}},{"lineSegment":[[-10.067337831006647,-1.0178078353243367,0.0],[-10.299795439141302,-0.88117571097488323,0.0]]},{"arc":{"center":[-7.7661779214291062,3.4293674420328548,0.0],"sweepStartEnd":[0.0,-37.247266668392840],"vectorX":[-2.5336175177121967,-4.3105431530077372,0.0],"vectorY":[4.3105431530077372,-2.5336175177121967,0.0]}},{"lineString":[[-12.391997862584658,1.5315292318559042,0.0],[-13.203897768630647,3.5104665066300731,0.0]]},{"arc":{"center":[-11.318694100384164,8.1414498934746007,0.0],"sweepStartEnd":[0.21128834236126062,90.0],"vectorX":[-1.9022683832058764,-4.6239998916798539,0.0],"vectorY":[4.6239998916798539,-1.9022683832058764,0.0]}},{"lineString":[[-6.694694208704310,6.2391815102687245,0.0],[-6.6946942087051866,6.2391815102691908,0.0],[-5.2254016746519483,9.8107114680251470,0.0]]},{"arc":{"center":[-0.60140178297264546,7.9084430848204477,0.0],"sweepStartEnd":[0.0,49.871852040703828],"vectorX":[-4.6239998916783627,1.9022683832042588,0.0],"vectorY":[1.9022683832042588,4.6239998916783627,0.0]}},{"lineString":[[-2.1270829898728163,12.669986621835697,0.0],[1.3442264429982971,10.279897143946570,0.0]]},{"arc":{"center":[-1.4912883171535904,6.1616625652756545,0.0],"sweepStartEnd":[0.0,-72.073871644914178],"vectorX":[2.8355147601518880,4.1182345786709158,0.0],"vectorY":[-4.1182345786709140,2.8355147601518871,-0.0]}},{"lineString":[[3.2997676439965966,4.7313539352495066,0.0],[2.6995263278276980,2.7207461016751040,0.0],[7.0878615671917942,2.3926426193547741,0.0]]},{"arc":{"center":[6.3519072878824367,-7.4506363230520716,0.0],"sweepStartEnd":[0.0,53.163685868306068],"vectorX":[0.73595427930935819,9.8432789424068474,0.0],"vectorY":[9.8432789424068474,-0.73595427930935819,0.0]}},{"lineSegment":[[14.671218221963304,-2.1383077732213733,0.0],[14.064465710401620,2.2963301780734930,0.0]]}]},{"loop":[{"lineString":[[0.0,0.0,0.0],[0.0,-1.1099127396475472,0.0],[-2.7845841505570910,-1.1099127396475472,0.0],[-2.7845841505570910,0.66773336508352088,0.0],[-1.0691118128924550,1.3000392028327798,0.0],[5.7273356393959105,0.66773336508352088,0.0],[1.2624942771813004,-0.79621048587147758,0.0],[0.0,0.0,0.0]]}]},{"loop":[{"lineString":[[0.0,0.0,0.0],[-0.61584713540328018,3.6896823785790831,0.0],[-2.1046386024192785,3.5546727122894772,0.0],[-4.5339664386762699,4.3668057741930220,0.0]]},{"lineSegment":[[-4.5339664386762699,4.3668057741930220,0.0],[-3.4830315566345291,8.8043855724003581,0.0]]},{"arc":{"center":[5.4583975482485450,6.6868214566134254,0.0],"sweepStartEnd":[0.0,90.0],"vectorX":[-8.9414291048830723,2.1175641157869345,0.0],"vectorY":[0.70355605406719779,2.9707702977462520,0.0]}},{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.0,0.33333333333333331,0.66666666666666663,1.0,1.0,1.0,1.0],"order":4,"points":[[6.1619536023157417,9.6575917543596770,0.0],[7.6970225999927528,7.6512847098875341,0.0],[7.3079996213549023,6.2473773492108648,0.0],[8.3612688818575567,2.3160063875048049,0.0],[11.049464577076748,-0.44821671834839205,0.0],[5.1088506699955403,-3.7825088938882185,0.0]]}},{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.33333333333333331,0.66666666666666663,1.0,1.0,1.0],"order":3,"points":[[5.1088506699955403,-3.7825088938882185,0.0],[3.4639091154954258,-2.1355720615638454,0.0],[-0.60275194979654145,-6.0241729156630566,0.0],[-1.7450724737549592,-2.5015580243025948,0.0],[-7.5023679145053777,-2.5015580243025948,0.0]]}},{"arc":{"center":[-7.5023679145053777,0.24333669623802656,0.0],"sweepStartEnd":[0.0,-137.47124911458326],"vectorX":[0.0,-2.7448947205406213,0.0],"vectorY":[2.7448947205406213,0.0,0.0]}},{"lineString":[[-9.3578071873755597,2.2661545653361688,0.0],[-5.6289622552135761,0.86420574016983043,0.0],[-4.7515480756461290,3.1979153293903608,0.0],[-3.6212763391345097,2.4372130792977615,0.0],[-3.6656470266960799,0.33545973814295671,0.0],[0.0,0.0,0.0]]}]},{"path":[{"lineSegment":[[18.551832491582125,2.0533413059542021,0.0],[12.611218584500918,-1.2809508695856238,0.0]]},{"bcurve":{"closed":false,"knots":[0.0,0.0,0.0,0.33333333333333331,0.66666666666666663,1.0,1.0,1.0],"order":3,"points":[[12.611218584500918,-1.2809508695856238,0.0],[10.966277030000803,0.36598596273874939,0.0],[6.8996159647088362,-3.5226148913604618,0.0],[5.7572954407504184,0.0,0.0],[0.0,0.0,0.0]]}},{"arc":{"center":[0.0,2.7448947205406213,0.0],"sweepStartEnd":[0.0,-137.47124911458326],"vectorX":[0.0,-2.7448947205406213,0.0],"vectorY":[2.7448947205406213,0.0,0.0]}}]}] diff --git a/core/geometry/src/test/topology/RegionOps.test.ts b/core/geometry/src/test/topology/RegionOps.test.ts index 06c76466bb5a..4503d3639056 100644 --- a/core/geometry/src/test/topology/RegionOps.test.ts +++ b/core/geometry/src/test/topology/RegionOps.test.ts @@ -43,6 +43,8 @@ import { prettyPrint } from "../testFunctions"; import { GraphChecker } from "./Graph.test"; import * as fs from "fs"; import { RecursiveCurveProcessor } from "../../curve/CurveProcessor"; +import { BezierCurve3d } from "../../bspline/BezierCurve3d"; +import { BSplineCurve3dH } from "../../bspline/BSplineCurve3dH"; const diegoPathA = [ { @@ -648,18 +650,15 @@ class HasEllipticalArcProcessor extends RecursiveCurveProcessor { class HasStrokablePrimitiveProcessor extends RecursiveCurveProcessor { private _hasStrokablePrimitive: boolean; private _preserveEllipticalArcs: boolean; - private _checkChildrenOnly: boolean; - public constructor(preserveEllipticalArcs: boolean = false, checkChildrenOnly: boolean = false) { + public constructor(preserveEllipticalArcs: boolean = false) { super(); this._hasStrokablePrimitive = false; this._preserveEllipticalArcs = preserveEllipticalArcs; - this._checkChildrenOnly = checkChildrenOnly; } - public override announceCurvePrimitive(data: CurvePrimitive, indexInParent = -1): void { + public override announceCurvePrimitive(data: CurvePrimitive, _indexInParent = -1): void { if (data instanceof LineSegment3d || data instanceof LineString3d || (data instanceof Arc3d && (data.isCircular || this._preserveEllipticalArcs))) return; // not strokable - if (!this._checkChildrenOnly || indexInParent >= 1) - this._hasStrokablePrimitive = true; + this._hasStrokablePrimitive = true; } public claimResult(): boolean { return this._hasStrokablePrimitive; } } @@ -668,11 +667,10 @@ class HasStrokablePrimitiveProcessor extends RecursiveCurveProcessor { function testOffsetSingle(ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions): void { const offsetCurve = RegionOps.constructCurveXYOffset(baseCurve, options); if (ck.testDefined(offsetCurve, "Offset computed")) { - // spot-check some curve-curve distances, starting with smaller curve + // spot-check some curve-curve distances from baseCurve to offsetCurve if (!options.preserveEllipticalArcs) { - let tolFactor = 100 * (options.strokeOptions.hasAngleTol ? options.strokeOptions.angleTol!.degrees : 1); + const tolFactor = 1000 * (options.strokeOptions.hasAngleTol ? options.strokeOptions.angleTol!.degrees : 1); for (const cp of baseCurve.children) { - if (cp instanceof Arc3d && !cp.isCircular) tolFactor *= 10; // ellipse approximations are sloppier for (let u = 0.0738; u < 1.0; u += 0.0467) { const basePt = cp.fractionToPoint(u); const offsetDetail = offsetCurve!.closestPoint(basePt); @@ -681,9 +679,10 @@ function testOffsetSingle(ck: Checker, allGeometry: GeometryQuery[], delta: Poin if (!projectsToVertex && offsetDetail.curve instanceof LineString3d) { const scaledParam = offsetDetail.fraction * (offsetDetail.curve.numPoints() - 1); projectsToVertex = Geometry.isAlmostEqualNumber(scaledParam, Math.trunc(scaledParam)); + projectsToVertex = projectsToVertex || Geometry.isAlmostEqualNumber(scaledParam, 1 + Math.trunc(scaledParam)); // e.g., true for scaledParam === 4.9999999 } if (!projectsToVertex) { // avoid measuring projections to linestring vertices as they usually exceed offset distance - if (!ck.testCoordinateWithToleranceFactor(offsetDetail.point.distance(basePt), Math.abs(options.leftOffsetDistance), tolFactor, "Offset distance spot check")) { + if (!ck.testCoordinateWithToleranceFactor(offsetDetail.point.distance(basePt), Math.abs(options.leftOffsetDistance), tolFactor)) { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, basePt, 0.05, delta.x, delta.y); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, offsetDetail.point, 0.05, delta.x, delta.y); } @@ -697,8 +696,8 @@ function testOffsetSingle(ck: Checker, allGeometry: GeometryQuery[], delta: Poin } function testOffsetBothSides(ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions): void { - const halfRangeY = baseCurve.range().yLength() / 2; - delta.y += halfRangeY; + const rangeY = baseCurve.range().yLength(); + delta.y += rangeY; GeometryCoreTestIO.captureCloneGeometry(allGeometry, baseCurve, delta.x, delta.y); testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on given offset @@ -706,16 +705,10 @@ function testOffsetBothSides(ck: Checker, allGeometry: GeometryQuery[], delta: P testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on other side options.leftOffsetDistance *= -1; // undo - delta.y += halfRangeY; + delta.y += rangeY; } function testOffset(ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions): void { - if (true) { // TODO: temporarily disable some inputs until clonePartialCurve is implemented for B-spline curves - const processor = new HasStrokablePrimitiveProcessor(options.preserveEllipticalArcs, true); - baseCurve.announceToCurveProcessor(processor); - if (processor.claimResult()) - return; - } testOffsetBothSides(ck, allGeometry, delta, baseCurve, options); // toggle ellipse preservation if (true) { @@ -742,6 +735,20 @@ function testOffset(ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, b testOffsetBothSides(ck, allGeometry, delta, baseCurve, opts); } } + // test arc joins + if (true) { + const opts = options.clone(); + opts.jointOptions.minArcDegrees = opts.jointOptions.minArcDegrees > 0 ? 0 : 180; + testOffsetBothSides(ck, allGeometry, delta, baseCurve, opts); + } +} + +function testOffsetWrapper(ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions): void { + const rangeX = options.leftOffsetDistance + baseCurve.range().xLength(); + delta.x += rangeX; + testOffset(ck, allGeometry, delta, baseCurve, options); + delta.x += rangeX; + delta.y = 0; } describe("CloneSplitCurves", () => { @@ -929,18 +936,39 @@ describe("CloneSplitCurves", () => { const allGeometry: GeometryQuery[] = []; const ck = new Checker(); const delta = Point2d.createZero(); - const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/testInputs/curve/offsetCurve.imjs", "utf8"))) as CurveChain[]; const offsetDistance = 0.5; const options = new OffsetOptions(offsetDistance); - for (const chain of inputs) { - if (chain instanceof Path || chain instanceof Loop) { - const halfRangeX = offsetDistance + chain.range().xLength() / 2; - delta.x += halfRangeX; - testOffset(ck, allGeometry, delta, chain, options); - delta.x += halfRangeX; - delta.y = 0; - } - } + + // sample chains + const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/testInputs/curve/offsetCurve.imjs", "utf8"))) as CurveChain[]; + for (const chain of inputs) + if (chain instanceof Path || chain instanceof Loop) + testOffsetWrapper(ck, allGeometry, delta, chain, options); + + // Bezier splines + const poles: Point3d[] = [Point3d.createZero(), Point3d.create(1,1), Point3d.create(2,-1), Point3d.create(3,2), Point3d.create(4,-2), Point3d.create(5,3)]; + const mirrorPoles: Point3d[] = []; + poles.forEach((pt) => {mirrorPoles.push(Point3d.create(-pt.x, pt.y));}); + mirrorPoles.reverse(); + const rotatedPoles: Point3d[] = []; + mirrorPoles.forEach((pt) => {rotatedPoles.push(Point3d.create(pt.x, -pt.y));}); + testOffsetWrapper(ck, allGeometry, delta, Path.create(BezierCurve3d.create(mirrorPoles)!, BezierCurve3d.create(poles)!), options); + testOffsetWrapper(ck, allGeometry, delta, Path.create(BezierCurve3d.create(rotatedPoles)!, BezierCurve3d.create(poles)!), options); + + // unclamped splines + const knots: number[] = [1,2,3,4,5,6,7,8]; + const curve = BSplineCurve3dH.create(poles, knots, 4)!; + const mirrorCurve = BSplineCurve3dH.create(mirrorPoles, knots, 4)!; + const rotatedCurve = BSplineCurve3dH.create(rotatedPoles, knots, 4)!; + const scaleUp = Transform.createScaleAboutPoint(Point3d.createZero(), 5); + curve.tryTransformInPlace(scaleUp); + mirrorCurve.tryTransformInPlace(scaleUp); + rotatedCurve.tryTransformInPlace(scaleUp); + testOffsetWrapper(ck, allGeometry, delta, Path.create(mirrorCurve, LineSegment3d.create(mirrorCurve.endPoint(), curve.startPoint()), curve), options); + testOffsetWrapper(ck, allGeometry, delta, Path.create(rotatedCurve, LineSegment3d.create(rotatedCurve.endPoint(), curve.startPoint()), curve), options); + // save unclamped, clamped, control polygon, start point, end point + GeometryCoreTestIO.saveGeometry([curve, curve.clonePartialCurve(0,1), LineString3d.create(curve.copyXYZFloat64Array(true)), Arc3d.createXY(curve.startPoint(), 0.5), Arc3d.createXY(curve.endPoint(), 0.5)], "BSplineCurve", "Unclamped"); + GeometryCoreTestIO.saveGeometry(allGeometry, "RegionOps", "OffsetCurves"); expect(ck.getNumErrors()).equals(0); }); diff --git a/core/hypermodeling/CHANGELOG.json b/core/hypermodeling/CHANGELOG.json index 346273f7b996..da6d09ad0c6d 100644 --- a/core/hypermodeling/CHANGELOG.json +++ b/core/hypermodeling/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/hypermodeling-frontend", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/hypermodeling-frontend_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/hypermodeling-frontend_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/hypermodeling-frontend_v3.0.0", diff --git a/core/hypermodeling/CHANGELOG.md b/core/hypermodeling/CHANGELOG.md index 4de985deef5e..23ba5f1ca56b 100644 --- a/core/hypermodeling/CHANGELOG.md +++ b/core/hypermodeling/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/hypermodeling-frontend -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/hypermodeling/package.json b/core/hypermodeling/package.json index 094dd4f087ed..0bb155b00d7c 100644 --- a/core/hypermodeling/package.json +++ b/core/hypermodeling/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/hypermodeling-frontend", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js hypermodeling package", "main": "lib/cjs/hypermodeling-frontend.js", "module": "lib/esm/hypermodeling-frontend.js", "typings": "lib/cjs/hypermodeling-frontend", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s copy:public && npm run -s build:cjs", @@ -38,10 +37,10 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-frontend": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-frontend": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21" }, "devDependencies": { "@itwin/build-tools": "workspace:*", diff --git a/core/i18n/CHANGELOG.json b/core/i18n/CHANGELOG.json index 72ac05b21eb3..e6e6c194daf2 100644 --- a/core/i18n/CHANGELOG.json +++ b/core/i18n/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-i18n", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-i18n_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-i18n_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-i18n_v3.0.0", diff --git a/core/i18n/CHANGELOG.md b/core/i18n/CHANGELOG.md index 9d0b6d1fd32e..4d562dd80dde 100644 --- a/core/i18n/CHANGELOG.md +++ b/core/i18n/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-i18n -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/i18n/package.json b/core/i18n/package.json index b8438ad22167..8bf0995c8771 100644 --- a/core/i18n/package.json +++ b/core/i18n/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-i18n", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js localization code", "main": "lib/cjs/core-i18n.js", "module": "lib/esm/core-i18n.js", "typings": "lib/cjs/core-i18n", - "imodeljsSharedLibrary": true, "license": "MIT", "repository": { "type": "git", @@ -33,7 +32,7 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21" }, "//devDependencies": [ "NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install", diff --git a/core/markup/CHANGELOG.json b/core/markup/CHANGELOG.json index 2a7931b030aa..7652b07c32ed 100644 --- a/core/markup/CHANGELOG.json +++ b/core/markup/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-markup", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-markup_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-markup_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-markup_v3.0.0", diff --git a/core/markup/CHANGELOG.md b/core/markup/CHANGELOG.md index 344b0b1931c8..30515853b7f8 100644 --- a/core/markup/CHANGELOG.md +++ b/core/markup/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-markup -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/markup/package.json b/core/markup/package.json index f0cccb2d6f27..a5bcf0f8b01d 100644 --- a/core/markup/package.json +++ b/core/markup/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-markup", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js markup package", "main": "lib/cjs/core-markup.js", "module": "lib/esm/core-markup.js", "typings": "lib/cjs/core-markup", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s copy:public && npm run -s build:cjs", @@ -43,10 +42,10 @@ "@svgdotjs/svg.js": "3.0.13" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-frontend": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-frontend": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21" }, "devDependencies": { "@itwin/build-tools": "workspace:*", diff --git a/core/mobile/CHANGELOG.json b/core/mobile/CHANGELOG.json index 9d6cc96dbeff..99eb4cb3578e 100644 --- a/core/mobile/CHANGELOG.json +++ b/core/mobile/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-mobile", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-mobile_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-mobile_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-mobile_v3.0.0", diff --git a/core/mobile/CHANGELOG.md b/core/mobile/CHANGELOG.md index 662b40100bba..292be5de8feb 100644 --- a/core/mobile/CHANGELOG.md +++ b/core/mobile/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-mobile -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/mobile/package.json b/core/mobile/package.json index a13a44699a70..a1a12d31400b 100644 --- a/core/mobile/package.json +++ b/core/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/core-mobile", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js MobileHost and MobileApp", "license": "MIT", "engines": { @@ -32,11 +32,11 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-backend": "workspace:^3.1.0-dev.33", - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-frontend": "workspace:^3.1.0-dev.33", - "@itwin/presentation-common": "workspace:^3.1.0-dev.33" + "@itwin/core-backend": "workspace:^3.2.0-dev.21", + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-frontend": "workspace:^3.2.0-dev.21", + "@itwin/presentation-common": "workspace:^3.2.0-dev.21" }, "dependencies": { "deep-assign": "^2.0.0", diff --git a/core/orbitgt/CHANGELOG.json b/core/orbitgt/CHANGELOG.json index 9922d20b7cf5..8b0052c45dde 100644 --- a/core/orbitgt/CHANGELOG.json +++ b/core/orbitgt/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-orbitgt", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-orbitgt_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-orbitgt_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-orbitgt_v3.0.0", diff --git a/core/orbitgt/CHANGELOG.md b/core/orbitgt/CHANGELOG.md index 00f773f58e8c..80d0239418a3 100644 --- a/core/orbitgt/CHANGELOG.md +++ b/core/orbitgt/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-orbitgt -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/orbitgt/package.json b/core/orbitgt/package.json index 870151398650..8631047f74eb 100644 --- a/core/orbitgt/package.json +++ b/core/orbitgt/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-orbitgt", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "", "main": "lib/cjs/core-orbitgt.js", "module": "lib/esm/core-orbitgt.js", "typings": "lib/cjs/core-orbitgt", - "imodeljsSharedLibrary": true, "license": "MIT", "scripts": { "build": "npm run -s build:cjs", diff --git a/core/quantity/CHANGELOG.json b/core/quantity/CHANGELOG.json index 02632f999925..5546d1a5ed89 100644 --- a/core/quantity/CHANGELOG.json +++ b/core/quantity/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-quantity", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-quantity_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-quantity_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-quantity_v3.0.0", diff --git a/core/quantity/CHANGELOG.md b/core/quantity/CHANGELOG.md index c3ea4901c3d3..1e553ed55512 100644 --- a/core/quantity/CHANGELOG.md +++ b/core/quantity/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-quantity -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/quantity/package.json b/core/quantity/package.json index d411bcad3426..6b9108bdebfb 100644 --- a/core/quantity/package.json +++ b/core/quantity/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-quantity", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "Quantity parsing, formatting and conversions for iModel.js", "main": "lib/cjs/core-quantity.js", "module": "lib/esm/core-quantity.js", "typings": "lib/cjs/core-quantity", - "imodeljsSharedLibrary": true, "license": "MIT", "repository": { "type": "git", @@ -53,7 +52,7 @@ "typescript": "~4.4.0" }, "peerDependencies": { - "@itwin/core-bentley": "workspace:^3.1.0-dev.33" + "@itwin/core-bentley": "workspace:^3.2.0-dev.21" }, "nyc": { "extends": "./node_modules/@itwin/build-tools/.nycrc" diff --git a/core/telemetry/CHANGELOG.json b/core/telemetry/CHANGELOG.json index 26b066c804a4..24f591c01928 100644 --- a/core/telemetry/CHANGELOG.json +++ b/core/telemetry/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/core-telemetry", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-telemetry_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-telemetry_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/core-telemetry_v3.0.0", diff --git a/core/telemetry/CHANGELOG.md b/core/telemetry/CHANGELOG.md index 144c24cce648..b233538213f7 100644 --- a/core/telemetry/CHANGELOG.md +++ b/core/telemetry/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/core-telemetry -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/telemetry/package.json b/core/telemetry/package.json index a5d5e3f6067a..aacb5c26364f 100644 --- a/core/telemetry/package.json +++ b/core/telemetry/package.json @@ -1,11 +1,10 @@ { "name": "@itwin/core-telemetry", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "iTwin.js Telemetry Client", "main": "lib/cjs/core-telemetry.js", "module": "lib/esm/core-telemetry.js", "typings": "lib/cjs/core-telemetry", - "imodeljsSharedLibrary": true, "license": "MIT", "repository": { "type": "git", diff --git a/core/transformer/CHANGELOG.json b/core/transformer/CHANGELOG.json index 5a356298cc83..978fdc569da4 100644 --- a/core/transformer/CHANGELOG.json +++ b/core/transformer/CHANGELOG.json @@ -1,6 +1,57 @@ { "name": "@itwin/core-transformer", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/core-transformer_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/core-transformer_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": { + "none": [ + { + "comment": "add ignoreDeadPredecessors option to transformer, deprecate direct importer options access" + }, + { + "comment": "Upgrade target to ES2019" + }, + { + "comment": "rename contextId -> iTwinId" + }, + { + "comment": "rename to @itwin/core-transformer" + }, + { + "comment": "remove ClientRequestContext and its subclasses" + }, + { + "comment": "removed deprecated API surface" + }, + { + "comment": "remove ClientRequestContext.current" + }, + { + "comment": "Renamed all occurrences of the term revision0 to version0." + }, + { + "comment": "remove requestContext argument from importSchemas" + }, + { + "comment": "create new imodel-transformer package separate from backend package" + }, + { + "comment": "fix bug where element aspect export could be mishandled when the element was deferred" + }, + { + "comment": "add preserveElementIdsForFiltering option for transformations" + } + ] + } + }, { "version": "3.0.0", "tag": "@itwin/core-transformer_v3.0.0", diff --git a/core/transformer/CHANGELOG.md b/core/transformer/CHANGELOG.md index 991434324ce3..35aac2c0b79b 100644 --- a/core/transformer/CHANGELOG.md +++ b/core/transformer/CHANGELOG.md @@ -1,6 +1,29 @@ # Change Log - @itwin/core-transformer -This log was last generated on Fri, 20 Aug 2021 20:34:29 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +### Updates + +- add ignoreDeadPredecessors option to transformer, deprecate direct importer options access +- Upgrade target to ES2019 +- rename contextId -> iTwinId +- rename to @itwin/core-transformer +- remove ClientRequestContext and its subclasses +- removed deprecated API surface +- remove ClientRequestContext.current +- Renamed all occurrences of the term revision0 to version0. +- remove requestContext argument from importSchemas +- create new imodel-transformer package separate from backend package +- fix bug where element aspect export could be mishandled when the element was deferred +- add preserveElementIdsForFiltering option for transformations ## 3.0.0 Fri, 20 Aug 2021 20:34:29 GMT diff --git a/core/transformer/package.json b/core/transformer/package.json index f34f22bf6b8c..1d89209af98d 100644 --- a/core/transformer/package.json +++ b/core/transformer/package.json @@ -1,6 +1,6 @@ { "name": "@itwin/core-transformer", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "API for exporting an iModel's parts and also importing them into another iModel", "main": "lib/cjs/core-transformer.js", "typings": "lib/cjs/core-transformer", @@ -37,11 +37,11 @@ "url": "http://www.bentley.com" }, "peerDependencies": { - "@itwin/core-backend": "workspace:^3.1.0-dev.33", - "@itwin/core-bentley": "workspace:^3.1.0-dev.33", - "@itwin/core-common": "workspace:^3.1.0-dev.33", - "@itwin/core-geometry": "workspace:^3.1.0-dev.33", - "@itwin/ecschema-metadata": "workspace:^3.1.0-dev.33" + "@itwin/core-backend": "workspace:^3.2.0-dev.21", + "@itwin/core-bentley": "workspace:^3.2.0-dev.21", + "@itwin/core-common": "workspace:^3.2.0-dev.21", + "@itwin/core-geometry": "workspace:^3.2.0-dev.21", + "@itwin/ecschema-metadata": "workspace:^3.2.0-dev.21" }, "//devDependencies": [ "NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install", diff --git a/core/transformer/src/IModelExporter.ts b/core/transformer/src/IModelExporter.ts index e2a323398110..c7e8d8f8a716 100644 --- a/core/transformer/src/IModelExporter.ts +++ b/core/transformer/src/IModelExporter.ts @@ -6,7 +6,7 @@ * @module iModels */ -import { AccessToken, assert, DbResult, Id64, Id64String, IModelStatus, Logger } from "@itwin/core-bentley"; +import { AccessToken, assert, DbResult, Id64, Id64String, IModelStatus, Logger, YieldManager } from "@itwin/core-bentley"; import { ECVersion, Schema, SchemaKey } from "@itwin/ecschema-metadata"; import { CodeSpec, FontProps, IModel, IModelError } from "@itwin/core-common"; import { TransformerLoggerCategory } from "./TransformerLoggerCategory"; @@ -440,6 +440,8 @@ export class IModelExporter { return this.trackProgress(); } + private _yieldManager = new YieldManager(); + /** Export the model contents. * @param modelId The only required parameter * @param elementClassFullName Can be optionally specified if the goal is to export a subset of the model contents @@ -475,6 +477,7 @@ export class IModelExporter { } while (DbResult.BE_SQLITE_ROW === statement.step()) { await this.exportElement(statement.getValue(0).getId()); + await this._yieldManager.allowYield(); } }); } @@ -638,6 +641,7 @@ export class IModelExporter { const relInstanceId: Id64String = statement.getValue(0).getId(); const relProps: RelationshipProps = this.sourceDb.relationships.getInstanceProps(baseRelClassFullName, relInstanceId); await this.exportRelationship(relProps.classFullName, relInstanceId); // must call exportRelationship using the actual classFullName, not baseRelClassFullName + await this._yieldManager.allowYield(); } }); } diff --git a/core/transformer/src/IModelTransformer.ts b/core/transformer/src/IModelTransformer.ts index 63ff7e11b7e0..cec69c698e8a 100644 --- a/core/transformer/src/IModelTransformer.ts +++ b/core/transformer/src/IModelTransformer.ts @@ -7,7 +7,7 @@ */ import * as path from "path"; import * as Semver from "semver"; -import { AccessToken, DbResult, Guid, Id64, Id64Set, Id64String, IModelStatus, Logger, LogLevel, MarkRequired } from "@itwin/core-bentley"; +import { AccessToken, DbResult, Guid, Id64, Id64Set, Id64String, IModelStatus, Logger, LogLevel, MarkRequired, YieldManager } from "@itwin/core-bentley"; import * as ECSchemaMetaData from "@itwin/ecschema-metadata"; import { Point3d, Transform } from "@itwin/core-geometry"; import { @@ -704,6 +704,8 @@ export class IModelTransformer extends IModelExportHandler { }); } + private _yieldManager = new YieldManager(); + /** Detect Relationship deletes using ExternalSourceAspects in the target iModel and a *brute force* comparison against relationships in the source iModel. * @see processChanges * @note This method is called from [[processAll]] and is not needed by [[processChanges]], so it only needs to be called directly when processing a subset of an iModel. @@ -715,7 +717,7 @@ export class IModelTransformer extends IModelExportHandler { } const aspectDeleteIds: Id64String[] = []; const sql = `SELECT ECInstanceId,Identifier,JsonProperties FROM ${ExternalSourceAspect.classFullName} aspect WHERE aspect.Scope.Id=:scopeId AND aspect.Kind=:kind`; - this.targetDb.withPreparedStatement(sql, (statement: ECSqlStatement): void => { + await this.targetDb.withPreparedStatement(sql, async (statement: ECSqlStatement) => { statement.bindId("scopeId", this.targetScopeElementId); statement.bindString("kind", ExternalSourceAspect.Kind.Relationship); while (DbResult.BE_SQLITE_ROW === statement.step()) { @@ -728,6 +730,7 @@ export class IModelTransformer extends IModelExportHandler { } aspectDeleteIds.push(statement.getValue(0).getId()); } + await this._yieldManager.allowYield(); } }); this.targetDb.elements.deleteAspect(aspectDeleteIds); diff --git a/core/webgl-compatibility/CHANGELOG.json b/core/webgl-compatibility/CHANGELOG.json index 377ffddf5df6..458b8d7a845f 100644 --- a/core/webgl-compatibility/CHANGELOG.json +++ b/core/webgl-compatibility/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@itwin/webgl-compatibility", "entries": [ + { + "version": "3.0.2", + "tag": "@itwin/webgl-compatibility_v3.0.2", + "date": "Thu, 10 Mar 2022 21:18:13 GMT", + "comments": {} + }, + { + "version": "3.0.1", + "tag": "@itwin/webgl-compatibility_v3.0.1", + "date": "Thu, 24 Feb 2022 15:26:55 GMT", + "comments": {} + }, { "version": "3.0.0", "tag": "@itwin/webgl-compatibility_v3.0.0", diff --git a/core/webgl-compatibility/CHANGELOG.md b/core/webgl-compatibility/CHANGELOG.md index d2edb182735d..0b26102f53f7 100644 --- a/core/webgl-compatibility/CHANGELOG.md +++ b/core/webgl-compatibility/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @itwin/webgl-compatibility -This log was last generated on Mon, 24 Jan 2022 14:00:52 GMT and should not be manually modified. +This log was last generated on Thu, 10 Mar 2022 21:18:13 GMT and should not be manually modified. + +## 3.0.2 +Thu, 10 Mar 2022 21:18:13 GMT + +_Version update only_ + +## 3.0.1 +Thu, 24 Feb 2022 15:26:55 GMT + +_Version update only_ ## 3.0.0 Mon, 24 Jan 2022 14:00:52 GMT diff --git a/core/webgl-compatibility/package.json b/core/webgl-compatibility/package.json index 2b4b3a362e62..ecfb0737ea59 100644 --- a/core/webgl-compatibility/package.json +++ b/core/webgl-compatibility/package.json @@ -1,12 +1,11 @@ { "name": "@itwin/webgl-compatibility", - "version": "3.1.0-dev.33", + "version": "3.2.0-dev.21", "description": "APIs for determining the level of compatibility of a browser+device with the iTwin.js rendering system.", "license": "MIT", "main": "lib/cjs/webgl-compatibility.js", "module": "lib/esm/webgl-compatibility.js", "typings": "lib/cjs/webgl-compatibility.js", - "imodeljsSharedLibrary": true, "scripts": { "build": "npm run -s build:cjs", "build:ci": "npm run -s build && npm run -s build:esm", diff --git a/core/webgl-compatibility/src/Capabilities.ts b/core/webgl-compatibility/src/Capabilities.ts index 498b7dd10d90..71c27725142a 100644 --- a/core/webgl-compatibility/src/Capabilities.ts +++ b/core/webgl-compatibility/src/Capabilities.ts @@ -73,6 +73,23 @@ const buggyIntelMatchers = [ /ANGLE \(Intel, Intel\(R\) (U)?HD Graphics 6(2|3)0 Direct3D11/, ]; +// Regexes to match as many Intel integrated GPUs as possible. +// https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units +const integratedIntelGpuMatchers = [ + /(U)?HD Graphics/, + /Iris/, +]; + +function isIntegratedGraphics(args: {unmaskedVendor?: string, unmaskedRenderer?: string}): boolean { + if (args.unmaskedRenderer && args.unmaskedRenderer.includes("Intel") && integratedIntelGpuMatchers.some((x) => x.test(args.unmaskedRenderer!))) + return true; + + // NB: For now, we do not attempt to detect AMD integrated graphics. + // It appears that AMD integrated graphics are not usually paired with a graphics card so detecting integrated usage there is less important than Intel. + + return false; +} + /** Describes the rendering capabilities of the host system. * @internal */ @@ -316,6 +333,7 @@ export class Capabilities { missingOptionalFeatures, unmaskedRenderer, unmaskedVendor, + usingIntegratedGraphics: isIntegratedGraphics({unmaskedVendor, unmaskedRenderer}), driverBugs: { ...this._driverBugs }, userAgent: navigator.userAgent, createdContext: gl, diff --git a/core/webgl-compatibility/src/RenderCompatibility.ts b/core/webgl-compatibility/src/RenderCompatibility.ts index 26e3fab8f598..612422f7e38d 100644 --- a/core/webgl-compatibility/src/RenderCompatibility.ts +++ b/core/webgl-compatibility/src/RenderCompatibility.ts @@ -109,6 +109,10 @@ export interface WebGLRenderCompatibilityInfo { unmaskedRenderer?: string; /** The vendor string reported by this client's graphics driver. */ unmaskedVendor?: string; + /** If true, there is a likelihood that integrated graphics are being used. This can be used to warn users on systems with both integrated graphics and dedicated graphics that they should try to switch to their dedicated graphics for better performance. + * @note This property has the possibility of providing false positives and negatives. A user should use this property mainly as a hint and manually verify what graphics chip is being used. + */ + usingIntegratedGraphics?: boolean; /** If WebGL context creation failed, an error message supplied by the browser. */ contextErrorMessage?: string; /** The WebGL context created by the browser and used to generate the compatibility report. */ diff --git a/core/webgl-compatibility/src/test/Compatibility.test.ts b/core/webgl-compatibility/src/test/Compatibility.test.ts index 27bfcd03bd58..517915c426b3 100644 --- a/core/webgl-compatibility/src/test/Compatibility.test.ts +++ b/core/webgl-compatibility/src/test/Compatibility.test.ts @@ -214,4 +214,30 @@ describe("Render Compatibility", () => { expect(caps.driverBugs.fragDepthDoesNotDisableEarlyZ).to.equal(expected); } }); + + it("detects integrated and dedicated graphics", () => { + const renderers = [ + [ "ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], + [ "ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], + [ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true ], + [ "Intel(R) Iris(TM) Graphics 6100", true ], + [ "ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false ], + ]; + + for (const renderer of renderers) { + overriddenFunctions.overrideCreateContext((ctx: WebGLContext, pname: number) => { + const ext = ctx.getExtension("WEBGL_debug_renderer_info"); + if (ext && pname === ext.UNMASKED_RENDERER_WEBGL) + return renderer[0]; + + return undefined; + }); + + const context = makeTestContext(true); + const caps = new Capabilities(); + const compatibility = caps.init(context); + + expect(compatibility.usingIntegratedGraphics).to.equal(renderer[1]); + } + }); }); diff --git a/docs/changehistory/1.10.0.md b/docs/changehistory/1.10.0.md index 97e3a10e3ba6..60449aa77de8 100644 --- a/docs/changehistory/1.10.0.md +++ b/docs/changehistory/1.10.0.md @@ -13,7 +13,7 @@ iModel.js will now perform smooth animations when changing between saved views, ## IModel Transformation and Data Exchange [IModelExporter](https://www.imodeljs.org/v1/reference/imodeljs-transformer/imodels/imodelexporter), [IModelTransformer](https://www.imodeljs.org/v1/reference/imodeljs-transformer/imodels/imodeltransformer), and [IModelImporter](https://www.imodeljs.org/v1/reference/imodeljs-transformer/imodels/imodelimporter) are now beta and provide low-level functionality needed for iModel transformation and data exchange. -See the [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md) article for more information. +See the [iModel Transformation and Data Exchange](../learning/transformer/index.md) article for more information. ## High-DPI display support diff --git a/docs/changehistory/1.5.0.md b/docs/changehistory/1.5.0.md index b07759e3040f..fc7952c192dd 100644 --- a/docs/changehistory/1.5.0.md +++ b/docs/changehistory/1.5.0.md @@ -18,7 +18,7 @@ version: '1.5.0' ## Blank IModelConnections - The new method `IModelConnection.createBlank` provides a way for applications to create an `IModelConnection` that is not connected to an iModel or a backend. This is useful for using iModel.js to show *just* Reality data (reality meshes, point clouds, terrain, etc.), background maps, and other non-iModel-based graphics without requiring a backend server. -- There is also a new convenience method [SpatialViewState.createBlank](https://www.imodeljs.org/v1/reference/imodeljs-frontend/imodelconnection/imodelconnection/#createblank) to create a *blank* spatial view appropriate for these non-iModel based visualizations. See the [Blank Connection]($docs/learning/frontend/BlankConnection.md) learning article for further details. +- There is also a new convenience method [SpatialViewState.createBlank](https://www.imodeljs.org/v1/reference/imodeljs-frontend/imodelconnection/imodelconnection/#createblank) to create a *blank* spatial view appropriate for these non-iModel based visualizations. See the [Blank Connection](../learning/frontend/BlankConnection.md) learning article for further details. ## Favorite Properties diff --git a/docs/changehistory/1.8.0.md b/docs/changehistory/1.8.0.md index 8fc2212d6369..cfd9873ba00e 100644 --- a/docs/changehistory/1.8.0.md +++ b/docs/changehistory/1.8.0.md @@ -16,7 +16,7 @@ When the cursor moves over the icon, a set of *Logo Cards* with notices and logo If the user clicks or taps on the iModel.js icon, a modal dialog opens showing the logo cards. -See [Logo Cards]($docs/learning/frontend/LogoCards.md) for more information. +See [Logo Cards](../learning/frontend/LogoCards.md) for more information. ## View-independent Geometry diff --git a/docs/changehistory/2.11.0.md b/docs/changehistory/2.11.0.md index 44d886f2f7c1..9b2558023b6a 100644 --- a/docs/changehistory/2.11.0.md +++ b/docs/changehistory/2.11.0.md @@ -198,7 +198,7 @@ Note that [DisplayStyleSettings.addExcludedElements]($common) and [DisplayStyleS In previous versions the method to open briefcases ([BriefcaseDb.open]($backend)) and standalone files (`StandaloneDb.open` renamed to `StandaloneDb.openFile`) provided options to upgrade the schemas in the iModel. This functionality has been now separated out, and there are separate methods to validate and upgrade the schemas in the iModel. As a result [OpenBriefcaseProps]($common) and [SnapshotOpenOptions]($common) do not include options to upgrade anymore. -See section on [Upgrading Schemas]($docs/learning/backend/IModelDb.md#upgrading-schemas-in-an-imodel) for more information. +See section on [Upgrading Schemas](../learning/backend/IModelDb.md#upgrading-schemas-in-an-imodel) for more information. ## Filtering in Property Grid @@ -296,7 +296,7 @@ A property value renderer for instance key values has been added, which allows u ### Breaking changes to `ContentRelatedInstances` -Behavior of `ContentRelatedInstances` specification used in content rules was changed. It used to include input instances into the result if all paths in `relationshipPaths` property had `count: "*"` and target class matched input instance class. The behavior was changed to match cases where steps `relationshipPaths` have `count` set to specific number - the result only includes instances resulting from step outputs. See [RelationshipPathSpecification documentation]($docs/presentation/Common-Rules/RelationshipPathSpecification.md) for more details and examples. +Behavior of `ContentRelatedInstances` specification used in content rules was changed. It used to include input instances into the result if all paths in `relationshipPaths` property had `count: "*"` and target class matched input instance class. The behavior was changed to match cases where steps `relationshipPaths` have `count` set to specific number - the result only includes instances resulting from step outputs. See [RelationshipPathSpecification documentation](../presentation/RelationshipPathSpecification.md) for more details and examples. Example: diff --git a/docs/changehistory/2.12.0.md b/docs/changehistory/2.12.0.md index 5d77f9ccea6a..f1cfe15d41f0 100644 --- a/docs/changehistory/2.12.0.md +++ b/docs/changehistory/2.12.0.md @@ -17,7 +17,7 @@ Updated recommended version of Electron from 10.1.3 to 11.1.0. Note that Electro ## IpcSocket for use with dedicated backends -For cases where a frontend and backend are explicitly paired (e.g. desktop and mobile apps), a more direct communication path is now supported via the [IpcSocket api]($docs/learning/IpcInterface.md). See the [Rpc vs Ipc learning article]($docs/learning/RpcVsIpc.md) for more details. +For cases where a frontend and backend are explicitly paired (e.g. desktop and mobile apps), a more direct communication path is now supported via the [IpcSocket api](../learning/IpcInterface.md). See the [Rpc vs Ipc learning article](../learning/RpcVsIpc.md) for more details. ## External textures diff --git a/docs/changehistory/2.13.0.md b/docs/changehistory/2.13.0.md index 3452af4cd5a2..ebdddcb22b05 100644 --- a/docs/changehistory/2.13.0.md +++ b/docs/changehistory/2.13.0.md @@ -170,8 +170,8 @@ Presentation.initialize({ ### Accessing selection in instance filter of content specifications Added a way to create and filter content that's related to given input through some ID type of property that is not part of a relationship. That can be done by -using [ContentInstancesOfSpecificClasses specification]($docs/presentation/content/ContentInstancesOfSpecificClasses.md) with an instance filter that makes use -of the newly added [SelectedInstanceKeys]($docs/presentation/content/ECExpressions.md#instance=filter) ECExpression symbol. Example: +using [ContentInstancesOfSpecificClasses specification](../presentation/content/ContentInstancesOfSpecificClasses.md) with an instance filter that makes use +of the newly added [SelectedInstanceKeys](../presentation/content/ECExpressions.md#instance=filter) ECExpression symbol. Example: ```json { @@ -198,7 +198,7 @@ Previously this was not possible, because there is no ECRelationship between `EC ### ECInstance ECExpression context method enhancements -Added lambda versions for [ECInstance ECExpression context]($docs/presentation/Advanced/ECExpressions.md#ecinstance) methods: `GetRelatedInstancesCount`, +Added lambda versions for [ECInstance ECExpression context](../presentation/Advanced/ECExpressions.md#ecinstance) methods: `GetRelatedInstancesCount`, `HasRelatedInstance`, `GetRelatedValue`. This allows using those methods without the need of an ECRelationship between "current" ECInstance and related ECInstance. Example: @@ -221,4 +221,3 @@ and related ECInstance. Example: ``` The above example returns `ECDbMeta:ECClassDef` instances only if there are `BisCore:Elements` of those classes. - diff --git a/docs/changehistory/2.15.0.md b/docs/changehistory/2.15.0.md index 2fab8c160bf3..455d6dbd2344 100644 --- a/docs/changehistory/2.15.0.md +++ b/docs/changehistory/2.15.0.md @@ -23,7 +23,7 @@ Clip volumes now nest. For example, if you define a view clip, a model clip grou ## Txn monitoring -[TxnManager]($backend) now has additional events for monitoring changes to the iModel resulting from [Txns]($docs/learning/InteractiveEditing.md), including: +[TxnManager]($backend) now has additional events for monitoring changes to the iModel resulting from [Txns](../learning/InteractiveEditing.md), including: - [TxnManager.onModelsChanged]($backend) for changes to the properties of [Model]($backend)s and - [TxnManager.onModelGeometryChanged]($backend) for changes to the geometry contained within [GeometricModel]($backend)s. diff --git a/docs/changehistory/2.16.0.md b/docs/changehistory/2.16.0.md index 3062025ff790..f2d474ef4235 100644 --- a/docs/changehistory/2.16.0.md +++ b/docs/changehistory/2.16.0.md @@ -100,15 +100,15 @@ instance. The related instance, possibly being a of a different ECClass, might h ### Custom category renderers -[VirtualizedPropertyGrid]($components-react) now allows developers to fully customize displayed category contents, if the category is assigned a custom renderer via Presentation Rules. You can read more about that in our [Category customization learning page]($docs/presentation/Customization/PropertyCategoryRenderers.md). +[VirtualizedPropertyGrid]($components-react) now allows developers to fully customize displayed category contents, if the category is assigned a custom renderer via Presentation Rules. You can read more about that in our [Category customization learning page](../presentation/Content/PropertyCategoryRenderers.md). ### Custom category nesting -A new `parentId` attribute was added to [PropertyCategorySpecification]($presentation-common) to provide nesting abilities. See more details in our [property categorization page]($docs/presentation/Content/PropertyCategorization.md#category-nesting). +A new `parentId` attribute was added to [PropertyCategorySpecification]($presentation-common) to provide nesting abilities. See more details in our [property categorization page](../presentation/Content/PropertyCategorization.md#category-nesting). ### Presentation rule schema requirements -A new `requiredSchemas` attribute was added to [Ruleset]($presentation-common), [Rule]($presentation-common) and [SubCondition]($presentation-common) definitions. The attribute allows specifying ECSchema requirements for rules and avoid using them when requirements are not met. See the [schema requirements page]($docs/presentation/Advanced/SchemaRequirements.md) for more details. +A new `requiredSchemas` attribute was added to [Ruleset]($presentation-common), [Rule]($presentation-common) and [SubCondition]($presentation-common) definitions. The attribute allows specifying ECSchema requirements for rules and avoid using them when requirements are not met. See the [schema requirements page](../presentation/Advanced/SchemaRequirements.md) for more details. ## Promoted APIs diff --git a/docs/changehistory/2.17.0.md b/docs/changehistory/2.17.0.md index beb76461a842..78caa78bf5ac 100644 --- a/docs/changehistory/2.17.0.md +++ b/docs/changehistory/2.17.0.md @@ -30,6 +30,7 @@ Within [IpcApp]($frontend)-based applications, [BriefcaseConnection]($frontend)s ## Reality model APIs Several APIs relating to reality models have been introduced, in some cases replacing previous `beta` APIs. A reality model can be displayed in a [Viewport]($frontend) in one of two ways: + * Adding to the [ViewState]($frontend)'s [ModelSelector]($backend) the Id of a persistent [SpatialModelState]($frontend) containing a URL pointing to a 3d tileset; or * Attaching to the [DisplayStyleState]($frontend) a [ContextRealityModel]($common) with a URL pointing to a 3d tileset. @@ -45,7 +46,7 @@ A reality model displaying simple building meshes for locations all over the wor ## Popout Widgets -IModelApps, that use AppUi version "2", can now specify if a Widget can support being "popped-out" to a child popup window. The child window runs in the same javascript context as the parent application window. See [Child Window Manager]($docs/learning/ui/appui-react/ChildWindows.md) for more details. +IModelApps, that use AppUi version "2", can now specify if a Widget can support being "popped-out" to a child popup window. The child window runs in the same javascript context as the parent application window. See [Child Window Manager](../learning/ui/appui-react/ChildWindows.md) for more details. ## External textures @@ -67,7 +68,7 @@ Disabling this feature is not recommended and will incur a performance penalty. ## ECClass Ids in changed events -The events [TxnManager.onElementsChanged]($backend) and [TxnManager.onModelsChanged]($backend) now include the Id of each changed entity's [ECClass]($docs/bis/intro/glossary/#ecclass). The [OrderedId64Array]($core-bentley) properties of [TxnChangedEntities]($backend) are deprecated in favor of the new [EntityIdAndClassIdIterable]($common) properties. +The events [TxnManager.onElementsChanged]($backend) and [TxnManager.onModelsChanged]($backend) now include the Id of each changed entity's [ECClass](../bis/intro/glossary/#ecclass). The [OrderedId64Array]($core-bentley) properties of [TxnChangedEntities]($backend) are deprecated in favor of the new [EntityIdAndClassIdIterable]($common) properties. ## Presentation @@ -106,6 +107,7 @@ The arguments for the @beta protected static methods called during modifications * [ElementAspect]($backend) `[onInsert, onInserted, onUpdate, onUpdated, onDelete, onDeleted]` In addition, new protected static methods were added: + * [Element]($backend) `[onChildInsert, onChildInserted, onChildUpdate, onChildUpdated, onChildDelete, onChildDeleted, onChildAdd, onChildAdded, onChildDrop, onChildDropped]` ### [@itwin/webgl-compatibility](https://www.itwinjs.org/reference/webgl-compatibility/) @@ -144,4 +146,3 @@ To make it easier to use async APIs while exporting a schema, [IModelExportHandl [IModelTransformer.shouldExportSchema]($transformer) now gets a [SchemaKey]($ecschema-metadata) schema key as argument, instead of a full [Schema]($ecschema-metadata). If you need to check the full schema, return `true` in shouldExportSchema and in [IModelExportHandler.onExportSchema]($transformer), you can use the schema object to check and then return early. - diff --git a/docs/changehistory/3.0.0.md b/docs/changehistory/3.0.0.md index 11bae5549468..b0d87003b50d 100644 --- a/docs/changehistory/3.0.0.md +++ b/docs/changehistory/3.0.0.md @@ -46,7 +46,7 @@ Many of the enhancements introduced in iTwin.js 3.0 were directly motivated by f #### Documentation -A collection of [learning articles]($docs/learning/display/index.md) has been assembled to provide an overview of the features provided by the display system, illustrated by interactive samples. +A collection of [learning articles](../learning/display/index.md) has been assembled to provide an overview of the features provided by the display system, illustrated by interactive samples. #### Viewport.zoomToElements improvements @@ -185,7 +185,7 @@ Improvements were made to the performance of [ParticleCollectionBuilder]($fronte #### Support for glTF graphics -[glTF](https://www.khronos.org/gltf/) has become the de facto standard format for 3d graphics on the web. Now you can create a [RenderGraphic]($frontend) from a glTF asset for use with [Decorators]($docs/learning/frontend/ViewDecorations), using [readGltfGraphics]($frontend). [This example]($docs/learning/frontend/ViewDecorations#gltf-decorations) demonstrates how to convert a glTF asset into a graphic and display it using a decorator. +[glTF](https://www.khronos.org/gltf/) has become the de facto standard format for 3d graphics on the web. Now you can create a [RenderGraphic]($frontend) from a glTF asset for use with [Decorators](../learning/frontend/ViewDecorations), using [readGltfGraphics]($frontend). [This example](../learning/frontend/ViewDecorations#gltf-decorations) demonstrates how to convert a glTF asset into a graphic and display it using a decorator. Note: `readGltfGraphics` targets the [glTF 2.0 specification](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html), but implementation of the full specification is an ongoing work in progress. The current implementation can successfully read many glTF assets, but if a particular asset fails to load or display properly, please [file an issue](https://github.com/iTwin/itwinjs-core/issues). @@ -218,11 +218,11 @@ Note: `readGltfGraphics` targets the [glTF 2.0 specification](https://www.khrono ##### Schema requirements A new `requiredSchemas` attribute has been added: [Ruleset.requiredSchemas]($presentation-common) and [RuleBase.requiredSchemas]($presentation-common). The attribute allows an easy way to filter presentation rules based on -ECSchemas / domains available in the iModel. See more details in the [Defining ECSchema Requirements for Presentation Rules]($docs/presentation/Advanced/SchemaRequirements) page. +ECSchemas / domains available in the iModel. See more details in the [Defining ECSchema Requirements for Presentation Rules](../presentation/Advanced/SchemaRequirements) page. ##### Conditional root node rules -Similar to [Child Node Rule]($docs/presentation/Hierarchies/ChildNodeRule), the [Root Node Rule]($docs/presentation/Hierarchies/RootNodeRule) now also has a [condition]($docs/presentation/Hierarchies/RootNodeRule#attribute-condition) attribute. The attribute provides more flexibility in enabling or disabling the rule, including the use of [ruleset variables]($docs/presentation/Advanced/RulesetVariables#using-variables-in-rule-condition). +Similar to [Child Node Rule](../presentation/Hierarchies/ChildNodeRule), the [Root Node Rule](../presentation/Hierarchies/RootNodeRule) now also has a [condition](../presentation/Hierarchies/RootNodeRule#attribute-condition) attribute. The attribute provides more flexibility in enabling or disabling the rule, including the use of [ruleset variables](../presentation/Advanced/RulesetVariables#using-variables-in-rule-condition). ##### More precise way to set class polymorphism @@ -503,7 +503,7 @@ requestContext.enter(); you can simply delete it. -This change mostly affects backend code. For backend [RPC]($docs/learning/RpcInterface.md) implementations, all *unhandled* exceptions will automatically be logged along the appropriate RPC metadata. For this reason, it often preferable to throw an exception rather than logging an error and returning a status in code that may or may not be called from RPC. +This change mostly affects backend code. For backend [RPC](../learning/RpcInterface.md) implementations, all _unhandled_ exceptions will automatically be logged along the appropriate RPC metadata. For this reason, it often preferable to throw an exception rather than logging an error and returning a status in code that may or may not be called from RPC. ### iModels @@ -531,7 +531,7 @@ Previously the concurrency "mode" was determined by applications when opening a Locks apply to Elements only. The "schema lock" is acquired by exclusively locking element id 0x1 (the root subject id). Models are locked via their modeled element (which has the same id as the model) -See the [ConcurrencyControl]($docs/learning/backend/ConcurrencyControl.md) learning article for more information and examples. +See the [ConcurrencyControl](../learning/backend/ConcurrencyControl.md) learning article for more information and examples. #### BriefcaseManager, BriefcaseDb, and IModelDb changes @@ -612,7 +612,7 @@ On the frontend the [GeoConverter]($frontend) class has been modified to accept #### BentleyError constructor no longer logs -In V2, the constructor of the base exception class [BentleyError]($core-bentley) accepted 5 arguments, the last 3 being optional. Arguments 3 and 4 were for logging the exception in the constructor itself. That is a bad idea, since exceptions are often handled and recovered in `catch` statements, so there is no actual "problem" to report. In that case the message in the log is either misleading or just plain wrong. Also, code in `catch` statements always has more "context" about *why* the error may have happened than the lower level code that threw (e.g. "invalid Id" vs. "invalid MyHashClass Id") so log messages from callers can be more helpful than from callees. Since every thrown exception must be caught *somewhere*, logging should be done when exceptions are caught, not when they're thrown. +In V2, the constructor of the base exception class [BentleyError]($core-bentley) accepted 5 arguments, the last 3 being optional. Arguments 3 and 4 were for logging the exception in the constructor itself. That is a bad idea, since exceptions are often handled and recovered in `catch` statements, so there is no actual "problem" to report. In that case the message in the log is either misleading or just plain wrong. Also, code in `catch` statements always has more "context" about _why_ the error may have happened than the lower level code that threw (e.g. "invalid Id" vs. "invalid MyHashClass Id") so log messages from callers can be more helpful than from callees. Since every thrown exception must be caught _somewhere_, logging should be done when exceptions are caught, not when they're thrown. The [BentleyError]($core-bentley) constructor now accepts 3 arguments, the last argument (`metaData`) is optional. The previous `log` and `category` arguments were removed. If your code passed 5 arguments, remove the 3rd and 4th. If you previously passed 3 or 4 arguments, just leave the first two. Also, the previous version of the constructor required the metaData argument to be a function that returns an object. It may now also just be an object. @@ -1628,8 +1628,8 @@ A number of packages have been renamed to use the @itwin scope rather than the @ | `IModelApp.settings` | [IModelApp.userPreferences]($frontend) | | `IModelConnection.Models.loaded` | use `for..of` to iterate and `getLoaded` to look up by Id | | `IModelConnection.Views.saveThumbnail` | use IPC and `IModelDb.saveThumbnail` | -| `IOidcFrontendClient` | *eliminated* | -| `isIOidcFrontendClient` | *eliminated* | +| `IOidcFrontendClient` | _eliminated_ | +| `isIOidcFrontendClient` | _eliminated_ | | `OidcBrowserClient` | `BrowserAuthorizationClient` in `@itwin/browser-authorization` | | `OidcFrontendClientConfiguration` | `BrowserAuthorizationClientConfiguration` in `@itwin/browser-authorization` | | `QuantityFormatter.onActiveUnitSystemChanged` | [QuantityFormatter.onActiveFormattingUnitSystemChanged]($frontend) | @@ -1644,7 +1644,7 @@ A number of packages have been renamed to use the @itwin scope rather than the @ | `Viewport.featureOverrideProvider` | [Viewport.featureOverrideProviders]($frontend) | | `Viewport.setFlashed` | [Viewport.flashedId]($frontend) | | `Viewport.setRedrawPending` | [Viewport.requestRedraw]($frontend) | -| `WebAppViewer` | *eliminated* | +| `WebAppViewer` | _eliminated_ | | `NativeAppAuthorization` | Moved to @iTwin/auth-clients repo as `ElectronRendererAuthorization` | ### @itwin/core-geometry @@ -1668,16 +1668,16 @@ SAML support has officially been dropped as a supported workflow. All related AP | `OidcDelegationClient` | `DelegationAuthorizationClient` | | `BackendAuthorizationClient` | Moved to @iTwin/auth-clients as BrowserAuthorizationClient | | `AgentAuthorizationClient` | Moved to @iTwin/auth-clients as SerivceAuthorizationClient | -| `DelegationAuthorizationClient` | *removed* | +| `DelegationAuthorizationClient` | _removed_ | | `IntrospectionClient` | Moved to @iTwin/auth-clients | -| `ImsAuthorizationClient` | *removed* | +| `ImsAuthorizationClient` | _removed_ | ### @itwin/appui-abstract | Removed | Replacement | | ----------------------------- | -------------------------- | -| `ContentLayoutProps.priority` | *eliminated* | -| `UiItemsArbiter` | *eliminated* | +| `ContentLayoutProps.priority` | _eliminated_ | +| `UiItemsArbiter` | _eliminated_ | | `UiAbstract.messagePresenter` | `UiAdmin.messagePresenter` | ### @itwin/core-react @@ -1730,16 +1730,16 @@ SAML support has officially been dropped as a supported workflow. All related AP | `FunctionKey` | `FunctionKey` in @bentley/ui-abstract | | `IModelAppUiSettings` | `UserSettingsStorage` in @bentley/ui-framework | | `ConfigurableUiManager.findFrontstageDef` | `FrontstageManager.findFrontstageDef` | -| `ConfigurableUiManager.loadContentGroup` | *eliminated* | -| `ConfigurableUiManager.loadContentGroups` | *eliminated* | -| `ConfigurableUiManager.loadContentLayout` | *eliminated* | -| `ConfigurableUiManager.loadContentLayouts` | *eliminated* | -| `ContentGroupManager` | *eliminated* | +| `ConfigurableUiManager.loadContentGroup` | _eliminated_ | +| `ConfigurableUiManager.loadContentGroups` | _eliminated_ | +| `ConfigurableUiManager.loadContentLayout` | _eliminated_ | +| `ConfigurableUiManager.loadContentLayouts` | _eliminated_ | +| `ContentGroupManager` | _eliminated_ | | `Frontstage.initializeFrontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `Frontstage.findFrontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `Frontstage.initializeFromProvider` | `Frontstage.create` (async method) | | `FrontstageProps.defaultLayout` | `ContentGroup` now holds the layout information. | -| `FrontstageProvider.initializeDef` | *eliminated* | +| `FrontstageProvider.initializeDef` | _eliminated_ | | `FrontstageProvider.frontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `reactElement` in ContentControl | `ContentControl.reactNode` | | `reactElement` in NavigationAidControl | `NavigationAidControl.reactNode` | @@ -1754,13 +1754,13 @@ SAML support has officially been dropped as a supported workflow. All related AP | `SavedViewLayoutProps` | `StageContentLayoutProps` | | `SpecialKey` | `SpecialKey` in @itwin/appui-abstract | | `WidgetState` | `WidgetState` in @itwin/appui-abstract | -| `UserProfileBackstageItem` | *eliminated* | -| `SignIn` | *eliminated* | -| `SignOutModalFrontstage` | *eliminated* | -| `IModelConnectedCategoryTree` | *eliminated* | -| `IModelConnectedModelsTree` | *eliminated* | -| `IModelConnectedSpatialContainmentTree` | *eliminated* | -| `CategoryTreeWithSearchBox` | *eliminated* | +| `UserProfileBackstageItem` | _eliminated_ | +| `SignIn` | _eliminated_ | +| `SignOutModalFrontstage` | _eliminated_ | +| `IModelConnectedCategoryTree` | _eliminated_ | +| `IModelConnectedModelsTree` | _eliminated_ | +| `IModelConnectedSpatialContainmentTree` | _eliminated_ | +| `CategoryTreeWithSearchBox` | _eliminated_ | | `UiSettingsProvider` | `UiStateStorageHandler` | | `useUiSettingsStorageContext` | `useUiStateStorageHandler` | | `VisibilityComponent` | `TreeWidgetComponent` in @bentley/tree-widget-react | @@ -1768,14 +1768,14 @@ SAML support has officially been dropped as a supported workflow. All related AP | `WidgetProvider` | Provide widget via [UiItemsProvider]($appui-abstract) | | `ContentLayoutProps` | `ContentLayoutProps` in @itwin/appui-abstract | | All drag & drop related APIs | Third party components. E.g. see this [example](https://www.itwinjs.org/sample-showcase/?group=UI+Trees&sample=drag-and-drop) | -| `ModelsTreeProps.enablePreloading` | *eliminated* | +| `ModelsTreeProps.enablePreloading` | _eliminated_ | ### @itwin/core-bentley | Removed | Replacement | | --------------- | ---------------------------------------------------------- | | `Config` | Use `process.env` to access environment variables directly | -| `EnvMacroSubst` | *eliminated* | +| `EnvMacroSubst` | _eliminated_ | ### @itwin/presentation-common @@ -1785,11 +1785,11 @@ SAML support has officially been dropped as a supported workflow. All related AP | `ContentInstancesOfSpecificClassesSpecification.arePolymorphic` | `ContentInstancesOfSpecificClassesSpecification.handleInstancesPolymorphically` | | `ContentModifiersList.propertiesDisplay` | `ContentModifiersList.propertyOverrides` | | `ContentModifiersList.propertyEditors` | `ContentModifiersList.propertyOverrides` | -| `ContentRelatedInstancesSpecification.isRecursive` | *eliminated* | +| `ContentRelatedInstancesSpecification.isRecursive` | _eliminated_ | | `ContentRelatedInstancesSpecification.relatedClasses` | `ContentRelatedInstancesSpecification.relationshipPaths.targetClass` | | `ContentRelatedInstancesSpecification.relationships` | `ContentRelatedInstancesSpecification.relationshipPaths.relationship` | | `ContentRelatedInstancesSpecification.requiredDirection` | `ContentRelatedInstancesSpecification.relationshipPaths.direction` | -| `ContentRelatedInstancesSpecification.skipRelatedLevel` | *eliminated* | +| `ContentRelatedInstancesSpecification.skipRelatedLevel` | _eliminated_ | | `Descriptor.toCompressedJSON` | `Descriptor.toJSON` | | `DescriptorOverrides.hiddenFieldNames` | `DescriptorOverrides.fieldsSelector` | | `DescriptorOverrides.sortDirection` | `DescriptorOverrides.sorting.direction` | @@ -1800,22 +1800,22 @@ SAML support has officially been dropped as a supported workflow. All related AP | `ExtendedHierarchyRequestOptions` | `HierarchyRequestOptions` | | `ExtendedHierarchyRpcRequestOptions` | `HierarchyRpcRequestOptions` | | `Field.fromJSON` | `Field.fromCompressedJSON` | -| `HierarchyCompareRpcOptions` | *eliminated* | +| `HierarchyCompareRpcOptions` | _eliminated_ | | `LabelRequestOptions` | `DisplayLabelRequestOptions` | | `LabelRpcRequestOptions` | `DisplayLabelRpcRequestOptions` | | `LoggingNamespaces` | `PresentationBackendLoggerCategory`, `PresentationBackendNativeLoggerCategory`, `PresentationFrontendLoggerCategory` or `PresentationComponentsLoggerCategory` | | `NodeDeletionInfo.target` | `NodeDeletionInfo.parent` and `NodeDeletionInfo.position` | | `NodeDeletionInfoJSON.target` | `NodeDeletionInfoJSON.parent` and `NodeDeletionInfoJSON.position` | -| `PresentationDataCompareOptions` | *eliminated* | -| `PresentationRpcInterface.compareHierarchies` | *eliminated* | -| `PresentationRpcInterface.compareHierarchiesPaged` | *eliminated* | +| `PresentationDataCompareOptions` | _eliminated_ | +| `PresentationRpcInterface.compareHierarchies` | _eliminated_ | +| `PresentationRpcInterface.compareHierarchiesPaged` | _eliminated_ | | `PresentationRpcInterface.getContent` | `PresentationRpcInterface.getPagedContent` and `getPagedContentSet` | | `PresentationRpcInterface.getContentAndSize` | `PresentationRpcInterface.getPagedContent` and `getPagedContentSet` | | `PresentationRpcInterface.getDisplayLabelDefinitions` | `PresentationRpcInterface.getPagedDisplayLabelDefinitions` | | `PresentationRpcInterface.getDistinctValues` | `PresentationRpcInterface.getPagedDistinctValues` | | `PresentationRpcInterface.getNodes` | `PresentationRpcInterface.getPagedNodes` | | `PresentationRpcInterface.getNodesAndCount` | `PresentationRpcInterface.getPagedNodes` | -| `PresentationRpcInterface.loadHierarchy` | *eliminated* | +| `PresentationRpcInterface.loadHierarchy` | _eliminated_ | | `PresentationUnitSystem` | `UnitSystemKey` in `@bentley/imodeljs-quantity` | | `PropertiesFieldDescriptor.propertyClass` | `PropertiesFieldDescriptor.properties.class` | | `PropertiesFieldDescriptor.propertyName` | `PropertiesFieldDescriptor.properties.name` | @@ -1824,8 +1824,8 @@ SAML support has officially been dropped as a supported workflow. All related AP | `RelatedInstanceNodesSpecification.relatedClasses` | `RelatedInstanceNodesSpecification.relationshipPaths.targetClass` | | `RelatedInstanceNodesSpecification.relationships` | `RelatedInstanceNodesSpecification.relationshipPaths.relationship` | | `RelatedInstanceNodesSpecification.requiredDirection` | `RelatedInstanceNodesSpecification.relationshipPaths.direction` | -| `RelatedInstanceNodesSpecification.skipRelatedLevel` | *eliminated* | -| `RelatedInstanceNodesSpecification.supportedSchemas` | *eliminated* | +| `RelatedInstanceNodesSpecification.skipRelatedLevel` | _eliminated_ | +| `RelatedInstanceNodesSpecification.supportedSchemas` | _eliminated_ | | `RelatedInstanceSpecification.class` | `RelatedInstanceSpecification.relationshipPath.targetClass` | | `RelatedInstanceSpecification.relationship` | `RelatedInstanceSpecification.relationshipPath.relationship` | | `RelatedInstanceSpecification.requiredDirection` | `RelatedInstanceSpecification.relationshipPath.direction` | @@ -1835,8 +1835,8 @@ SAML support has officially been dropped as a supported workflow. All related AP | `RelatedPropertiesSpecification.relationships` | `RelatedPropertiesSpecification.propertiesSource.relationship` | | `RelatedPropertiesSpecification.requiredDirection` | `RelatedPropertiesSpecification.propertiesSource.direction` | | `Ruleset.supportedSchemas` | `Ruleset.requiredSchemas` | -| `RequestPriority` | *eliminated* | -| `RequestOptions.priority` | *eliminated* | +| `RequestPriority` | _eliminated_ | +| `RequestOptions.priority` | _eliminated_ | | `SelectClassInfo.pathToPrimaryClass` | `SelectClassInfo.pathFromInputToSelectClass` | | `SelectClassInfo.relatedInstanceClasses` | `SelectClassInfo.relatedInstancePaths` | | `SelectClassInfoJSON.pathToPrimaryClass` | `SelectClassInfoJSON.pathFromInputToSelectClass` | @@ -1927,18 +1927,17 @@ SAML support has officially been dropped as a supported workflow. All related AP | Removed | Replacement | | ---------------------------------- | ------------ | -| `UserInfo` | *eliminated* | -| `AuthorizationClient.isAuthorized` | *eliminated* | +| `UserInfo` | _eliminated_ | +| `AuthorizationClient.isAuthorized` | _eliminated_ | ### @bentley/frontend-authorization-client | Removed | Replacement | | ------------------------------------------- | --------------------------- | -| `FrontendAuthorizationClient` | *removed* | -| `FrontendAuthorizationClientLoggerCategory` | *removed* | +| `FrontendAuthorizationClient` | _removed_ | +| `FrontendAuthorizationClientLoggerCategory` | _removed_ | | `BrowserAuthorizationCallbackHandler` | Moved to iTwin/auth-clients | -| `BrowserAuthorizationBase` | *removed* | +| `BrowserAuthorizationBase` | _removed_ | | `BrowserAuthorizationClient` | Moved to iTwin/auth-clients | | `BrowserAuthorizationClientRedirectState` | Moved to iTwin/auth-clients | | `BrowserAuthorizationLogger` | Moved to iTwin/auth-clients | - diff --git a/docs/changehistory/NextVersion.md b/docs/changehistory/NextVersion.md index e78c469dc3ad..7ef4427157fc 100644 --- a/docs/changehistory/NextVersion.md +++ b/docs/changehistory/NextVersion.md @@ -2,92 +2,9 @@ publish: false --- # NextVersion - -## Simplified material creation - -[RenderSystem.createMaterial]($frontend) presents an awkward API requiring the instantiation of several related objects to create even a simple [RenderMaterial]($common). It also requires an [IModelConnection]($frontend). It has been deprecated in favor of [RenderSystem.createRenderMaterial]($frontend), which accepts a single [CreateRenderMaterialArgs]($frontend) object concisely specifying only the properties of interest to the caller. For example, the following: - -```ts - const params = new RenderMaterial.Params(); - params.alpha = 0.5; - params.diffuseColor = ColorDef.blue; - params.diffuse = 0.4; - - const mapParams = new TextureMapping.Params({ textureWeight: 0.25 }); - params.textureMapping = new TextureMapping(texture, mapParams); - const material = IModelApp.renderSystem.createMaterial(params, iModel); -``` - -Can now be expressed as follows (note no IModelConnection is required): - -```ts - const material = IModelApp.renderSystem.createRenderMaterial({ - alpha: 0.5, - diffuse: { color: ColorDef.blue, weight: 0.4 }, - textureMapping: { texture, weight: 0.25 }, - }); -``` - -## Model map layers - -Previously, map layers defined by a [MapLayerSettings]($common) were limited to imagery generated by tile servers, but many iModels contain planar spatial models representing [GIS](https://en.wikipedia.org/wiki/Geographic_information_system) data or aerial photography, similar to that obtained from tile imagery services. Now, the imagery for a map layer can also be obtained from such a model by specifying its model Id in a [ModelMapLayerSettings]($common). The model's geometry will be projected onto the terrain surface, and display of categories within the layer can be controlled by the view's category selector. - -In the image below, a planar GIS model is displayed as an ordinary model in the scene - note how it does not align correctly with the 3d terrain: - -![Gis as model](assets/gis-as-map-layer.jpg "2D GIS deta displayed as model") - -When displayed instead as a map layer, the same GIS model is correctly draped onto the 3d terrain: - -![GIS as map layer](assets/gis-as-model.jpg "2D GIS deta displayed as map layer") - -[MapLayerSettings]($common) now serves as a base class for [ImageMapLayerSettings]($common) and [ModelMapLayerSettings]($common), with respective JSON representations [ImageMapLayerProps]($common) and [ModelMapLayerProps]($common). - -## Obtain geometry from terrain and reality models - -- [TileGeometryCollector]($core-frontend), which specifies the level of detail, spatial volume, and other criteria for determining which tile meshes to obtain; and -- [GeometryTileTreeReference]($core-frontend), a [TileTreeReference]($core-frontend) that can supply [Polyface]($core-geometry) for its tiles. - -A [GeometryTileTreeReference]($core-frontend) can be obtained from an existing [TileTreeReference]($core-frontend) via [TileTreeReference.createGeometryTreeReference]($core-frontend). You can then supply a [TileGeometryCollector]($core-frontend) to [GeometryTileTreeReference.collectTileGeometry]($core-frontend) to collect the polyfaces. Because tile contents are downloaded asynchronously, you will need to repeat this process over successive frames until [TileGeometryCollector.isAllGeometryLoaded]($core-frontend) evaluates `true`. - -display-test-app provides [an example tool](https://github.com/iTwin/itwinjs-core/blob/master/test-apps/display-test-app/src/frontend/TerrainDrapeTool.ts) that uses these APIs to allow the user to drape line strings onto terrain and reality models. - -## Draco compression - -[Draco compression](https://codelabs.developers.google.com/codelabs/draco-3d) can significantly reduce the sizes of meshes and point clouds. iTwin.js has been enhanced to correctly decompress reality models, point clouds, and glTF models that contain draco-encoded data, reducing download time and bandwidth usage. - -## Floating content views in AppUI - -![Floating iModel Content Dialog](../learning/ui/appui/images/FloatingViewport.png "Floating iModel Content Dialog") - -## Font Workspaces - -It is now possible to store and load fonts from a Font Workspace. See [Fonts]($docs/learning/backend/Fonts.md) for more details. - -## Promote QuantityFormatter from beta to public - -The [QuantityFormatter]($core-frontend), accessed via `IModelApp.quantityFormatter`, is now public and provides a set of APIs to format and parse standard quantity types. For more documentation and samples see [Quantity Formatting]($docs/learning/frontend/QuantityFormatting.md). - -## New SchemaUnitProvider - -It is now possible to retrieve `Units` from schemas stored in IModels. The new [SchemaUnitProvider]($ecschema-metadata) can now be created and used by the [QuantityFormatter]($core-frontend) or any method in the `core-quantity` package that requires a [UnitsProvider]($quantity). Below is an example, extracted from `ui-test-app`, that demonstrates how to register the IModel-specific `UnitsProvider` as the IModelConnection is created. This new provider will provide access to a wide variety of Units that were not available in the standalone `BasicUnitsProvider`. - -```ts - try{ - // Reset QuantityFormatter UnitsProvider with new iModelConnection - const schemaLocater = new ECSchemaRpcLocater(iModelConnection); - const context = new SchemaContext(); - context.addLocater(schemaLocater); - await IModelApp.quantityFormatter.setUnitsProvider (new SchemaUnitProvider(context)); - } catch (_) { - await IModelApp.quantityFormatter.resetToUseInternalUnitsProvider(); // reset to use internal BasicUnitsProvider - } - - UiFramework.setIModelConnection(iModelConnection, true); -``` - ## Optimization of geometry in IModelImporter -The geometry produced by [connectors](https://www.itwinjs.org/learning/imodel-connectors/) and [transformation workflows]($docs/learning/transformer/index.md) is not always ideal. One common issue is a proliferation of [GeometryPart]($backend)s to which only one reference exists. In most cases, it would be more efficient to embed the part's geometry directly into the referencing element's [geometry stream](https://www.itwinjs.org/learning/common/geometrystream/). +The geometry produced by [connectors](https://www.itwinjs.org/learning/imodel-connectors/) and [transformation workflows](../learning/transformer/index.md) is not always ideal. One common issue is a proliferation of [GeometryPart]($backend)s to which only one reference exists. In most cases, it would be more efficient to embed the part's geometry directly into the referencing element's [geometry stream](https://www.itwinjs.org/learning/common/geometrystream/). [IModelImporter.optimizeGeometry]($transformer) has been introduced to enable this kind of optimization. It takes an [OptimizeGeometryOptions]($transformer) object specifying which optimizations to apply, and applies them to all of the 3d geometry in the iModel. Currently, only the optimization described above is supported, but more are expected to be added in the future. @@ -111,3 +28,30 @@ If you are using [IModelTransformer]($transformer), you can configure automatic ### Filtering related property instances The [related properties specification](../presentation/Content/RelatedPropertiesSpecification.md) allows including properties of related instances when requesting content for the primary instance. However, sometimes there's a need show properties of only a few related instances rather than all of them. That can now be done by supplying an instance filter - see the [`instanceFilter` attribute section](../presentation/Content/RelatedPropertiesSpecification.md#attribute-instancefilter) for more details. +### Detecting integrated graphics + +Many computers - especially laptops - contain two graphics processing units: a low-powered "integrated" GPU such as those manufactured by Intel, and a more powerful "discrete" GPU typically manufactured by NVidia or AMD. Operating systems and web browsers often default to using the integrated GPU to reduce power consumption, but this can produce poor performance in graphics-heavy applications like those built with iTwin.js. We recommend that users adjust their settings to use the discrete GPU if one is available. + +iTwin.js applications can now check [WebGLRenderCompatibilityInfo.usingIntegratedGraphics]($webgl-compatibility) to see if the user might experience degraded performance due to the use of integrated graphics. Because WebGL does not provide access to information about specific graphics hardware, this property is only a heuristic. But it will accurately identify integrated Intel chips manufactured within the past 10 years or so, and allow the application to suggest that the user verify whether a discrete GPU is available to use instead. As a simple example: + +```ts + const compatibility = IModelApp.queryRenderCompatibility(); + if (compatibility.usingIntegratedGraphics) + alert("Integrated graphics are in use. If a discrete GPU is available, consider switching your device or browser to use it."); +``` + +## ColorDef validation + +[ColorDef.fromString]($common) returns [ColorDef.black]($common) if the input is not a valid color string. [ColorDef.create]($common) coerces the input numeric representation into a 32-bit unsigned integer. In either case, this occurs silently. Now, you can use [ColorDef.isValidColor]($common) to determine if your input is valid. + +## ColorByName is an object, not an enum + +Enums in TypeScript have some shortcomings, one of which resulted in a bug that caused [ColorDef.fromString]($common) to return [ColorDef.black]($common) for some valid color strings like "aqua". This is due to several standard color names ("aqua" and "cyan", "magenta" and "fuschia", and several "grey" vs "gray" variations) having the same numeric values. To address this, [ColorByName]($common) has been converted from an `enum` to a `namespace`. Code that accesses `ColorByName` members by name will continue to compile with no change. + +## Deprecations in @itwin/components-react package + +The interfaces and components [ShowHideMenuProps]($components-react), [ShowHideMenu]($components-react), [ShowHideItem]($components-react)[ShowHideID]($components-react), [ShowHideDialogProps]($components-react), and [ShowHideDialog]($components-react) are all being deprecated because they were supporting components for the now deprecated [Table]($components-react) component. This `Table` component used an Open Source component that is not being maintained so it was determined to drop it from the API. The @itwin/itwinui-react package now delivers a Table component which should be used in place of the deprecated Table. + +## Deprecations in @itwin/core-react package + +Using the sprite loader for SVG icons is deprecated. This includes [SvgSprite]($core-react) and the methods getSvgIconSpec() and getSvgIconSource() methods on [IconSpecUtilities]($appui-abstract). The sprite loader has been replaced with a web component [IconWebComponent]($core-react) used by [Icon]($core-react) to load SVGs onto icons. diff --git a/docs/changehistory/index.md b/docs/changehistory/index.md index 952dd3faa580..80b789d8e0e8 100644 --- a/docs/changehistory/index.md +++ b/docs/changehistory/index.md @@ -42,7 +42,7 @@ Many of the enhancements introduced in iTwin.js 3.0 were directly motivated by f #### Documentation -A collection of [learning articles]($docs/learning/display/index.md) has been assembled to provide an overview of the features provided by the display system, illustrated by interactive samples. +A collection of [learning articles](../learning/display/index.md) has been assembled to provide an overview of the features provided by the display system, illustrated by interactive samples. #### Viewport.zoomToElements improvements @@ -181,7 +181,7 @@ Improvements were made to the performance of [ParticleCollectionBuilder]($fronte #### Support for glTF graphics -[glTF](https://www.khronos.org/gltf/) has become the de facto standard format for 3d graphics on the web. Now you can create a [RenderGraphic]($frontend) from a glTF asset for use with [Decorators]($docs/learning/frontend/ViewDecorations), using [readGltfGraphics]($frontend). [This example]($docs/learning/frontend/ViewDecorations#gltf-decorations) demonstrates how to convert a glTF asset into a graphic and display it using a decorator. +[glTF](https://www.khronos.org/gltf/) has become the de facto standard format for 3d graphics on the web. Now you can create a [RenderGraphic]($frontend) from a glTF asset for use with [Decorators](../learning/frontend/ViewDecorations), using [readGltfGraphics]($frontend). [This example](../learning/frontend/ViewDecorations#gltf-decorations) demonstrates how to convert a glTF asset into a graphic and display it using a decorator. Note: `readGltfGraphics` targets the [glTF 2.0 specification](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html), but implementation of the full specification is an ongoing work in progress. The current implementation can successfully read many glTF assets, but if a particular asset fails to load or display properly, please [file an issue](https://github.com/iTwin/itwinjs-core/issues). @@ -214,11 +214,11 @@ Note: `readGltfGraphics` targets the [glTF 2.0 specification](https://www.khrono ##### Schema requirements A new `requiredSchemas` attribute has been added: [Ruleset.requiredSchemas]($presentation-common) and [RuleBase.requiredSchemas]($presentation-common). The attribute allows an easy way to filter presentation rules based on -ECSchemas / domains available in the iModel. See more details in the [Defining ECSchema Requirements for Presentation Rules]($docs/presentation/Advanced/SchemaRequirements) page. +ECSchemas / domains available in the iModel. See more details in the [Defining ECSchema Requirements for Presentation Rules](../presentation/Advanced/SchemaRequirements) page. ##### Conditional root node rules -Similar to [Child Node Rule]($docs/presentation/Hierarchies/ChildNodeRule), the [Root Node Rule]($docs/presentation/Hierarchies/RootNodeRule) now also has a [condition]($docs/presentation/Hierarchies/RootNodeRule#attribute-condition) attribute. The attribute provides more flexibility in enabling or disabling the rule, including the use of [ruleset variables]($docs/presentation/Advanced/RulesetVariables#using-variables-in-rule-condition). +Similar to [Child Node Rule](../presentation/Hierarchies/ChildNodeRule), the [Root Node Rule](../presentation/Hierarchies/RootNodeRule) now also has a [condition](../presentation/Hierarchies/RootNodeRule#attribute-condition) attribute. The attribute provides more flexibility in enabling or disabling the rule, including the use of [ruleset variables](../presentation/Advanced/RulesetVariables#using-variables-in-rule-condition). ##### More precise way to set class polymorphism @@ -499,7 +499,7 @@ requestContext.enter(); you can simply delete it. -This change mostly affects backend code. For backend [RPC]($docs/learning/RpcInterface.md) implementations, all *unhandled* exceptions will automatically be logged along the appropriate RPC metadata. For this reason, it often preferable to throw an exception rather than logging an error and returning a status in code that may or may not be called from RPC. +This change mostly affects backend code. For backend [RPC](../learning/RpcInterface.md) implementations, all _unhandled_ exceptions will automatically be logged along the appropriate RPC metadata. For this reason, it often preferable to throw an exception rather than logging an error and returning a status in code that may or may not be called from RPC. ### iModels @@ -527,7 +527,7 @@ Previously the concurrency "mode" was determined by applications when opening a Locks apply to Elements only. The "schema lock" is acquired by exclusively locking element id 0x1 (the root subject id). Models are locked via their modeled element (which has the same id as the model) -See the [ConcurrencyControl]($docs/learning/backend/ConcurrencyControl.md) learning article for more information and examples. +See the [ConcurrencyControl](../learning/backend/ConcurrencyControl.md) learning article for more information and examples. #### BriefcaseManager, BriefcaseDb, and IModelDb changes @@ -608,7 +608,7 @@ On the frontend the [GeoConverter]($frontend) class has been modified to accept #### BentleyError constructor no longer logs -In V2, the constructor of the base exception class [BentleyError]($core-bentley) accepted 5 arguments, the last 3 being optional. Arguments 3 and 4 were for logging the exception in the constructor itself. That is a bad idea, since exceptions are often handled and recovered in `catch` statements, so there is no actual "problem" to report. In that case the message in the log is either misleading or just plain wrong. Also, code in `catch` statements always has more "context" about *why* the error may have happened than the lower level code that threw (e.g. "invalid Id" vs. "invalid MyHashClass Id") so log messages from callers can be more helpful than from callees. Since every thrown exception must be caught *somewhere*, logging should be done when exceptions are caught, not when they're thrown. +In V2, the constructor of the base exception class [BentleyError]($core-bentley) accepted 5 arguments, the last 3 being optional. Arguments 3 and 4 were for logging the exception in the constructor itself. That is a bad idea, since exceptions are often handled and recovered in `catch` statements, so there is no actual "problem" to report. In that case the message in the log is either misleading or just plain wrong. Also, code in `catch` statements always has more "context" about _why_ the error may have happened than the lower level code that threw (e.g. "invalid Id" vs. "invalid MyHashClass Id") so log messages from callers can be more helpful than from callees. Since every thrown exception must be caught _somewhere_, logging should be done when exceptions are caught, not when they're thrown. The [BentleyError]($core-bentley) constructor now accepts 3 arguments, the last argument (`metaData`) is optional. The previous `log` and `category` arguments were removed. If your code passed 5 arguments, remove the 3rd and 4th. If you previously passed 3 or 4 arguments, just leave the first two. Also, the previous version of the constructor required the metaData argument to be a function that returns an object. It may now also just be an object. @@ -1624,8 +1624,8 @@ A number of packages have been renamed to use the @itwin scope rather than the @ | `IModelApp.settings` | [IModelApp.userPreferences]($frontend) | | `IModelConnection.Models.loaded` | use `for..of` to iterate and `getLoaded` to look up by Id | | `IModelConnection.Views.saveThumbnail` | use IPC and `IModelDb.saveThumbnail` | -| `IOidcFrontendClient` | *eliminated* | -| `isIOidcFrontendClient` | *eliminated* | +| `IOidcFrontendClient` | _eliminated_ | +| `isIOidcFrontendClient` | _eliminated_ | | `OidcBrowserClient` | `BrowserAuthorizationClient` in `@itwin/browser-authorization` | | `OidcFrontendClientConfiguration` | `BrowserAuthorizationClientConfiguration` in `@itwin/browser-authorization` | | `QuantityFormatter.onActiveUnitSystemChanged` | [QuantityFormatter.onActiveFormattingUnitSystemChanged]($frontend) | @@ -1640,7 +1640,7 @@ A number of packages have been renamed to use the @itwin scope rather than the @ | `Viewport.featureOverrideProvider` | [Viewport.featureOverrideProviders]($frontend) | | `Viewport.setFlashed` | [Viewport.flashedId]($frontend) | | `Viewport.setRedrawPending` | [Viewport.requestRedraw]($frontend) | -| `WebAppViewer` | *eliminated* | +| `WebAppViewer` | _eliminated_ | | `NativeAppAuthorization` | Moved to @iTwin/auth-clients repo as `ElectronRendererAuthorization` | ### @itwin/core-geometry @@ -1664,16 +1664,16 @@ SAML support has officially been dropped as a supported workflow. All related AP | `OidcDelegationClient` | `DelegationAuthorizationClient` | | `BackendAuthorizationClient` | Moved to @iTwin/auth-clients as BrowserAuthorizationClient | | `AgentAuthorizationClient` | Moved to @iTwin/auth-clients as SerivceAuthorizationClient | -| `DelegationAuthorizationClient` | *removed* | +| `DelegationAuthorizationClient` | _removed_ | | `IntrospectionClient` | Moved to @iTwin/auth-clients | -| `ImsAuthorizationClient` | *removed* | +| `ImsAuthorizationClient` | _removed_ | ### @itwin/appui-abstract | Removed | Replacement | | ----------------------------- | -------------------------- | -| `ContentLayoutProps.priority` | *eliminated* | -| `UiItemsArbiter` | *eliminated* | +| `ContentLayoutProps.priority` | _eliminated_ | +| `UiItemsArbiter` | _eliminated_ | | `UiAbstract.messagePresenter` | `UiAdmin.messagePresenter` | ### @itwin/core-react @@ -1726,16 +1726,16 @@ SAML support has officially been dropped as a supported workflow. All related AP | `FunctionKey` | `FunctionKey` in @bentley/ui-abstract | | `IModelAppUiSettings` | `UserSettingsStorage` in @bentley/ui-framework | | `ConfigurableUiManager.findFrontstageDef` | `FrontstageManager.findFrontstageDef` | -| `ConfigurableUiManager.loadContentGroup` | *eliminated* | -| `ConfigurableUiManager.loadContentGroups` | *eliminated* | -| `ConfigurableUiManager.loadContentLayout` | *eliminated* | -| `ConfigurableUiManager.loadContentLayouts` | *eliminated* | -| `ContentGroupManager` | *eliminated* | +| `ConfigurableUiManager.loadContentGroup` | _eliminated_ | +| `ConfigurableUiManager.loadContentGroups` | _eliminated_ | +| `ConfigurableUiManager.loadContentLayout` | _eliminated_ | +| `ConfigurableUiManager.loadContentLayouts` | _eliminated_ | +| `ContentGroupManager` | _eliminated_ | | `Frontstage.initializeFrontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `Frontstage.findFrontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `Frontstage.initializeFromProvider` | `Frontstage.create` (async method) | | `FrontstageProps.defaultLayout` | `ContentGroup` now holds the layout information. | -| `FrontstageProvider.initializeDef` | *eliminated* | +| `FrontstageProvider.initializeDef` | _eliminated_ | | `FrontstageProvider.frontstageDef` | `FrontstageManager.getFrontstageDef` (async method) | | `reactElement` in ContentControl | `ContentControl.reactNode` | | `reactElement` in NavigationAidControl | `NavigationAidControl.reactNode` | @@ -1750,13 +1750,13 @@ SAML support has officially been dropped as a supported workflow. All related AP | `SavedViewLayoutProps` | `StageContentLayoutProps` | | `SpecialKey` | `SpecialKey` in @itwin/appui-abstract | | `WidgetState` | `WidgetState` in @itwin/appui-abstract | -| `UserProfileBackstageItem` | *eliminated* | -| `SignIn` | *eliminated* | -| `SignOutModalFrontstage` | *eliminated* | -| `IModelConnectedCategoryTree` | *eliminated* | -| `IModelConnectedModelsTree` | *eliminated* | -| `IModelConnectedSpatialContainmentTree` | *eliminated* | -| `CategoryTreeWithSearchBox` | *eliminated* | +| `UserProfileBackstageItem` | _eliminated_ | +| `SignIn` | _eliminated_ | +| `SignOutModalFrontstage` | _eliminated_ | +| `IModelConnectedCategoryTree` | _eliminated_ | +| `IModelConnectedModelsTree` | _eliminated_ | +| `IModelConnectedSpatialContainmentTree` | _eliminated_ | +| `CategoryTreeWithSearchBox` | _eliminated_ | | `UiSettingsProvider` | `UiStateStorageHandler` | | `useUiSettingsStorageContext` | `useUiStateStorageHandler` | | `VisibilityComponent` | `TreeWidgetComponent` in @bentley/tree-widget-react | @@ -1764,14 +1764,14 @@ SAML support has officially been dropped as a supported workflow. All related AP | `WidgetProvider` | Provide widget via [UiItemsProvider]($appui-abstract) | | `ContentLayoutProps` | `ContentLayoutProps` in @itwin/appui-abstract | | All drag & drop related APIs | Third party components. E.g. see this [example](https://www.itwinjs.org/sample-showcase/?group=UI+Trees&sample=drag-and-drop) | -| `ModelsTreeProps.enablePreloading` | *eliminated* | +| `ModelsTreeProps.enablePreloading` | _eliminated_ | ### @itwin/core-bentley | Removed | Replacement | | --------------- | ---------------------------------------------------------- | | `Config` | Use `process.env` to access environment variables directly | -| `EnvMacroSubst` | *eliminated* | +| `EnvMacroSubst` | _eliminated_ | ### @itwin/presentation-common @@ -1781,11 +1781,11 @@ SAML support has officially been dropped as a supported workflow. All related AP | `ContentInstancesOfSpecificClassesSpecification.arePolymorphic` | `ContentInstancesOfSpecificClassesSpecification.handleInstancesPolymorphically` | | `ContentModifiersList.propertiesDisplay` | `ContentModifiersList.propertyOverrides` | | `ContentModifiersList.propertyEditors` | `ContentModifiersList.propertyOverrides` | -| `ContentRelatedInstancesSpecification.isRecursive` | *eliminated* | +| `ContentRelatedInstancesSpecification.isRecursive` | _eliminated_ | | `ContentRelatedInstancesSpecification.relatedClasses` | `ContentRelatedInstancesSpecification.relationshipPaths.targetClass` | | `ContentRelatedInstancesSpecification.relationships` | `ContentRelatedInstancesSpecification.relationshipPaths.relationship` | | `ContentRelatedInstancesSpecification.requiredDirection` | `ContentRelatedInstancesSpecification.relationshipPaths.direction` | -| `ContentRelatedInstancesSpecification.skipRelatedLevel` | *eliminated* | +| `ContentRelatedInstancesSpecification.skipRelatedLevel` | _eliminated_ | | `Descriptor.toCompressedJSON` | `Descriptor.toJSON` | | `DescriptorOverrides.hiddenFieldNames` | `DescriptorOverrides.fieldsSelector` | | `DescriptorOverrides.sortDirection` | `DescriptorOverrides.sorting.direction` | @@ -1796,22 +1796,22 @@ SAML support has officially been dropped as a supported workflow. All related AP | `ExtendedHierarchyRequestOptions` | `HierarchyRequestOptions` | | `ExtendedHierarchyRpcRequestOptions` | `HierarchyRpcRequestOptions` | | `Field.fromJSON` | `Field.fromCompressedJSON` | -| `HierarchyCompareRpcOptions` | *eliminated* | +| `HierarchyCompareRpcOptions` | _eliminated_ | | `LabelRequestOptions` | `DisplayLabelRequestOptions` | | `LabelRpcRequestOptions` | `DisplayLabelRpcRequestOptions` | | `LoggingNamespaces` | `PresentationBackendLoggerCategory`, `PresentationBackendNativeLoggerCategory`, `PresentationFrontendLoggerCategory` or `PresentationComponentsLoggerCategory` | | `NodeDeletionInfo.target` | `NodeDeletionInfo.parent` and `NodeDeletionInfo.position` | | `NodeDeletionInfoJSON.target` | `NodeDeletionInfoJSON.parent` and `NodeDeletionInfoJSON.position` | -| `PresentationDataCompareOptions` | *eliminated* | -| `PresentationRpcInterface.compareHierarchies` | *eliminated* | -| `PresentationRpcInterface.compareHierarchiesPaged` | *eliminated* | +| `PresentationDataCompareOptions` | _eliminated_ | +| `PresentationRpcInterface.compareHierarchies` | _eliminated_ | +| `PresentationRpcInterface.compareHierarchiesPaged` | _eliminated_ | | `PresentationRpcInterface.getContent` | `PresentationRpcInterface.getPagedContent` and `getPagedContentSet` | | `PresentationRpcInterface.getContentAndSize` | `PresentationRpcInterface.getPagedContent` and `getPagedContentSet` | | `PresentationRpcInterface.getDisplayLabelDefinitions` | `PresentationRpcInterface.getPagedDisplayLabelDefinitions` | | `PresentationRpcInterface.getDistinctValues` | `PresentationRpcInterface.getPagedDistinctValues` | | `PresentationRpcInterface.getNodes` | `PresentationRpcInterface.getPagedNodes` | | `PresentationRpcInterface.getNodesAndCount` | `PresentationRpcInterface.getPagedNodes` | -| `PresentationRpcInterface.loadHierarchy` | *eliminated* | +| `PresentationRpcInterface.loadHierarchy` | _eliminated_ | | `PresentationUnitSystem` | `UnitSystemKey` in `@bentley/imodeljs-quantity` | | `PropertiesFieldDescriptor.propertyClass` | `PropertiesFieldDescriptor.properties.class` | | `PropertiesFieldDescriptor.propertyName` | `PropertiesFieldDescriptor.properties.name` | @@ -1820,8 +1820,8 @@ SAML support has officially been dropped as a supported workflow. All related AP | `RelatedInstanceNodesSpecification.relatedClasses` | `RelatedInstanceNodesSpecification.relationshipPaths.targetClass` | | `RelatedInstanceNodesSpecification.relationships` | `RelatedInstanceNodesSpecification.relationshipPaths.relationship` | | `RelatedInstanceNodesSpecification.requiredDirection` | `RelatedInstanceNodesSpecification.relationshipPaths.direction` | -| `RelatedInstanceNodesSpecification.skipRelatedLevel` | *eliminated* | -| `RelatedInstanceNodesSpecification.supportedSchemas` | *eliminated* | +| `RelatedInstanceNodesSpecification.skipRelatedLevel` | _eliminated_ | +| `RelatedInstanceNodesSpecification.supportedSchemas` | _eliminated_ | | `RelatedInstanceSpecification.class` | `RelatedInstanceSpecification.relationshipPath.targetClass` | | `RelatedInstanceSpecification.relationship` | `RelatedInstanceSpecification.relationshipPath.relationship` | | `RelatedInstanceSpecification.requiredDirection` | `RelatedInstanceSpecification.relationshipPath.direction` | @@ -1831,8 +1831,8 @@ SAML support has officially been dropped as a supported workflow. All related AP | `RelatedPropertiesSpecification.relationships` | `RelatedPropertiesSpecification.propertiesSource.relationship` | | `RelatedPropertiesSpecification.requiredDirection` | `RelatedPropertiesSpecification.propertiesSource.direction` | | `Ruleset.supportedSchemas` | `Ruleset.requiredSchemas` | -| `RequestPriority` | *eliminated* | -| `RequestOptions.priority` | *eliminated* | +| `RequestPriority` | _eliminated_ | +| `RequestOptions.priority` | _eliminated_ | | `SelectClassInfo.pathToPrimaryClass` | `SelectClassInfo.pathFromInputToSelectClass` | | `SelectClassInfo.relatedInstanceClasses` | `SelectClassInfo.relatedInstancePaths` | | `SelectClassInfoJSON.pathToPrimaryClass` | `SelectClassInfoJSON.pathFromInputToSelectClass` | @@ -1923,17 +1923,17 @@ SAML support has officially been dropped as a supported workflow. All related AP | Removed | Replacement | | ---------------------------------- | ------------ | -| `UserInfo` | *eliminated* | -| `AuthorizationClient.isAuthorized` | *eliminated* | +| `UserInfo` | _eliminated_ | +| `AuthorizationClient.isAuthorized` | _eliminated_ | ### @bentley/frontend-authorization-client | Removed | Replacement | | ------------------------------------------- | --------------------------- | -| `FrontendAuthorizationClient` | *removed* | -| `FrontendAuthorizationClientLoggerCategory` | *removed* | +| `FrontendAuthorizationClient` | _removed_ | +| `FrontendAuthorizationClientLoggerCategory` | _removed_ | | `BrowserAuthorizationCallbackHandler` | Moved to iTwin/auth-clients | -| `BrowserAuthorizationBase` | *removed* | +| `BrowserAuthorizationBase` | _removed_ | | `BrowserAuthorizationClient` | Moved to iTwin/auth-clients | | `BrowserAuthorizationClientRedirectState` | Moved to iTwin/auth-clients | | `BrowserAuthorizationLogger` | Moved to iTwin/auth-clients | diff --git a/docs/getting-started/leftNav.md b/docs/getting-started/leftNav.md index 243f8b693f6d..2ecebda324c1 100644 --- a/docs/getting-started/leftNav.md +++ b/docs/getting-started/leftNav.md @@ -23,4 +23,4 @@ --- -## [Tutorials]($docs/learning/tutorials/index.md) +## [Tutorials](../learning/tutorials/index.md) diff --git a/docs/getting-started/offline-quickstart.md b/docs/getting-started/offline-quickstart.md index a288359769ee..6fb83df99c75 100644 --- a/docs/getting-started/offline-quickstart.md +++ b/docs/getting-started/offline-quickstart.md @@ -10,7 +10,7 @@ Writing an iTwin.js application requires the following software: ## 2. Get, build, and develop code -[Follow the "Developing a Desktop Viewer" tutorial]($docs/learning/tutorials/develop-desktop-viewer.md) +[Follow the "Developing a Desktop Viewer" tutorial](../learning/tutorials/develop-desktop-viewer.md)     diff --git a/docs/getting-started/online-quickstart.md b/docs/getting-started/online-quickstart.md index aac66c254de7..ac4b89ed3c9e 100644 --- a/docs/getting-started/online-quickstart.md +++ b/docs/getting-started/online-quickstart.md @@ -14,7 +14,7 @@ Writing an iTwin.js application requires the following software: ## 3. Get, build, and develop code -[Follow the "Developing a web viewer" tutorial]($docs/learning/tutorials/develop-web-viewer.md) +[Follow the "Developing a web viewer" tutorial](../learning/tutorials/develop-web-viewer.md)     @@ -22,7 +22,7 @@ Writing an iTwin.js application requires the following software: ## Next Steps -### [Follow tutorials to dive deeper into iTwin.js]($docs/learning/tutorials/index.md) +### [Follow tutorials to dive deeper into iTwin.js](../learning/tutorials/index.md) ### [iTwin.js Blog](https://medium.com/itwinjs) diff --git a/docs/learning/Glossary.md b/docs/learning/Glossary.md index e60c8ae0c9b3..c179e836cf5f 100644 --- a/docs/learning/Glossary.md +++ b/docs/learning/Glossary.md @@ -18,7 +18,7 @@ tableRowAnchors: true | **Changeset** | A group of changes to an iModel. Changesets are created whenever an Briefcase is modified and reflect the union of all Additions, Deletions, and Modifications over a period of time. Changeset are assigned an identifier when they are uploaded to iModelHub and every Changeset stores the identifier of its parent Changeset. In this way the chain of Changesets for an iModel in iModelHub forms its "timeline of changes". | | **ChangeSummary** | A [summary of the changes](./ChangeSummaries) in a Changeset in the form of ECClasses and ECProperties. | | **Class Registry** | A registry of known JavaScript classes that handle ECClasses. Each JavaScript class has a static member called `className` that identifies its BIS class. When an Entity is loaded from an iModel, a JavaScript instance of the registered class will be created. If no JavaScript class is registered for the ECClass, one is created dynamically. | -| **Code** | An optional [three part *human readable* identifier]($docs/bis/intro/codes.md) for an Element. A code consists of a CodeSpec, CodeScope, and CodeValue. The combination of all three parts must be unique within an iModel. | +| **Code** | An optional [three part *human readable* identifier](../bis/intro/codes.md) for an Element. A code consists of a CodeSpec, CodeScope, and CodeValue. The combination of all three parts must be unique within an iModel. | | **CodeScope** | A Code Scope determines a *scope for uniqueness* for the code value. For example, a scope may specify the whole iModel, only within a certain Model, within an assembly, etc. For a given CodeSpec and CodeScope, all CodeValues must be unique. | | **CodeSpec** | A CodeSpec defines the *specification* (i.e. type) of a code. Often the specification is defined by some external system that enforces conventions, consistency, and validation. A CodeSpec captures the rules for encoding and decoding significant business information into and from a CodeValue. iModels hold a table of the known CodeSpecs, defined by the CodeSpec ECClass, and Elements refer to one of them by Id. | | **CodeValue** | A human-readable string with the *name* of an Element. CodeValues are formatted according to the rules of its CodeSpec. | @@ -82,7 +82,7 @@ tableRowAnchors: true | **Rush** | A tool for [managing multiple NPM packages](http://rushjs.io/) within a single git repository. | | **Schema** | See [ECSchema](#ecschema). | | **SheetModel** | A digital representation of a *sheet of paper*. Sheet Models are 2d models in bounded paper coordinates. SheetModels may contain annotation Elements as well as references to [DrawingViewDefinition]($backend)s. or [SpatialViewDefinition]($backend)s. | -| **Snapshot iModel** | A [static]($docs/learning/backend/AccessingIModels.md/#snapshot-imodels) point-in-time representation of the state of an iModel. | +| **Snapshot iModel** | A [static](./backend/AccessingIModels.md/#snapshot-imodels) point-in-time representation of the state of an iModel. | | **Spatial Coordinate System** | The 3d coordinate system of an iModel. The units are always meters (see ACS). The origin (0,0,0) of the Spatial Coordinate System may be oriented on the earth via an EcefLocation. | | **SpatialModel** | A subclass of GeometricModel that holds 3d Elements in the iModel's Spatial Coordinate System. | | **SpatialViewDefinition** | A subclass of ViewDefinition that displays one or more SpatialModels. | diff --git a/docs/learning/backend/AccessingIModels.md b/docs/learning/backend/AccessingIModels.md index f533766026af..a128385cf421 100644 --- a/docs/learning/backend/AccessingIModels.md +++ b/docs/learning/backend/AccessingIModels.md @@ -33,7 +33,7 @@ The second method creates an *empty* Snapshot iModel given a filename. This is u #### Create Snapshots with *iTwin Snapshot* -[iTwin Snapshot]($docs/learning/tutorials/create-test-imodel-offline.md), is a free tool for creating snapshots. iTwin Snapshot was designed for developers to quickly generate snapshots for use in iTwin.js development. +[iTwin Snapshot](../tutorials/create-test-imodel-offline.md), is a free tool for creating snapshots. iTwin Snapshot was designed for developers to quickly generate snapshots for use in iTwin.js development. ### Important properties of Snapshot iModels diff --git a/docs/learning/backend/ConcurrencyControl.md b/docs/learning/backend/ConcurrencyControl.md index 78771d18d0b0..d4b7a71f71c2 100644 --- a/docs/learning/backend/ConcurrencyControl.md +++ b/docs/learning/backend/ConcurrencyControl.md @@ -19,16 +19,16 @@ This article assumes that you already know that: - An iModel is a multi-user database - An app works with a [briefcase](../Glossary.md#Briefcase) using the [BriefcaseDb]($backend) class. -- A briefcase has a unique [BriefcaseId]($common) that is issued and tracked by [iModelHub]($docs/learning/IModelHub/index.md). -- Changes are captured and distributed in the form of [Changesets]($docs/learning/IModelHub/briefcases.md). -- Changesets are ordered in a sequence that is called the [timeline]($docs/learning/IModelHub/index.md#the-timeline-of-changes-to-an-imodel) of the iModel. A changeset's position on the timeline is indicated by its [ChangesetIndex]($common). +- A briefcase has a unique [BriefcaseId]($common) that is issued and tracked by [iModelHub](../IModelHub/index.md). +- Changes are captured and distributed in the form of [Changesets](../IModelHub/briefcases.md). +- Changesets are ordered in a sequence that is called the [timeline](../IModelHub/index.md#the-timeline-of-changes-to-an-imodel) of the iModel. A changeset's position on the timeline is indicated by its [ChangesetIndex]($common). - Changesets are stored in iModelHub ## Concurrency Glossary | Term | Definition | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Base** | Changeset B is _based_ on Changeset A if B comes after A in the timeline. | +| **Base** | Changeset B is *based* on Changeset A if B comes after A in the timeline. | | **Change-merging** | Same as merge. | | **Concurrency Control** | How to coordinate simultaneous transactions while preserving data integrity. | | **Concurrency Control Policy** | The rules that apps must follow when changing models and elements. May be [optimistic](#optimistic-concurrency-control) or [pessimistic](#pessimistic-concurrency-control). | diff --git a/docs/learning/backend/SchemasAndElementsInTypeScript.md b/docs/learning/backend/SchemasAndElementsInTypeScript.md index 8182a543f6b4..8bdc5d85cdfb 100644 --- a/docs/learning/backend/SchemasAndElementsInTypeScript.md +++ b/docs/learning/backend/SchemasAndElementsInTypeScript.md @@ -1,8 +1,8 @@ # Schemas and Elements in TypeScript -A [Schema]($backend) represents an ECSchema in TypeScript. It is a collection of Entity-based classes. See [the BIS overview]($docs/bis) for how ECSchemas are used to model information. ECSchemas define classes for models, elements, and aspects, as well as ECRelationships. +A [Schema]($backend) represents an ECSchema in TypeScript. It is a collection of Entity-based classes. See [the BIS overview](../../bis/index.md) for how ECSchemas are used to model information. ECSchemas define classes for models, elements, and aspects, as well as ECRelationships. -An [Element]($backend) object represents an *instance* of a [bis:Element]($docs/BIS/intro/element-fundamentals.md) class when it is read from an iModel. The Element object has properties that correspond to the bis class definition in the schema. An [ElementAspect]($backend) object represents an instance of a [bis:Aspect]($docs/BIS/intro/elementaspect-fundamentals.md) in memory. +An [Element]($backend) object represents an *instance* of a [bis:Element](../../BIS/intro/element-fundamentals.md) class when it is read from an iModel. The Element object has properties that correspond to the bis class definition in the schema. An [ElementAspect]($backend) object represents an instance of a [bis:Aspect](../../BIS/intro/elementaspect-fundamentals.md) in memory. ECSchemas typically define subclasses of bis:Element, bis:Aspect, and so on. The objects that are loaded into memory are instances of TypeScript/JavaScript classes that match the ECSchema definitions. So, for example, an instance of a bis:GeometricElement3d is an object of the class [GeometricElement3d]($backend). diff --git a/docs/learning/faq.md b/docs/learning/faq.md index cebaa83908f5..cd5196cf5ca7 100644 --- a/docs/learning/faq.md +++ b/docs/learning/faq.md @@ -5,4 +5,4 @@ If you have a question that is not covered here, you might find an answer on one 1. How are labels calculated in presentation-driven components like tree and property grid? - Presentation-driven components apply default BIS rules when creating content for these components. The rules include some label overrides whose behavior is described in detail [here]($docs/presentation/Advanced/DefaultBisRules.md#label-overrides). + Presentation-driven components apply default BIS rules when creating content for these components. The rules include some label overrides whose behavior is described in detail [here](../presentation/Advanced/DefaultBisRules.md#label-overrides). diff --git a/docs/learning/frontend/Tools.md b/docs/learning/frontend/Tools.md index 3d6611137a0e..1477fe2a4780 100644 --- a/docs/learning/frontend/Tools.md +++ b/docs/learning/frontend/Tools.md @@ -37,11 +37,11 @@ The [ToolAdmin]($frontend) class supervises the collection of low-level input fr Routing of the interpreted, high-level events is as follows: - If there is an active tool, the events are directed to it. The active tool can either handle a particular event or ignore it. -- If the active tool does not handle a particular event, it *may* be directed to the [Idle Tool](#idle-tool). +- If the active tool does not handle a particular event, it *may* be directed to the [idle tool](#idle-tool). As mentioned above a View tool or Input Collector can temporarily interrupt a Primitive tool. The ToolAdmin handles that sequence transparently such that the Primitive tool does not have to be aware of the interruption. -A Primitive tool ends when another Primitive tool is run. The ToolAdmin establishes [Select Tool](#selection-tool) as the *default* Primitive tool. When a default tool is provided, it becomes the active tool when the iTwin.js application starts or a Primitive tool wishes to exit. Having a default tool is optional, an application can instead choose to have the [Idle Tool](#idle-tool) handle input that would normally only be directed to the active tool, like data points and resets. +A Primitive tool ends when another Primitive tool is run. The ToolAdmin establishes [Select Tool](#selection-tool) as the *default* Primitive tool. When a default tool is provided, it becomes the active tool when the iTwin.js application starts or a Primitive tool wishes to exit. Having a default tool is optional, an application can instead choose to have the [idle tool](#idle-tool) handle input that would normally only be directed to the active tool, like data points and resets. ## Idle Tool @@ -63,6 +63,8 @@ For touch devices, the Idle tool associates the following touch events with view - Double tap to fit the view - Pinch to zoom the view in and out +An application can override the standard idle tool by supplying its own customized tool to [ToolAdmin.idleTool]($frontend). + ## Selection Tool iTwin.js also provides [SelectionTool]($frontend). SelectionTool is a subclass of [PrimitiveTool]($frontend) for creating and managing a [SelectionSet]($frontend) from existing elements. A SelectionSet identifies elements of particular interest for examining properties and other interactions. diff --git a/docs/learning/frontend/Views.md b/docs/learning/frontend/Views.md index dd57987fbe15..2ffead17383b 100644 --- a/docs/learning/frontend/Views.md +++ b/docs/learning/frontend/Views.md @@ -1,6 +1,6 @@ # Using Views in iTwin.js -A *View* renders geometry from one or more [Models]($docs/bis/intro/model-fundamentals) of an iModel in a web browser. iTwin.js applications can embed and interact with Views anywhere on a web page via an `HTMLDivElement`. +A *View* renders geometry from one or more [Models](../../bis/intro/model-fundamentals) of an iModel in a web browser. iTwin.js applications can embed and interact with Views anywhere on a web page via an `HTMLDivElement`. Views are managed by the [ViewManager]($frontend) class, using [IModelApp.viewManager]($frontend). diff --git a/docs/learning/iModelHub/Events.md b/docs/learning/iModelHub/Events.md index dc8f4028f696..93486c574d33 100644 --- a/docs/learning/iModelHub/Events.md +++ b/docs/learning/iModelHub/Events.md @@ -36,7 +36,7 @@ When a user [subscribes to events](#creating-events-subscription), they have to To receive `IModelHubEvent`s, user has to create an `EventSubscription`. Creating a subscription requires the user to specify an array of [event types](#event-types) they want to receive. -Creating subscription requires user to have an [access token]($docs/learning/common/AccessToken.md) and have a valid [iModel id](./imodels/GetiModel.md). +Creating subscription requires user to have an [access token](../common/AccessToken.md) and have a valid [iModel id](./imodels/GetiModel.md). Example: @@ -58,7 +58,7 @@ If `EventHandler.getEvent` is called with a timeout duration specified, this req `EventHandler.createListener` can be used to handle repeated calls to `EventHandler.getEvent` and `EventHandler.getSASToken`. -Authentication callback example, similar to [getting access token]($docs/learning/common/AccessToken.md). `AccessToken` could be retrieved from credentials stored somewhere else or refreshed before it expires. +Authentication callback example, similar to [getting access token](../common/AccessToken.md). `AccessToken` could be retrieved from credentials stored somewhere else or refreshed before it expires. Listener callback example. This callback just logs the type of the `IModelHubEvent` received. diff --git a/docs/learning/iModelHub/Permissions.md b/docs/learning/iModelHub/Permissions.md index 581de35899cd..3c3a4227b410 100644 --- a/docs/learning/iModelHub/Permissions.md +++ b/docs/learning/iModelHub/Permissions.md @@ -32,4 +32,4 @@ User that only has Read iModel permission can work with iModel, but they will be Permissions automatically included: _Read iModel_ -Modify iModel permission allows making changes to the iModel. It means that users will be able to manage `Locks` and push `Changeset`s to iModelHub. See [concurrency control]($docs/learning/backend/concurrencycontrol) and [BriefcaseDb.pushChanges]($backend). +Modify iModel permission allows making changes to the iModel. It means that users will be able to manage `Locks` and push `Changeset`s to iModelHub. See [concurrency control](../backend/concurrencycontrol) and [BriefcaseDb.pushChanges]($backend). diff --git a/docs/learning/iModelHub/iModels/CreateiModel.md b/docs/learning/iModelHub/iModels/CreateiModel.md index b8fa6dc436b6..d0dc75b67376 100644 --- a/docs/learning/iModelHub/iModels/CreateiModel.md +++ b/docs/learning/iModelHub/iModels/CreateiModel.md @@ -1,6 +1,6 @@ # iModel creation -To start working with iModelHub, an iModel for an [iTwin]($docs/learning/Glossary.md#itwin) has to be created. End users should usually create the iModel for an iTwin through iModelHub website. It's also possible to use the [BackendHubAccess.createNewIModel]($backend) method on [IModelHost.hubAccess]($backend) to create a new iModel in iModelHub. +To start working with iModelHub, an iModel for an [iTwin](../../Glossary.md#itwin) has to be created. End users should usually create the iModel for an iTwin through iModelHub website. It's also possible to use the [BackendHubAccess.createNewIModel]($backend) method on [IModelHost.hubAccess]($backend) to create a new iModel in iModelHub. ## iModel initialization diff --git a/docs/learning/iModelHub/iModels/index.md b/docs/learning/iModelHub/iModels/index.md index f7d4ef750eac..504ef2040f12 100644 --- a/docs/learning/iModelHub/iModels/index.md +++ b/docs/learning/iModelHub/iModels/index.md @@ -1,6 +1,6 @@ # iModels -To work with iModelHub, an [iModel](../../Glossary.md#iModel) has to be created for the ITwin. You can read more about iModels in the [overview page]($docs/learning/iModels.md). +To work with iModelHub, an [iModel](../../Glossary.md#iModel) has to be created for the ITwin. You can read more about iModels in the [overview page](../../iModels.md). ## Working with iModels diff --git a/docs/learning/leftNav.md b/docs/learning/leftNav.md index 79f9f4bda804..41e5130640d3 100644 --- a/docs/learning/leftNav.md +++ b/docs/learning/leftNav.md @@ -5,7 +5,7 @@ - [Common](./common/index.md) - [iTwin service clients](./clients/index.md) - [Geometry](./geometry/index.md) -- [Presentation]($docs/presentation/index.md) +- [Presentation](../presentation/index.md) - [UI](./ui/index.md) --- diff --git a/docs/learning/tutorials/create-test-imodel-itwin-sync.md b/docs/learning/tutorials/create-test-imodel-itwin-sync.md index 9568b47c41e2..4d7cb5487f3b 100644 --- a/docs/learning/tutorials/create-test-imodel-itwin-sync.md +++ b/docs/learning/tutorials/create-test-imodel-itwin-sync.md @@ -2,7 +2,7 @@ This tutorial will describe steps to get started with iTwin.js, using the free trial test environment. We will outline creating a Bentley user account, creating a starter iModel, then loading the starter iModel with data from source files on your desktop. At the end of the tutorial, you should have an iModel containing your own data that you will be able to view either on the web, with in a localhost web application, or with a local Electron app. -You should have a basic understanding of [iModels]($docs/learning/imodels.md), [iModelHub]($docs/learning/imodelhub/index.md), [iModel Connectors]($docs/learning/imodel-connectors.md), but don't worry if any of those concepts aren't entirely clear. +You should have a basic understanding of [iModels](../imodels.md), [iModelHub](../imodelhub/index.md), [iModel Connectors](../imodel-connectors.md), but don't worry if any of those concepts aren't entirely clear. ## Create iModel diff --git a/docs/learning/tutorials/create-test-imodel-offline.md b/docs/learning/tutorials/create-test-imodel-offline.md index 4e5e67641de1..daacad67aa05 100644 --- a/docs/learning/tutorials/create-test-imodel-offline.md +++ b/docs/learning/tutorials/create-test-imodel-offline.md @@ -2,7 +2,7 @@ Get started with iTwin.js in your local environment. It is free, with no iTwin subscription requirement or trial periods. -[Snapshot iModels]($docs/learning/backend/accessingimodels.md/#snapshot-imodels) are a static but intelligent format representing the state of an iModel at a point in time. Once created, they can not be modified. And do not have a connection with iModelHub. +[Snapshot iModels](../backend/accessingimodels.md/#snapshot-imodels) are a static but intelligent format representing the state of an iModel at a point in time. Once created, they can not be modified. And do not have a connection with iModelHub. ## Download iTwin Snapshot diff --git a/docs/learning/tutorials/create-test-imodel-sample.md b/docs/learning/tutorials/create-test-imodel-sample.md index a43d048be63e..934096402b17 100644 --- a/docs/learning/tutorials/create-test-imodel-sample.md +++ b/docs/learning/tutorials/create-test-imodel-sample.md @@ -13,28 +13,28 @@ The quickest way to get access to an iTwin Platform hosted iModel is by creating A metrostation located in Philadelphia. Contains platform, rails, and subway cars. -![stadium]($docs/learning/tutorials/images/metrostation.png) +![stadium](./images/metrostation.png) ### Stadium Soccer stadium in Singapore. Features landscape details and a metro station. This is the largest sample iModel. -![stadium]($docs/learning/tutorials/images/stadium.png) +![stadium](./images/stadium.png) ### Retail Building Sample Cafe and apartments. -![retail-building-sample]($docs/learning/tutorials/images/retail-building-sample.png) +![retail-building-sample](./images/retail-building-sample.png) ### Bay Town Process Plant Simple processing plant. This is the smallest sample iModel. -![bay-town-process-plant]($docs/learning/tutorials/images/bay-town-process-plant.png) +![bay-town-process-plant](./images/bay-town-process-plant.png) ### House Sample Features several 2D drawings and sheets. -![house-sample]($docs/learning/tutorials/images/house-sample.png) +![house-sample](./images/house-sample.png) diff --git a/docs/learning/tutorials/develop-agent.md b/docs/learning/tutorials/develop-agent.md index ce033498e5bd..6013464bb33b 100644 --- a/docs/learning/tutorials/develop-agent.md +++ b/docs/learning/tutorials/develop-agent.md @@ -2,14 +2,14 @@ ## Setup -- [Install necessary prerequisites]($docs/learning/tutorials/development-prerequisites). +- [Install necessary prerequisites](./development-prerequisites). - [Register an Agent Application](https://developer.bentley.com/register/) - Give your agent application a name. - Choose "Service" application type. - Select necessary API associations - Be sure to save the secret somewhere safe - it is only shown once - [Clone agent-starter repo](https://github.com/iTwin/agent-starter) -- If you do not have access to an iModel, follow one of our tutorials to [create an iModel]($docs/learning/tutorials/index.md) +- If you do not have access to an iModel, follow one of our tutorials to [create an iModel](./index.md) - Add `{client_id}@apps.imsoidc.bentley.com` as a project participant of your test iModel using the "[My sample iModels](https://developer.bentley.com/my-imodels/)" page. > Allow some time after registering the agent application. The identity profile of the agent is being created in the background and can take between 5 and 10 minutes diff --git a/docs/learning/tutorials/develop-desktop-viewer.md b/docs/learning/tutorials/develop-desktop-viewer.md index 4dda363cc647..6f2719b726fa 100644 --- a/docs/learning/tutorials/develop-desktop-viewer.md +++ b/docs/learning/tutorials/develop-desktop-viewer.md @@ -2,7 +2,7 @@ ## Setup -- [Install necessary prerequisites]($docs/learning/tutorials/development-prerequisites). +- [Install necessary prerequisites](./development-prerequisites.md). - From a terminal, `npx create-react-app your-app-name --template @itwin/desktop-viewer --scripts-version @bentley/react-scripts` - This will generate a new application based on the iTwin Viewer React component in the `your-app-name` directory. - Open the `your-app-name` directory in VS Code @@ -29,9 +29,9 @@ Once your new application is saved a client ID is generated, add the client ID a From a terminal at your application's root directory, `npm run build`. This will create both the frontend in the "build" folder and backend in the "lib" folder within the application's root directory. It is not necessary to build the frontend during development. -The app will open a pre-packaged offline snapshot iModel. You will likely want to use your own snapshot iModel. Follow the [Create a snapshot iModel]($docs/learning/tutorials/create-test-imodel-offline) tutorial. Then open your snapshot by clicking the Home button and selecting "Open Offline Snapshot". Alternatively, set the absolute path of your snapshot in `.env.local` using `ITWIN_VIEWER_SNAPSHOT` variable prior to running `npm run start`. +The app will open a pre-packaged offline snapshot iModel. You will likely want to use your own snapshot iModel. Follow the [Create a snapshot iModel](./create-test-imodel-offline) tutorial. Then open your snapshot by clicking the Home button and selecting "Open Offline Snapshot". Alternatively, set the absolute path of your snapshot in `.env.local` using `ITWIN_VIEWER_SNAPSHOT` variable prior to running `npm run start`. -Desktop apps can also open cloud hosted iModels. If you do not have access to one, follow one of our tutorials to [create an online iModel]($docs/learning/tutorials/index.md). Then open your online iModel by selecting "Open Online iModel" and logging in. +Desktop apps can also open cloud hosted iModels. If you do not have access to one, follow one of our tutorials to [create an online iModel](./index.md). Then open your online iModel by selecting "Open Online iModel" and logging in. ## Useful Links @@ -42,5 +42,5 @@ Desktop apps can also open cloud hosted iModels. If you do not have access to on ## Next Steps -- [iTwin Viewer - "Hello World"]($docs/learning/tutorials/hello-world-viewer/) +- [iTwin Viewer - "Hello World"](./hello-world-viewer) - [Visit the iTwin Sample Showcase](https://www.itwinjs.org/sample-showcase/) diff --git a/docs/learning/tutorials/develop-web-viewer.md b/docs/learning/tutorials/develop-web-viewer.md index 164c54a1eff8..cc8ee23dbaa7 100644 --- a/docs/learning/tutorials/develop-web-viewer.md +++ b/docs/learning/tutorials/develop-web-viewer.md @@ -2,7 +2,7 @@ ## Setup -- [Install necessary prerequisites]($docs/learning/tutorials/development-prerequisites). +- [Install necessary prerequisites](./development-prerequisites.md). - From a terminal, `npx create-react-app your-app-name --template @itwin/web-viewer --scripts-version @bentley/react-scripts` - This will generate a new application based on the iTwin Viewer React component in the `your-app-name` directory. - Open the `your-app-name` directory in VS Code. @@ -42,5 +42,5 @@ ## Next Steps -- [iTwin Viewer - "Hello World"]($docs/learning/tutorials/hello-world-viewer/) +- [iTwin Viewer - "Hello World"](./hello-world-viewer.md) - [Visit the iTwin Sample Showcase](https://www.itwinjs.org/sample-showcase/) diff --git a/docs/learning/tutorials/explore-imodel-console.md b/docs/learning/tutorials/explore-imodel-console.md index dc2ad7feab30..8f8f0f68a8cf 100644 --- a/docs/learning/tutorials/explore-imodel-console.md +++ b/docs/learning/tutorials/explore-imodel-console.md @@ -11,11 +11,11 @@ Execute queries ## Learn more -[Learn more about ECSQL]($docs/learning/ecsql) +[Learn more about ECSQL](../ecsql.md) Relaunch iModel Console tutorial by clicking the gear icon in the header -![relaunch imodelconsole tutorial]($docs/learning/tutorials/images/launch-console-tutorial.png) +![relaunch imodelconsole tutorial](./images/launch-console-tutorial.png)

diff --git a/docs/learning/tutorials/explore-schema-browser.md b/docs/learning/tutorials/explore-schema-browser.md index 96fb01f3ffba..0a878a6c8a2e 100644 --- a/docs/learning/tutorials/explore-schema-browser.md +++ b/docs/learning/tutorials/explore-schema-browser.md @@ -7,13 +7,13 @@ - In header, click the gear icon - Select "Schema Explorer" -![launch schema explorer]($docs/learning/tutorials/images/launch-schema-explorer.png) +![launch schema explorer](./images/launch-schema-explorer.png) - Explore schemas in iModel ## Learn More -[Learn more about Base Infrastructure Schemas (BIS)]($docs/bis) +[Learn more about Base Infrastructure Schemas (BIS)](../../bis/index.md)

diff --git a/docs/learning/tutorials/index.md b/docs/learning/tutorials/index.md index 8cf12d4e22b7..dcf928ef7157 100644 --- a/docs/learning/tutorials/index.md +++ b/docs/learning/tutorials/index.md @@ -34,7 +34,7 @@ Test iModels can be used for local development. There are a few different ways t ## Support -Please see the [Community Resources]($docs/learning/CommunityResources.md) page for the best places to get more help. +Please see the [Community Resources](../CommunityResources.md) page for the best places to get more help.