bimatter-viewer-react 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -0
- package/lib/Camera/useCameraFit.d.ts +2 -0
- package/lib/GeometryUtils/useGeometryIndex.d.ts +35 -0
- package/lib/GeometryUtils/useGeometryUtils.d.ts +13 -0
- package/lib/Hotkeys/useHotkeysUtils.d.ts +2 -0
- package/lib/Loaders/BmtLoader.d.ts +51 -0
- package/lib/Model.d.ts +7 -0
- package/lib/SelectableMesh.d.ts +10 -0
- package/lib/Selector/SelectionBox.d.ts +50 -0
- package/lib/Selector/useSelector.d.ts +3 -0
- package/lib/Viewer.d.ts +21 -0
- package/lib/api/ViewerApi.d.ts +40 -0
- package/lib/api/loader.d.ts +8 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +1165 -0
- package/lib/store/ViewerStore.d.ts +19 -0
- package/lib/store/ViewerStoreContext.d.ts +2 -0
- package/lib/store/ViewerStoreProvider.d.ts +7 -0
- package/lib/store/useViewerStore.d.ts +3 -0
- package/lib/types.d.ts +9 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# React + TypeScript + Vite
|
|
2
|
+
|
|
3
|
+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
4
|
+
|
|
5
|
+
Currently, two official plugins are available:
|
|
6
|
+
|
|
7
|
+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
|
8
|
+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
|
9
|
+
|
|
10
|
+
## React Compiler
|
|
11
|
+
|
|
12
|
+
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
|
|
13
|
+
|
|
14
|
+
## Expanding the ESLint configuration
|
|
15
|
+
|
|
16
|
+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
export default defineConfig([
|
|
20
|
+
globalIgnores(['dist']),
|
|
21
|
+
{
|
|
22
|
+
files: ['**/*.{ts,tsx}'],
|
|
23
|
+
extends: [
|
|
24
|
+
// Other configs...
|
|
25
|
+
|
|
26
|
+
// Remove tseslint.configs.recommended and replace with this
|
|
27
|
+
tseslint.configs.recommendedTypeChecked,
|
|
28
|
+
// Alternatively, use this for stricter rules
|
|
29
|
+
tseslint.configs.strictTypeChecked,
|
|
30
|
+
// Optionally, add this for stylistic rules
|
|
31
|
+
tseslint.configs.stylisticTypeChecked,
|
|
32
|
+
|
|
33
|
+
// Other configs...
|
|
34
|
+
],
|
|
35
|
+
languageOptions: {
|
|
36
|
+
parserOptions: {
|
|
37
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
38
|
+
tsconfigRootDir: import.meta.dirname,
|
|
39
|
+
},
|
|
40
|
+
// other options...
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
])
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// eslint.config.js
|
|
50
|
+
import reactX from 'eslint-plugin-react-x'
|
|
51
|
+
import reactDom from 'eslint-plugin-react-dom'
|
|
52
|
+
|
|
53
|
+
export default defineConfig([
|
|
54
|
+
globalIgnores(['dist']),
|
|
55
|
+
{
|
|
56
|
+
files: ['**/*.{ts,tsx}'],
|
|
57
|
+
extends: [
|
|
58
|
+
// Other configs...
|
|
59
|
+
// Enable lint rules for React
|
|
60
|
+
reactX.configs['recommended-typescript'],
|
|
61
|
+
// Enable lint rules for React DOM
|
|
62
|
+
reactDom.configs.recommended,
|
|
63
|
+
],
|
|
64
|
+
languageOptions: {
|
|
65
|
+
parserOptions: {
|
|
66
|
+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
|
67
|
+
tsconfigRootDir: import.meta.dirname,
|
|
68
|
+
},
|
|
69
|
+
// other options...
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
])
|
|
73
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Mesh } from "three";
|
|
2
|
+
import type { MeshBVH } from "three-mesh-bvh";
|
|
3
|
+
import type { ViewerModelRef } from "../types";
|
|
4
|
+
export type IndexArray = Uint16Array | Uint32Array;
|
|
5
|
+
export type IndexRange = {
|
|
6
|
+
count: number;
|
|
7
|
+
start: number;
|
|
8
|
+
};
|
|
9
|
+
export type MeshGeometryRecord = {
|
|
10
|
+
hiddenIds: Set<number>;
|
|
11
|
+
initialVisible: boolean;
|
|
12
|
+
mesh: Mesh;
|
|
13
|
+
modelID: number;
|
|
14
|
+
originalBoundsTree: MeshBVH | null;
|
|
15
|
+
originalIndex: IndexArray;
|
|
16
|
+
visibleStateKey: string;
|
|
17
|
+
triangleRanges: Array<IndexRange & {
|
|
18
|
+
id: number;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
export type ElementIndexEntry = {
|
|
22
|
+
record: MeshGeometryRecord;
|
|
23
|
+
vertexRanges: IndexRange[];
|
|
24
|
+
};
|
|
25
|
+
export type GeometryIndex = {
|
|
26
|
+
elementIndex: Map<number, ElementIndexEntry[]>;
|
|
27
|
+
indexedModel: unknown;
|
|
28
|
+
isolatedIdsByModel: Map<number, Set<number>> | null;
|
|
29
|
+
isolatedIds: Set<number> | null;
|
|
30
|
+
records: Set<MeshGeometryRecord>;
|
|
31
|
+
};
|
|
32
|
+
export type GeometryIndexApi = {
|
|
33
|
+
buildIndex: () => GeometryIndex;
|
|
34
|
+
};
|
|
35
|
+
export default function useGeometryIndex(modelRef: ViewerModelRef): GeometryIndexApi;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GeometryIndexApi } from "./useGeometryIndex";
|
|
2
|
+
export type GeometryUtilsApi = {
|
|
3
|
+
buildIndex: GeometryIndexApi["buildIndex"];
|
|
4
|
+
getAllIds: () => number[];
|
|
5
|
+
hideByIds: (ids: number[]) => void;
|
|
6
|
+
hideSelected: () => void;
|
|
7
|
+
isolateByIds: (ids: number[]) => void;
|
|
8
|
+
isolateSelected: () => void;
|
|
9
|
+
resetIsolation: () => void;
|
|
10
|
+
showAll: () => void;
|
|
11
|
+
showByIds: (ids: number[]) => void;
|
|
12
|
+
};
|
|
13
|
+
export default function useGeometryUtils(geometryIndex: GeometryIndexApi): GeometryUtilsApi;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pako from "pako";
|
|
2
|
+
export type BmtIndexArray = Uint16Array | Uint32Array;
|
|
3
|
+
export interface BmtMaterialData {
|
|
4
|
+
r: number;
|
|
5
|
+
g: number;
|
|
6
|
+
b: number;
|
|
7
|
+
opacity: number;
|
|
8
|
+
name: number;
|
|
9
|
+
}
|
|
10
|
+
export interface BmtGeomData {
|
|
11
|
+
pos: Float32Array;
|
|
12
|
+
ind: BmtIndexArray;
|
|
13
|
+
ids: Uint32Array;
|
|
14
|
+
matrix: string;
|
|
15
|
+
mat: BmtMaterialData;
|
|
16
|
+
}
|
|
17
|
+
export type BmtModelData = Record<number, BmtGeomData>;
|
|
18
|
+
type BmtMeshData = {
|
|
19
|
+
colorId: BmtMaterialData;
|
|
20
|
+
ids: Uint8Array;
|
|
21
|
+
ind: {
|
|
22
|
+
data: Uint8Array;
|
|
23
|
+
type: number;
|
|
24
|
+
};
|
|
25
|
+
pos: Uint8Array;
|
|
26
|
+
};
|
|
27
|
+
export declare class BinaryReader {
|
|
28
|
+
view: DataView;
|
|
29
|
+
offset: number;
|
|
30
|
+
constructor(buffer: ArrayBuffer);
|
|
31
|
+
readUint8(): number;
|
|
32
|
+
readUint32(): number;
|
|
33
|
+
readBytes(length: number): Uint8Array<ArrayBufferLike>;
|
|
34
|
+
eof(): boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare class BMTLoader {
|
|
37
|
+
decodeBuffer(buffer: Uint8Array): string;
|
|
38
|
+
decoder: typeof pako;
|
|
39
|
+
textDecoder: TextDecoder;
|
|
40
|
+
ChunkType: {
|
|
41
|
+
PROP: number;
|
|
42
|
+
MESH: number;
|
|
43
|
+
STRUCTURE: number;
|
|
44
|
+
GRIDS: number;
|
|
45
|
+
MATRIX: number;
|
|
46
|
+
};
|
|
47
|
+
parseMesh(data: Uint8Array): BmtMeshData;
|
|
48
|
+
loadModel(path: string): Promise<BmtModelData>;
|
|
49
|
+
parseBinaryFile(data: ArrayBuffer): BmtModelData;
|
|
50
|
+
}
|
|
51
|
+
export {};
|
package/lib/Model.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Matrix4 } from "three";
|
|
3
|
+
import type { BmtGeomData, BmtMaterialData } from "./Loaders/BmtLoader";
|
|
4
|
+
type SelectableMeshProps = {
|
|
5
|
+
data: BmtGeomData;
|
|
6
|
+
material: BmtMaterialData;
|
|
7
|
+
meshMatrix: Matrix4;
|
|
8
|
+
};
|
|
9
|
+
export declare const SelectableMesh: React.MemoExoticComponent<({ material, data, meshMatrix, }: SelectableMeshProps) => import("react/jsx-runtime").JSX.Element>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { MutableRefObject } from "react";
|
|
2
|
+
import { Camera, Object3D, Vector2 } from "three";
|
|
3
|
+
export type ClientRectSelection = {
|
|
4
|
+
minX: number;
|
|
5
|
+
minY: number;
|
|
6
|
+
maxX: number;
|
|
7
|
+
maxY: number;
|
|
8
|
+
};
|
|
9
|
+
export type SelectionBoxMode = "contains" | "intersects";
|
|
10
|
+
export type SelectionBoxProfile = {
|
|
11
|
+
boundsCheckMs: number;
|
|
12
|
+
candidateIds: number;
|
|
13
|
+
containedCandidateVertices: number;
|
|
14
|
+
containedIdsMs: number;
|
|
15
|
+
containedVerticesVisited: number;
|
|
16
|
+
intersectsBoundsCalls: number;
|
|
17
|
+
intersectsBoundsMs: number;
|
|
18
|
+
intersectsRangeCalls: number;
|
|
19
|
+
intersectsRangeMs: number;
|
|
20
|
+
intersectsTriangleCalls: number;
|
|
21
|
+
intersectsTriangleMs: number;
|
|
22
|
+
matrixUpdateMs: number;
|
|
23
|
+
meshCount: number;
|
|
24
|
+
mode: SelectionBoxMode;
|
|
25
|
+
selectedIds: number;
|
|
26
|
+
shapecastMs: number;
|
|
27
|
+
skippedMeshCount: number;
|
|
28
|
+
totalMs: number;
|
|
29
|
+
trianglePointCalls: number;
|
|
30
|
+
trianglePointMs: number;
|
|
31
|
+
trianglePointVertices: number;
|
|
32
|
+
triangleProjectionMs: number;
|
|
33
|
+
};
|
|
34
|
+
export declare const MIN_BOX_SIZE = 6;
|
|
35
|
+
export declare function getClientSelectionRect(start: Vector2, end: Vector2): ClientRectSelection;
|
|
36
|
+
export declare function getSelectionBoxMode(start: Vector2, end: Vector2): SelectionBoxMode;
|
|
37
|
+
export declare function getBoxSelectedIds({ model, camera, domElement, rect, mode, profile, }: {
|
|
38
|
+
model: Object3D | null;
|
|
39
|
+
camera: Camera;
|
|
40
|
+
domElement: HTMLElement;
|
|
41
|
+
rect: ClientRectSelection;
|
|
42
|
+
mode: SelectionBoxMode;
|
|
43
|
+
profile?: SelectionBoxProfile;
|
|
44
|
+
}): Map<number, Set<number>>;
|
|
45
|
+
export declare function getBoxSelectedIdsProfiled(options: Parameters<typeof getBoxSelectedIds>[0]): {
|
|
46
|
+
ids: Map<number, Set<number>>;
|
|
47
|
+
profile: SelectionBoxProfile;
|
|
48
|
+
};
|
|
49
|
+
export declare function updateSelectionBoxElement(elementRef: MutableRefObject<HTMLDivElement | null>, start: Vector2, end: Vector2): void;
|
|
50
|
+
export declare function removeSelectionBoxElement(elementRef: MutableRefObject<HTMLDivElement | null>): void;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { GeometryIndexApi } from "../GeometryUtils/useGeometryIndex";
|
|
2
|
+
import type { ViewerControlsRef, ViewerModelRef } from "../types";
|
|
3
|
+
export default function useSelector(modelRef: ViewerModelRef, controlRef: ViewerControlsRef, geometryIndex: GeometryIndexApi): void;
|
package/lib/Viewer.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ComponentProps } from "react";
|
|
2
|
+
import type { BmtModelData } from "./Loaders/BmtLoader";
|
|
3
|
+
import { Canvas } from "@react-three/fiber";
|
|
4
|
+
import { type ViewerApi, type ViewerSelection } from "./api/ViewerApi";
|
|
5
|
+
import { type ViewerModelSource } from "./api/loader";
|
|
6
|
+
type ModelsData = Record<number, BmtModelData>;
|
|
7
|
+
export type ViewerModelsData = ModelsData;
|
|
8
|
+
export type ViewerProps = {
|
|
9
|
+
camera?: ComponentProps<typeof Canvas>["camera"];
|
|
10
|
+
dpr?: ComponentProps<typeof Canvas>["dpr"];
|
|
11
|
+
defaultSelected?: ViewerSelection;
|
|
12
|
+
modelUrls?: string[];
|
|
13
|
+
modelSources?: ViewerModelSource[];
|
|
14
|
+
modelsData?: ModelsData;
|
|
15
|
+
onReady?: (api: ViewerApi) => void;
|
|
16
|
+
onSelectedChange?: (selected: ViewerSelection) => void;
|
|
17
|
+
selected?: ViewerSelection;
|
|
18
|
+
showStats?: boolean;
|
|
19
|
+
};
|
|
20
|
+
declare const Viewer: import("react").ForwardRefExoticComponent<ViewerProps & import("react").RefAttributes<ViewerApi>>;
|
|
21
|
+
export default Viewer;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SelectedStore, UserDevice, ViewerStoreApi } from "../store/ViewerStore";
|
|
2
|
+
export type ViewerSelection = Record<number, number[]>;
|
|
3
|
+
export type ViewerGeometryUtilsApi = {
|
|
4
|
+
getAllIds: () => number[];
|
|
5
|
+
hideByIds: (ids: number[]) => void;
|
|
6
|
+
hideSelected: () => void;
|
|
7
|
+
isolateByIds: (ids: number[]) => void;
|
|
8
|
+
isolateSelected: () => void;
|
|
9
|
+
resetIsolation: () => void;
|
|
10
|
+
showAll: () => void;
|
|
11
|
+
showByIds: (ids: number[]) => void;
|
|
12
|
+
};
|
|
13
|
+
export type ViewerSelectorApi = {
|
|
14
|
+
addSelected: (modelID: number, ids: number[]) => void;
|
|
15
|
+
getSelected: () => ViewerSelection;
|
|
16
|
+
removeSelected: (modelID: number, ids: number[]) => void;
|
|
17
|
+
resetSelection: (modelID?: number) => void;
|
|
18
|
+
setSelected: (modelID: number, ids: number[], reset?: boolean) => void;
|
|
19
|
+
};
|
|
20
|
+
export type ViewerUtilsApi = {
|
|
21
|
+
getShowStats: () => boolean;
|
|
22
|
+
getUserDevice: () => UserDevice;
|
|
23
|
+
setShowStats: (showStats: boolean) => void;
|
|
24
|
+
};
|
|
25
|
+
export type ViewerCameraApi = {
|
|
26
|
+
fitCamera: () => void;
|
|
27
|
+
};
|
|
28
|
+
export type ViewerApi = {
|
|
29
|
+
camera: ViewerCameraApi;
|
|
30
|
+
geometryUtils: ViewerGeometryUtilsApi;
|
|
31
|
+
selector: ViewerSelectorApi;
|
|
32
|
+
utils: ViewerUtilsApi;
|
|
33
|
+
};
|
|
34
|
+
export type ViewerSceneApi = {
|
|
35
|
+
camera: ViewerCameraApi;
|
|
36
|
+
geometryUtils: ViewerGeometryUtilsApi;
|
|
37
|
+
};
|
|
38
|
+
export declare function serializeSelected(selected: SelectedStore): ViewerSelection;
|
|
39
|
+
export declare function createSelectedStore(selection: ViewerSelection): SelectedStore;
|
|
40
|
+
export declare function createPublicViewerApi(viewerStore: ViewerStoreApi, getSceneApi: () => ViewerSceneApi | null): ViewerApi;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type BmtModelData } from "../Loaders/BmtLoader";
|
|
2
|
+
export type ViewerModelSource = string | File;
|
|
3
|
+
export type ViewerLoadedModels = Record<number, BmtModelData>;
|
|
4
|
+
declare function loadModel(sources: ViewerModelSource[]): Promise<ViewerLoadedModels>;
|
|
5
|
+
export declare const loader: {
|
|
6
|
+
loadModel: typeof loadModel;
|
|
7
|
+
};
|
|
8
|
+
export {};
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { default as Viewer } from "./Viewer";
|
|
2
|
+
export type { ViewerModelsData, ViewerProps } from "./Viewer";
|
|
3
|
+
export type { ViewerApi, ViewerCameraApi, ViewerGeometryUtilsApi, ViewerSelection, ViewerSelectorApi, ViewerUtilsApi, } from "./api/ViewerApi";
|
|
4
|
+
export { BMTLoader } from "./Loaders/BmtLoader";
|
|
5
|
+
export type { BmtGeomData, BmtIndexArray, BmtMaterialData, BmtModelData, } from "./Loaders/BmtLoader";
|
|
6
|
+
export { loader } from "./api/loader";
|
|
7
|
+
export type { ViewerLoadedModels, ViewerModelSource } from "./api/loader";
|
|
8
|
+
export { createViewerStore, } from "./store/ViewerStore";
|
|
9
|
+
export { ViewerStoreProvider } from "./store/ViewerStoreProvider";
|
|
10
|
+
export { useViewerStore, useViewerStoreApi, } from "./store/useViewerStore";
|
|
11
|
+
export type { SelectedStore, UserDevice, ViewerStore, ViewerStoreApi, } from "./store/ViewerStore";
|