Skip to content

Commit 347b3d7

Browse files
authored
Merge pull request #219 from microbit-foundation/194-implement-3d-inspection-of-data-samples-on-cursor-hover
194 implement 3d inspection of data samples on cursor hover
2 parents 2ef842f + c5f197b commit 347b3d7

File tree

14 files changed

+317
-84
lines changed

14 files changed

+317
-84
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script lang="ts">
2+
import View3D from './View3D.svelte';
3+
import { Vector3 } from './View3DUtility';
4+
5+
6+
export let dataPoint: Vector3
7+
export let position: {x: number, y: number}
8+
export let size: number
9+
export let isOpen: boolean
10+
11+
</script>
12+
13+
{#if isOpen}
14+
15+
<div
16+
class="fixed z-10"
17+
style="left: {position.x}px; top: {position.y}px;"
18+
>
19+
<div
20+
class="
21+
absolute
22+
border-gray-200
23+
overflow-hidden
24+
border
25+
border-solid
26+
relative
27+
bg-white
28+
rounded-1
29+
shadow-dark-400
30+
shadow-md
31+
flex
32+
justify-center"
33+
style="width: {size}px; height: {size}px;"
34+
>
35+
<View3D {dataPoint} height={size} width={size} smoothing={true}/>
36+
</div>
37+
38+
</div>
39+
{/if}
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
<script lang="ts">
2-
import { t } from "../../i18n";
2+
import { t } from "../../i18n";
33
import { compatibility } from "../../script/stores/uiStore";
4-
import Live3DView from "./Live3DView.svelte";
4+
import View3DUnsafe from "./View3DUnsafe.svelte";
5+
import { Vector3 } from './View3DUtility';
56
67
export let smoothing = false;
78
export let width: number;
89
export let height: number;
10+
export let dataPoint: Vector3;
911
1012
const webGlCompatible = $compatibility.webGL
1113
</script>
1214

1315
{#if webGlCompatible}
14-
<Live3DView
15-
smoothing={smoothing}
16-
width={width}
17-
height={height}
16+
<View3DUnsafe
17+
{smoothing}
18+
{width}
19+
{height}
20+
{dataPoint}
1821
/>
1922
{:else}
2023
<div
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script lang="ts">
2+
import { currentData } from '../../script/stores/mlStore';
3+
import View3D from './View3D.svelte';
4+
import { Vector3 } from './View3DUtility';
5+
6+
export let smoothing = false;
7+
export let width: number;
8+
export let height: number;
9+
export let freeze = false
10+
11+
let liveDataPoint: Vector3 = {x: 0, y: 0, z: 0}
12+
13+
$: {
14+
if (!freeze){
15+
liveDataPoint = $currentData
16+
}
17+
}
18+
19+
</script>
20+
21+
<View3D
22+
{smoothing}
23+
{width}
24+
{height}
25+
dataPoint={liveDataPoint}
26+
/>

src/components/3d-inspector/Live3DView.svelte renamed to src/components/3d-inspector/View3DUnsafe.svelte

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import { onDestroy, onMount } from "svelte";
33
import * as THREE from "three";
44
import Smoother from "../../script/utils/Smoother";
5-
import Live3DUtility, { type Vector3 } from "./Live3DUtility";
6-
import { currentData } from '../../script/stores/mlStore';
5+
import Live3DUtility, { type Vector3 } from "./View3DUtility";
76
87
// TODO: The file has a lot of hardcoded (somewhat arbitrary) number values. Go through them and check if a refactor is in order
98
@@ -13,6 +12,7 @@
1312
export let smoothing = false;
1413
export let width: number;
1514
export let height: number;
15+
export let dataPoint: Vector3;
1616
1717
/**
1818
* VARIABLES DEFINED IN FUNCTIONS OR FROM ELEMENTS
@@ -50,7 +50,10 @@
5050
/**
5151
* Setup reactive functionality
5252
*/
53-
$: handleNewDataPoint($currentData);
53+
$: {
54+
lastDataPoint = dataPoint
55+
updateCameraTarget(dataPoint)
56+
}
5457
$: updateCanvasSize(height, width);
5558
5659
function onMicrobitModelLoad(model: THREE.Scene) {
@@ -61,11 +64,6 @@
6164
updateFrame();
6265
}
6366
64-
function handleNewDataPoint(data: Vector3) {
65-
lastDataPoint = data;
66-
updateCameraTarget(data);
67-
}
68-
6967
// TODO: Consider refactoring this to use cam location params.
7068
// If the camera location is changed to control where the model is in the canvas, the
7169
// values in this function needs changing to match
@@ -81,12 +79,16 @@
8179
// X and Y need different mappings than Z, as Z points up/downwards and therefore require different
8280
// mapping.
8381
const mapToCameraDistance = (val: number): number => {
84-
if (val < 0) return val * -1.5;
82+
if (val < 0) {
83+
return val * -1.5;
84+
}
8585
return val * 0.6;
8686
};
8787
8888
const mapToCameraDistanceZ = (val: number): number => {
89-
if (val < 0) return val * -.7;
89+
if (val < 0) {
90+
return val * -.7;
91+
}
9092
return val * 1.5;
9193
};
9294
@@ -97,7 +99,9 @@
9799
mapToCameraDistance(data.y),
98100
mapToCameraDistanceZ(data.z)
99101
);
100-
if (setCurrentDistance) cameraCurrentDistance = cameraTargetDistance;
102+
if (setCurrentDistance) {
103+
cameraCurrentDistance = cameraTargetDistance;
104+
}
101105
}
102106
103107
/**
@@ -121,8 +125,14 @@
121125
// When called. Update bars are updated with the latest information.
122126
// Camera distance and position is updated and lastly three.JS renders a new frame
123127
function updateFrame() {
124-
if (microbitModel === undefined) return; // TODO: If microbit model can ever be undefined, it has the wrong type
125-
if (canvas === undefined) return; // TODO: If canvas can ever be undefined, it has the wrong type
128+
if (microbitModel === undefined) {
129+
// TODO: If microbit model can ever be undefined, it has the wrong type
130+
return;
131+
}
132+
if (canvas === undefined) {
133+
// TODO: If canvas can ever be undefined, it has the wrong type
134+
return;
135+
}
126136
127137
updateBarSizes({
128138
x: xSmoother.process(lastDataPoint.x),
@@ -142,18 +152,23 @@
142152
* Which moves towards the target
143153
*/
144154
function updateCameraDistanceVariable(): void {
155+
// TODO: What does the -0.07 and / 6 mean in this? Clean up code
145156
const diff = Math.max(
146157
-0.07,
147158
(cameraTargetDistance - cameraCurrentDistance) / 6
148159
);
149160
150-
if (diff < 0) lastIncrease++;
161+
if (diff < 0) {
162+
lastIncrease++;
163+
}
151164
else {
152165
cameraCurrentDistance += diff;
153166
lastIncrease = 0;
154167
}
155168
156-
if (25 < lastIncrease) cameraCurrentDistance += diff;
169+
if (25 < lastIncrease) {
170+
cameraCurrentDistance += diff;
171+
}
157172
}
158173
159174
/**
@@ -162,14 +177,19 @@
162177
*/
163178
function updateCameraPosition(distance: number): void {
164179
distance = distance * 1.6 - 0.6;
165-
if (distance < 0.2) distance = 0.2;
180+
if (distance < 0.2) {
181+
distance = 0.2;
182+
}
166183
camera.position.z = -2 + 7 * distance;
167184
camera.position.x = -2 + 7 * distance;
168185
camera.position.y = -4 + 5 * distance;
169186
}
170187
171188
onDestroy(() => {
172-
if (updater !== undefined) clearInterval(updater);
189+
if (updater !== undefined) {
190+
clearInterval(updater);
191+
}
192+
canvas.remove()
173193
});
174194
175195
onMount(() => {

src/components/3d-inspector/Live3DUtility.ts renamed to src/components/3d-inspector/View3DUtility.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { writable } from 'svelte/store'
12
import * as THREE from 'three';
23
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
34

@@ -139,3 +140,12 @@ export type Vector3 = {
139140
};
140141

141142
export default Live3DUtility;
143+
144+
export const graphInspectorState =
145+
writable<{isOpen: boolean, dataPoint: Vector3, inspectorPosition: {x: number, y: number} }>(
146+
{
147+
isOpen: false,
148+
dataPoint: {x: 0, y: 0, z: 0},
149+
inspectorPosition: {x: 0, y: 0}
150+
}
151+
)

src/components/Gesture.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,10 @@
225225
<GestureTilePart small>
226226
<div class="flex p-2 h-30">
227227
{#each gesture.recordings as recording (String(gesture.ID) + String(recording.ID))}
228-
<Recording {recording} onDelete={deleteRecording} />
228+
<Recording
229+
{recording}
230+
onDelete={deleteRecording}
231+
/>
229232
{/each}
230233
</div>
231234
</GestureTilePart>

src/components/Recording.svelte

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script lang="ts">
2+
import { fade } from 'svelte/transition';
23
import type { RecordingData } from '../script/stores/mlStore';
34
import RecordingGraph from './graphs/RecordingGraph.svelte';
45
@@ -10,7 +11,9 @@
1011
1112
// Method for propagating deletion of recording
1213
function deleteClicked() {
13-
if (hide) return;
14+
if (hide) {
15+
return;
16+
}
1417
1518
hide = true;
1619
setTimeout(() => {
@@ -20,25 +23,26 @@
2023
}
2124
</script>
2225

23-
<main class="h-26 w-40 pr-3 pt-1 bg-white">
24-
<div class="relative">
25-
<div
26-
class="absolute h-26 w-40 transition ease
27-
{hide ? 'bg-white duration-500' : 'bg-transparent'}">
28-
</div>
29-
</div>
30-
<!-- Deleting button -->
31-
<div class="relative">
32-
<button class="absolute -left-2.8px -top-6px outline-none">
26+
<div class="h-26 w-40 pr-3 pt-1 bg-white relative">
27+
{#if hide}
28+
<div
29+
transition:fade
30+
class="
31+
absolute
32+
h-26
33+
w-40
34+
bg-white
35+
"
36+
/>
37+
{/if}
38+
<RecordingGraph data="{recording.data}" />
39+
<button class="absolute -left-2.8px top-0px outline-none">
3340
<div class="relative">
34-
<i class="z-1 absolute fas fa-circle fa-lg text-white"></i>
41+
<i class="z-1 absolute fas fa-circle fa-lg text-white" />
3542
<i
3643
class="z-2 absolute far fa-times-circle fa-lg transition
3744
ease cursor-pointer text-light-800 hover:text-black"
38-
on:click="{deleteClicked}"></i>
45+
on:click="{deleteClicked}" />
3946
</div>
4047
</button>
41-
</div>
42-
<!-- Graph for recording data -->
43-
<RecordingGraph data="{recording.data}" />
44-
</main>
48+
</div>

src/components/bottom/BottomPanel.svelte

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
import ConnectedLiveGraphButtons from './ConnectedLiveGraphButtons.svelte';
1111
import LiveGraphInformationSection from './LiveGraphInformationSection.svelte';
1212
import BaseDialog from '../dialogs/BaseDialog.svelte';
13-
import Live3DViewCompatabilityWrapper from '../3d-inspector/Live3DViewCompatabilityWrapper.svelte';
13+
import Live3DViewCompatabilityWrapper from '../3d-inspector/View3D.svelte';
14+
import View3DLive from '../3d-inspector/View3DLive.svelte';
1415
1516
let componentWidth: number;
1617
let connectDialogReference: ConnectDialogContainer;
@@ -74,15 +75,15 @@
7475
<div
7576
class="absolute right-0 cursor-pointer hover:bg-secondary hover:bg-opacity-10 transition"
7677
on:click={() => (isLive3DOpen = true)}>
77-
<Live3DViewCompatabilityWrapper width={160} height={160} />
78+
<View3DLive width={160} height={160} freeze={isLive3DOpen}/>
7879
</div>
7980
<BaseDialog isOpen={isLive3DOpen} onClose={() => (isLive3DOpen = false)}>
8081
<!-- hardcoded margin-left matches the size of the sidebar -->
8182
<div
8283
class="ml-75 border-gray-200 overflow-hidden border border-solid relative bg-white rounded-1 shadow-dark-400 shadow-md flex justify-center"
8384
style="height: calc(100vh - 160px); width: calc(100vh - 160px);">
8485
<div class="-mt-5 w-full h-full justify-center align-middle flex items-center">
85-
<Live3DViewCompatabilityWrapper width={600} height={600} smoothing />
86+
<View3DLive width={600} height={600} smoothing />
8687
</div>
8788
</div>
8889
</BaseDialog>

src/components/connection-prompt/ConnectDialogContainer.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
$connectionDialogState.connectionState = ConnectDialogStates.USB_DONE;
4545
})
4646
.catch(() => {
47-
// Error during flashing process
47+
// Error during flashing process
4848
$connectionDialogState.connectionState = ConnectDialogStates.MANUAL_TUTORIAL;
4949
});
5050
})

src/components/dialogs/BaseDialog.svelte

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,25 @@
1212
}
1313
</script>
1414

15-
<svelte:window on:keydown="{handleKeyPress}" />
15+
<svelte:window on:keydown={handleKeyPress} />
1616

1717
{#if isOpen}
1818
<div
1919
transition:fly
20-
class="z-10000 fixed top-0 left-0 bg-black/50 bg-blend-darken h-screen w-screen flex justify-center items-center"
21-
on:click="{onClose}">
20+
class="
21+
z-10000
22+
fixed
23+
top-0
24+
left-0
25+
bg-black/50
26+
bg-blend-darken
27+
h-screen
28+
w-screen
29+
flex
30+
justify-center
31+
items-center
32+
"
33+
on:click={onClose}>
2234
<slot />
2335
</div>
2436
{/if}

0 commit comments

Comments
 (0)