|
22 | 22 | MousePos, |
23 | 23 | Point, |
24 | 24 | SACNConfig, |
| 25 | + Triangle, |
25 | 26 | } from "./types"; |
26 | 27 | import { |
27 | 28 | calcPan, |
|
62 | 63 |
|
63 | 64 | let showMousePosition = false; |
64 | 65 | let showCalibrationPoints = false; |
| 66 | + let showTriangles = false; |
| 67 | + let triangles = writable<Triangle[]>([]); |
| 68 | + let activeTriangleIndex: number | null = null; |
65 | 69 | let showFixtureConfiguration = false; |
66 | 70 | let showSACNConfiguration = false; |
67 | 71 | let showSettingsMenu = false; |
|
81 | 85 | fixtures, |
82 | 86 | get(calibrationPoints), |
83 | 87 | ); |
84 | | - App.SetFixtures(goFixtures); |
| 88 | + App.SetFixtures(goFixtures).then(fetchTriangles); |
85 | 89 | }); |
86 | 90 |
|
87 | 91 | calibrationPoints.subscribe((calibrationPoints) => { |
|
90 | 94 |
|
91 | 95 | let goCalibrationPoints: { [id: string]: main.CalibrationPoint } = |
92 | 96 | convertCalibrationPointsToGo(calibrationPoints); |
93 | | - App.SetCalibrationPoints(goCalibrationPoints); |
| 97 | + App.SetCalibrationPoints(goCalibrationPoints).then(fetchTriangles); |
94 | 98 | }); |
95 | 99 |
|
96 | 100 | onMount(() => { |
|
232 | 236 | }); |
233 | 237 | }); |
234 | 238 |
|
235 | | - const toggleShowMousePosition = () => { |
236 | | - showMousePosition = !showMousePosition; |
237 | | - }; |
238 | | -
|
239 | | - const toggleShowCalibrationPoints = () => { |
240 | | - showCalibrationPoints = !showCalibrationPoints; |
241 | | - }; |
242 | | -
|
243 | 239 | const toggleShowFixtureConfiguration = () => { |
244 | 240 | showFixtureConfiguration = !showFixtureConfiguration; |
245 | 241 | }; |
|
252 | 248 | showSettingsMenu = !showSettingsMenu; |
253 | 249 | }; |
254 | 250 |
|
| 251 | + async function fetchTriangles() { |
| 252 | + try { |
| 253 | + activeTriangleIndex = null; |
| 254 | + const result = await App.GetTriangles(); |
| 255 | + triangles.set( |
| 256 | + (result || []).map((t: any) => ({ |
| 257 | + ax: t.Ax, ay: t.Ay, |
| 258 | + bx: t.Bx, by: t.By, |
| 259 | + cx: t.Cx, cy: t.Cy, |
| 260 | + })) |
| 261 | + ); |
| 262 | + } catch (err) { |
| 263 | + App.Log(`Failed to fetch triangles: ${err}`); |
| 264 | + } |
| 265 | + } |
| 266 | +
|
| 267 | + function pointInTriangle(px: number, py: number, t: Triangle): boolean { |
| 268 | + const d1 = (px - t.bx) * (t.ay - t.by) - (t.ax - t.bx) * (py - t.by); |
| 269 | + const d2 = (px - t.cx) * (t.by - t.cy) - (t.bx - t.cx) * (py - t.cy); |
| 270 | + const d3 = (px - t.ax) * (t.cy - t.ay) - (t.cx - t.ax) * (py - t.ay); |
| 271 | +
|
| 272 | + const hasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0); |
| 273 | + const hasPos = (d1 > 0) || (d2 > 0) || (d3 > 0); |
| 274 | +
|
| 275 | + return !(hasNeg && hasPos); |
| 276 | + } |
| 277 | +
|
255 | 278 | function getNewCalibrationName() { |
256 | 279 | calibrationPointCounter.update((value) => { |
257 | 280 | return value + 1; |
|
682 | 705 |
|
683 | 706 | mousePos.set({ x, y }); |
684 | 707 |
|
| 708 | + if (showTriangles) { |
| 709 | + const tris = get(triangles); |
| 710 | + let found: number | null = null; |
| 711 | + for (let i = 0; i < tris.length; i++) { |
| 712 | + if (pointInTriangle(x, y, tris[i])) { |
| 713 | + found = i; |
| 714 | + break; |
| 715 | + } |
| 716 | + } |
| 717 | + activeTriangleIndex = found; |
| 718 | + } |
| 719 | +
|
685 | 720 | if ( |
686 | 721 | get(currentlyCalibrating) !== null && |
687 | 722 | !calibrateForOnePointSelectCalibrationPoint |
|
808 | 843 | on:click={handleClickOnVideo} |
809 | 844 | > |
810 | 845 | <svg class="video-cover-svg"> |
| 846 | + {#if showTriangles} |
| 847 | + {#each $triangles as tri, index} |
| 848 | + <line |
| 849 | + class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}" |
| 850 | + x1="{tri.ax * 100}%" |
| 851 | + y1="{tri.ay * 100}%" |
| 852 | + x2="{tri.bx * 100}%" |
| 853 | + y2="{tri.by * 100}%" |
| 854 | + ></line> |
| 855 | + <line |
| 856 | + class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}" |
| 857 | + x1="{tri.bx * 100}%" |
| 858 | + y1="{tri.by * 100}%" |
| 859 | + x2="{tri.cx * 100}%" |
| 860 | + y2="{tri.cy * 100}%" |
| 861 | + ></line> |
| 862 | + <line |
| 863 | + class="triangle-line {activeTriangleIndex === index ? 'triangle-active' : ''}" |
| 864 | + x1="{tri.cx * 100}%" |
| 865 | + y1="{tri.cy * 100}%" |
| 866 | + x2="{tri.ax * 100}%" |
| 867 | + y2="{tri.ay * 100}%" |
| 868 | + ></line> |
| 869 | + {/each} |
| 870 | + {/if} |
| 871 | + |
811 | 872 | {#each $calibrationPointOutline as point, index} |
812 | 873 | <line |
813 | 874 | class="outline-line" |
|
832 | 893 | ></line> |
833 | 894 | {/if} |
834 | 895 | </svg> |
| 896 | + {#if showTriangles && activeTriangleIndex !== null && activeTriangleIndex < $triangles.length} |
| 897 | + {@const tri = $triangles[activeTriangleIndex]} |
| 898 | + <div |
| 899 | + class="triangle-fill" |
| 900 | + style="clip-path: polygon({tri.ax * 100}% {tri.ay * 100}%, {tri.bx * 100}% {tri.by * 100}%, {tri.cx * 100}% {tri.cy * 100}%);" |
| 901 | + ></div> |
| 902 | + {/if} |
835 | 903 | {#if showCalibrationPoints} |
836 | 904 | {#each Object.values($calibrationPoints) as calibrationPoint (calibrationPoint.id)} |
837 | 905 | <div |
|
966 | 1034 | Remove Calibration Point |
967 | 1035 | </button> |
968 | 1036 | <div class="settings-separator"></div> |
969 | | - <button on:click={toggleShowMousePosition} |
970 | | - >{showMousePosition |
971 | | - ? "Hide Mouse Position" |
972 | | - : "Show Mouse Position"}</button |
973 | | - > |
974 | | - <button on:click={toggleShowCalibrationPoints}> |
975 | | - {showCalibrationPoints |
976 | | - ? "Hide Calibration Points" |
977 | | - : "Show Calibration Points"} |
978 | | - </button> |
| 1037 | + <label class="checkbox-label"> |
| 1038 | + <input type="checkbox" bind:checked={showMousePosition} /> |
| 1039 | + Show Mouse Position |
| 1040 | + </label> |
| 1041 | + <label class="checkbox-label"> |
| 1042 | + <input type="checkbox" bind:checked={showCalibrationPoints} /> |
| 1043 | + Show Calibration Points |
| 1044 | + </label> |
| 1045 | + <label class="checkbox-label"> |
| 1046 | + <input type="checkbox" bind:checked={showTriangles} /> |
| 1047 | + Draw Triangles |
| 1048 | + </label> |
979 | 1049 | </div> |
980 | 1050 | <Info |
981 | 1051 | bind:addingCalibrationPoint |
|
1138 | 1208 | box-sizing: border-box; |
1139 | 1209 | } |
1140 | 1210 |
|
| 1211 | + .triangle-line { |
| 1212 | + stroke: var(--accent-orange); |
| 1213 | + stroke-width: 2px; |
| 1214 | + stroke-opacity: 0.7; |
| 1215 | + } |
| 1216 | +
|
| 1217 | + .triangle-line.triangle-active { |
| 1218 | + stroke: var(--accent-blue); |
| 1219 | + stroke-width: 3px; |
| 1220 | + stroke-opacity: 1; |
| 1221 | + } |
| 1222 | +
|
| 1223 | + .triangle-fill { |
| 1224 | + position: absolute; |
| 1225 | + top: 0; |
| 1226 | + left: 0; |
| 1227 | + width: 100%; |
| 1228 | + height: 100%; |
| 1229 | + background: var(--accent-blue); |
| 1230 | + opacity: 0.15; |
| 1231 | + pointer-events: none; |
| 1232 | + } |
| 1233 | +
|
| 1234 | + .checkbox-label { |
| 1235 | + display: flex; |
| 1236 | + align-items: center; |
| 1237 | + gap: 8px; |
| 1238 | + cursor: pointer; |
| 1239 | + } |
| 1240 | +
|
1141 | 1241 | .settings-separator { |
1142 | 1242 | margin-top: 12px; |
1143 | 1243 | } |
|
0 commit comments