File size: 4,139 Bytes
31a2d08
 
 
 
62c50cd
5679415
 
31a2d08
 
 
 
 
 
 
 
 
 
 
 
 
c99cc8d
 
31a2d08
 
5679415
31a2d08
 
c99cc8d
5679415
c99cc8d
 
 
31a2d08
 
 
c99cc8d
31a2d08
 
 
 
c99cc8d
62c50cd
 
c99cc8d
31a2d08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5412da9
31a2d08
 
 
 
 
 
 
c99cc8d
 
 
 
31a2d08
 
 
 
 
 
 
5743069
31a2d08
 
 
d10886e
5679415
 
 
 
 
 
 
d10886e
31a2d08
5743069
31a2d08
 
c99cc8d
 
 
 
 
62c50cd
e7b5357
 
 
 
 
153165c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31a2d08
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<script lang="ts">
    import { onMount, onDestroy } from "svelte";
    import type { IViewer } from "./viewers/IViewer";
    import { createViewer } from "./viewers/ViewerFactory";
    import { ArrowLeft, Cube, WatsonHealth3DPrintMesh } from "carbon-icons-svelte";
    import type { Config } from "./utils/Config";
    import { getConfig } from "./utils/getConfig";

    interface Scene {
        name: string;
        url: string;
        thumbnail: string;
    }

    export let modelName: string;
    export let scene: Scene;
    export let onBack: () => void;

    let container: HTMLDivElement;
    let canvas: HTMLCanvasElement;
    let overlay: HTMLDivElement;
    let loadingBarFill: HTMLDivElement;

    let viewer: IViewer;
    let displayName: string;

    async function loadScene() {
        overlay.style.display = "flex";
        displayName = (await getConfig(modelName)).DisplayName || modelName;
        viewer = await createViewer(scene.url, canvas, (progress) => {
            loadingBarFill.style.width = `${progress * 100}%`;
        });
        window.addEventListener("resize", handleResize);
        window.addEventListener("keydown", handleKeyDown);
        handleResize();
        overlay.style.display = "none";
    }

    function handleResize() {
        if (!canvas || !container) return;
        requestAnimationFrame(() => {
            canvas.width = container.clientWidth;
            canvas.height = container.clientHeight;
        });
    }

    function handleKeyDown(e: KeyboardEvent) {
        if (e.code === "KeyP") {
            capture();
        }
    }

    async function capture() {
        const data = await viewer.capture();
        if (!data) {
            console.error("Failed to capture screenshot");
            return;
        }
        const a = document.createElement("a");
        a.href = data;
        a.download = `${scene.name}.png`;
        a.click();
    }

    onMount(loadScene);

    onDestroy(() => {
        viewer?.dispose();
        if (typeof window !== "undefined") {
            window.removeEventListener("resize", handleResize);
            window.removeEventListener("keydown", handleKeyDown);
        }
    });
</script>

<div class="header">
    <div class="back" aria-label="Back" aria-hidden="true" on:click={onBack}>
        <ArrowLeft size={24} />
    </div>
    <div class="spacer" />
    <button class="title-button" on:click={loadScene}>
        <!-- svelte-ignore a11y-click-events-have-key-events -->
        <!-- svelte-ignore a11y-no-static-element-interactions -->
        <h2>
            {#if displayName}
                <span class="muted" on:click={onBack}>{displayName}/</span>{scene.name.length > 16
                    ? `${scene.name.slice(0, 16)}...`
                    : scene.name}
            {:else}
                Loading...
            {/if}
        </h2>
    </button>
    <div class="desktop-spacer" />
</div>
<div class="canvas-container" bind:this={container}>
    <div bind:this={overlay} class="loading-overlay">
        <div class="loading-bar">
            <div bind:this={loadingBarFill} class="loading-bar-fill" />
        </div>
    </div>
    <canvas class="viewer-canvas" bind:this={canvas} width={800} height={600}> </canvas>
    <div class="stats">
        {#if viewer}
            <p>vertex count: {viewer.vertexCount}</p>
        {/if}
    </div>
    {#if viewer && !viewer.topoOnly}
        <div class="mode-toggle">
            <label>
                <input
                    type="radio"
                    name="modeB"
                    value="default"
                    checked
                    on:change={() => viewer.setRenderMode("default")}
                />
                <Cube class="mode-toggle-icon" />
            </label>
            <label>
                <input
                    type="radio"
                    name="modeB"
                    value="wireframe"
                    on:change={() => viewer.setRenderMode("wireframe")}
                />
                <WatsonHealth3DPrintMesh class="mode-toggle-icon" />
            </label>
        </div>
    {/if}
</div>