@tableslayer/ui 0.1.3 → 0.1.4
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/package.json +2 -13
- package/src/lib/components/Avatar/Avatar.svelte +82 -0
- package/src/lib/components/Avatar/AvatarFileInput.svelte +85 -0
- package/src/lib/components/Avatar/AvatarPopover.svelte +34 -0
- package/src/lib/components/Avatar/index.ts +4 -0
- package/src/lib/components/Avatar/types.ts +24 -0
- package/src/lib/components/BrushSizeSlider/BrushSizeSlider.svelte +174 -0
- package/src/lib/components/BrushSizeSlider/index.ts +1 -0
- package/src/lib/components/Button/Button.svelte +182 -0
- package/src/lib/components/Button/ConfirmActionButton.svelte +98 -0
- package/src/lib/components/Button/IconButton.svelte +121 -0
- package/src/lib/components/Button/RadioButton.svelte +93 -0
- package/src/lib/components/Button/index.ts +5 -0
- package/src/lib/components/Button/types.ts +54 -0
- package/src/lib/components/CardFan/CardFan.svelte +165 -0
- package/src/lib/components/CardFan/index.ts +2 -0
- package/src/lib/components/CardFan/types.ts +6 -0
- package/src/lib/components/CodeBlock/Code.svelte +7 -0
- package/src/lib/components/CodeBlock/CodeBlock.svelte +102 -0
- package/src/lib/components/CodeBlock/index.ts +3 -0
- package/src/lib/components/CodeBlock/types.ts +10 -0
- package/src/lib/components/ColorMode/ColorMode.svelte +8 -0
- package/src/lib/components/ColorMode/index.ts +2 -0
- package/src/lib/components/ColorMode/types.ts +12 -0
- package/src/lib/components/ColorPicker/ColorPicker.svelte +838 -0
- package/src/lib/components/ColorPicker/ColorPickerSwatch.svelte +32 -0
- package/src/lib/components/ColorPicker/index.ts +3 -0
- package/src/lib/components/ColorPicker/types.ts +51 -0
- package/src/lib/components/ContextMenu/ContextMenu.svelte +86 -0
- package/src/lib/components/ContextMenu/index.ts +2 -0
- package/src/lib/components/ContextMenu/types.ts +15 -0
- package/src/lib/components/DrawingSliders/DrawingSliders.svelte +379 -0
- package/src/lib/components/DrawingSliders/index.ts +1 -0
- package/src/lib/components/Editor/Editor.svelte +825 -0
- package/src/lib/components/Editor/index.ts +1 -0
- package/src/lib/components/FogSliders/FogSliders.svelte +33 -0
- package/src/lib/components/FogSliders/index.ts +1 -0
- package/src/lib/components/Hr/Hr.svelte +15 -0
- package/src/lib/components/Hr/index.ts +1 -0
- package/src/lib/components/Icon/Icon.svelte +6 -0
- package/src/lib/components/Icon/index.ts +2 -0
- package/src/lib/components/Icon/types.ts +20 -0
- package/src/lib/components/Input/DualInputSlider.svelte +126 -0
- package/src/lib/components/Input/FileInput.svelte +176 -0
- package/src/lib/components/Input/FormControl.svelte +150 -0
- package/src/lib/components/Input/FormError.svelte +37 -0
- package/src/lib/components/Input/Input.svelte +56 -0
- package/src/lib/components/Input/InputCheckbox.svelte +99 -0
- package/src/lib/components/Input/InputSlider.svelte +86 -0
- package/src/lib/components/Input/Label.svelte +19 -0
- package/src/lib/components/Input/index.ts +9 -0
- package/src/lib/components/Input/types.ts +39 -0
- package/src/lib/components/Link/Link.svelte +41 -0
- package/src/lib/components/Link/LinkBox.svelte +20 -0
- package/src/lib/components/Link/LinkOverlay.svelte +23 -0
- package/src/lib/components/Link/index.ts +4 -0
- package/src/lib/components/Link/types.ts +17 -0
- package/src/lib/components/Loading/Loader.svelte +60 -0
- package/src/lib/components/Loading/Skeleton.svelte +9 -0
- package/src/lib/components/Loading/index.ts +2 -0
- package/src/lib/components/Logo/Logo.svelte +16 -0
- package/src/lib/components/Logo/index.ts +1 -0
- package/src/lib/components/MarkerTooltip/MarkerTooltip.svelte +435 -0
- package/src/lib/components/MarkerTooltip/index.ts +1 -0
- package/src/lib/components/Menu/SelectorMenu.svelte +280 -0
- package/src/lib/components/Menu/index.ts +2 -0
- package/src/lib/components/Menu/types.ts +17 -0
- package/src/lib/components/MyCounterButton.svelte +11 -0
- package/src/lib/components/Panel/index.ts +2 -0
- package/src/lib/components/Panel/panel.svelte +18 -0
- package/src/lib/components/Panel/types.ts +8 -0
- package/src/lib/components/PersistButton/PersistButton.svelte +100 -0
- package/src/lib/components/PersistButton/index.ts +1 -0
- package/src/lib/components/Popover/Popover.svelte +81 -0
- package/src/lib/components/Popover/index.ts +2 -0
- package/src/lib/components/Popover/types.ts +19 -0
- package/src/lib/components/PropsTable/PropsTable.svelte +107 -0
- package/src/lib/components/RadialMenu/EffectPreview.svelte +36 -0
- package/src/lib/components/RadialMenu/EffectPreviewScene.svelte +194 -0
- package/src/lib/components/RadialMenu/RadialMenu.svelte +503 -0
- package/src/lib/components/RadialMenu/RadialMenuItem.svelte +176 -0
- package/src/lib/components/RadialMenu/index.ts +2 -0
- package/src/lib/components/RadialMenu/types.ts +35 -0
- package/src/lib/components/Select/Select.svelte +342 -0
- package/src/lib/components/Select/index.ts +2 -0
- package/src/lib/components/Select/types.ts +22 -0
- package/src/lib/components/Spacer/Spacer.svelte +14 -0
- package/src/lib/components/Spacer/index.ts +2 -0
- package/src/lib/components/Spacer/types.ts +5 -0
- package/src/lib/components/Stage/components/AnnotationLayer/AnnotationLayer.svelte +445 -0
- package/src/lib/components/Stage/components/AnnotationLayer/AnnotationMaterial.svelte +167 -0
- package/src/lib/components/Stage/components/AnnotationLayer/types.ts +196 -0
- package/src/lib/components/Stage/components/CursorLayer/CursorLayer.svelte +148 -0
- package/src/lib/components/Stage/components/CursorLayer/cursor.svg +26 -0
- package/src/lib/components/Stage/components/CursorLayer/index.ts +2 -0
- package/src/lib/components/Stage/components/CursorLayer/types.ts +23 -0
- package/src/lib/components/Stage/components/DrawingLayer/DrawingMaterial.svelte +364 -0
- package/src/lib/components/Stage/components/DrawingLayer/types.ts +65 -0
- package/src/lib/components/Stage/components/EdgeOverlayLayer/EdgeOverlayLayer.svelte +72 -0
- package/src/lib/components/Stage/components/EdgeOverlayLayer/types.ts +34 -0
- package/src/lib/components/Stage/components/FogLayer/FogLayer.svelte +75 -0
- package/src/lib/components/Stage/components/FogLayer/types.ts +51 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarLayer.svelte +249 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarMaterial.svelte +200 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/types.ts +116 -0
- package/src/lib/components/Stage/components/GridLayer/GridLayer.svelte +20 -0
- package/src/lib/components/Stage/components/GridLayer/GridMaterial.svelte +69 -0
- package/src/lib/components/Stage/components/GridLayer/types.ts +79 -0
- package/src/lib/components/Stage/components/LayerInput/LayerInput.svelte +300 -0
- package/src/lib/components/Stage/components/MapLayer/MapLayer.svelte +196 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/GifDataSource.ts +265 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/IMapDataSource.ts +55 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/ImageDataSource.ts +87 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/VideoDataSource.ts +150 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/dataSourceFactory.ts +48 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/index.ts +16 -0
- package/src/lib/components/Stage/components/MapLayer/types.ts +58 -0
- package/src/lib/components/Stage/components/MarkerLayer/MarkerLayer.svelte +398 -0
- package/src/lib/components/Stage/components/MarkerLayer/MarkerToken.svelte +262 -0
- package/src/lib/components/Stage/components/MarkerLayer/types.ts +126 -0
- package/src/lib/components/Stage/components/MeasurementLayer/MeasurementLayer.svelte +364 -0
- package/src/lib/components/Stage/components/MeasurementLayer/MeasurementManager.svelte +473 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/BaseMeasurement.ts +427 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/BeamMeasurement.ts +105 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/CircleMeasurement.ts +98 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/ConeMeasurement.ts +163 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/LineMeasurement.ts +102 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/RectangleMeasurement.ts +120 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/index.ts +7 -0
- package/src/lib/components/Stage/components/MeasurementLayer/types.ts +94 -0
- package/src/lib/components/Stage/components/MeasurementLayer/utils/canvasDrawing.ts +357 -0
- package/src/lib/components/Stage/components/MeasurementLayer/utils/distanceCalculations.ts +170 -0
- package/src/lib/components/Stage/components/ParticleSystem/ParticleSystem.svelte +220 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/ash.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/leaves.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/rain.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/snow.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/rng.js +20 -0
- package/src/lib/components/Stage/components/ParticleSystem/types.ts +95 -0
- package/src/lib/components/Stage/components/PerformanceDebugger/PerformanceDebugger.svelte +144 -0
- package/src/lib/components/Stage/components/PerformanceDebugger/index.ts +1 -0
- package/src/lib/components/Stage/components/PerformanceOverlay/PerformanceOverlay.svelte +208 -0
- package/src/lib/components/Stage/components/PerformanceOverlay/index.ts +1 -0
- package/src/lib/components/Stage/components/PointerInputManager/PointerInputManager.svelte +201 -0
- package/src/lib/components/Stage/components/Scene/Scene.svelte +651 -0
- package/src/lib/components/Stage/components/Scene/luts.ts +24 -0
- package/src/lib/components/Stage/components/Scene/types.ts +225 -0
- package/src/lib/components/Stage/components/Stage/Stage.svelte +332 -0
- package/src/lib/components/Stage/components/Stage/types.ts +136 -0
- package/src/lib/components/Stage/components/WeatherLayer/WeatherLayer.svelte +135 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/AshPreset.ts +71 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/LeavesPreset.ts +70 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/RainPreset.ts +68 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/SnowPreset.ts +70 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/index.ts +6 -0
- package/src/lib/components/Stage/components/WeatherLayer/types.ts +35 -0
- package/src/lib/components/Stage/helpers/clippingPlaneStore.svelte.ts +28 -0
- package/src/lib/components/Stage/helpers/debugState.svelte.ts +18 -0
- package/src/lib/components/Stage/helpers/grid.ts +548 -0
- package/src/lib/components/Stage/helpers/lazyBrush.ts +171 -0
- package/src/lib/components/Stage/helpers/performanceMetrics.svelte.ts +220 -0
- package/src/lib/components/Stage/helpers/utils.ts +21 -0
- package/src/lib/components/Stage/index.ts +49 -0
- package/src/lib/components/Stage/shaders/AnnotationEffects.frag +1070 -0
- package/src/lib/components/Stage/shaders/Annotations.frag +29 -0
- package/src/lib/components/Stage/shaders/Drawing.frag +83 -0
- package/src/lib/components/Stage/shaders/Drawing.vert +5 -0
- package/src/lib/components/Stage/shaders/Fog.frag +147 -0
- package/src/lib/components/Stage/shaders/FractalNoise.frag +96 -0
- package/src/lib/components/Stage/shaders/GridShader.frag +174 -0
- package/src/lib/components/Stage/shaders/Overlay.frag +23 -0
- package/src/lib/components/Stage/shaders/Overlay.vert +0 -0
- package/src/lib/components/Stage/shaders/Particles.frag +27 -0
- package/src/lib/components/Stage/shaders/Particles.vert +51 -0
- package/src/lib/components/Stage/shaders/ToolOutline.frag +59 -0
- package/src/lib/components/Stage/shaders/default.vert +8 -0
- package/src/lib/components/Stage/types.ts +4 -0
- package/src/lib/components/Table/Table.svelte +16 -0
- package/src/lib/components/Table/Td.svelte +17 -0
- package/src/lib/components/Table/Th.svelte +18 -0
- package/src/lib/components/Table/index.ts +4 -0
- package/src/lib/components/Table/types.ts +14 -0
- package/src/lib/components/Text/Text.svelte +23 -0
- package/src/lib/components/Text/index.ts +2 -0
- package/src/lib/components/Text/types.ts +12 -0
- package/src/lib/components/Title/Title.svelte +54 -0
- package/src/lib/components/Title/index.ts +2 -0
- package/src/lib/components/Title/types.ts +9 -0
- package/src/lib/components/Toast/Toast.svelte +155 -0
- package/src/lib/components/Toast/index.ts +5 -0
- package/src/lib/components/Toast/toastCookie.ts +24 -0
- package/src/lib/components/Toast/types.ts +6 -0
- package/src/lib/components/ToolTip/ToolTip.svelte +70 -0
- package/src/lib/components/ToolTip/index.ts +2 -0
- package/src/lib/components/ToolTip/types.ts +14 -0
- package/src/lib/components/index.ts +32 -0
- package/src/lib/components/types.ts +0 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/styles/globals.css +108 -0
- package/src/lib/styles/normalize.css +9 -0
- package/src/lib/styles/reset.css +133 -0
- package/src/lib/styles/utilities.css +179 -0
- package/src/lib/styles/vars.css +1103 -0
- package/src/lib/types/awareness.ts +17 -0
- package/src/lib/utils/rle.ts +217 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { getContext, onDestroy } from 'svelte';
|
|
4
|
+
import { T, type Props as ThrelteProps } from '@threlte/core';
|
|
5
|
+
import { ToolType } from '../DrawingLayer/types';
|
|
6
|
+
import { type FogOfWarLayerProps } from './types';
|
|
7
|
+
import type { Size } from '../../types';
|
|
8
|
+
import type { Callbacks } from '../Stage/types';
|
|
9
|
+
import LayerInput from '../LayerInput/LayerInput.svelte';
|
|
10
|
+
import toolOutlineVertexShader from '../../shaders/default.vert?raw';
|
|
11
|
+
import toolOutlineFragmentShader from '../../shaders/ToolOutline.frag?raw';
|
|
12
|
+
import { SceneLayer } from '../Scene/types';
|
|
13
|
+
import FogOfWarMaterial from './FogOfWarMaterial.svelte';
|
|
14
|
+
|
|
15
|
+
interface Props extends ThrelteProps<typeof THREE.Mesh> {
|
|
16
|
+
props: FogOfWarLayerProps;
|
|
17
|
+
isActive: boolean;
|
|
18
|
+
mapSize: Size | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { props, isActive, mapSize, ...meshProps }: Props = $props();
|
|
22
|
+
|
|
23
|
+
const onFogUpdate = getContext<Callbacks>('callbacks').onFogUpdate;
|
|
24
|
+
|
|
25
|
+
// Convert percentage-based tool.size to texture pixels for outline
|
|
26
|
+
// This must match the conversion in FogOfWarMaterial
|
|
27
|
+
const toolSizePixels = $derived.by(() => {
|
|
28
|
+
if (!mapSize) return props.tool.size;
|
|
29
|
+
const textureSize = Math.min(mapSize.width, mapSize.height);
|
|
30
|
+
return Math.round(textureSize * (props.tool.size / 100));
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
let mesh: THREE.Mesh = $state(new THREE.Mesh());
|
|
34
|
+
let outlineMesh: THREE.Mesh = $state(new THREE.Mesh());
|
|
35
|
+
let material: FogOfWarMaterial | undefined = $state();
|
|
36
|
+
let drawing = false;
|
|
37
|
+
let hasFinishedDrawing = false;
|
|
38
|
+
|
|
39
|
+
// Export drawing state so parent can check it
|
|
40
|
+
export function isDrawing() {
|
|
41
|
+
return drawing;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// If mouse leaves the drawing area, we need to reset the start position
|
|
45
|
+
// when it re-enters the drawing area to prevent the drawing from "jumping"
|
|
46
|
+
// to the new point
|
|
47
|
+
let lastPos: THREE.Vector2 | null = null;
|
|
48
|
+
|
|
49
|
+
// Add outline material
|
|
50
|
+
// Initial value will be updated by $effect below
|
|
51
|
+
const outlineMaterial = new THREE.ShaderMaterial({
|
|
52
|
+
uniforms: {
|
|
53
|
+
uStart: { value: new THREE.Vector2(Infinity, Infinity) },
|
|
54
|
+
uEnd: { value: new THREE.Vector2(Infinity, Infinity) },
|
|
55
|
+
uBrushSize: { value: props.tool.size }, // Will be updated to pixels in $effect
|
|
56
|
+
uTextureSize: { value: new THREE.Vector2(0, 0) },
|
|
57
|
+
uShapeType: { value: props.tool.type },
|
|
58
|
+
uOutlineColor: { value: new THREE.Color(props.outline.color) },
|
|
59
|
+
uOutlineOpacity: { value: props.outline.opacity },
|
|
60
|
+
uOutlineThickness: { value: props.outline.thickness }
|
|
61
|
+
},
|
|
62
|
+
vertexShader: toolOutlineVertexShader,
|
|
63
|
+
fragmentShader: toolOutlineFragmentShader,
|
|
64
|
+
transparent: true,
|
|
65
|
+
depthTest: false
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
onDestroy(() => {
|
|
69
|
+
outlineMaterial.dispose();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Whenever the tool becomes inactive, reset the drawing state and hide outline
|
|
73
|
+
$effect(() => {
|
|
74
|
+
if (!isActive) {
|
|
75
|
+
lastPos = null;
|
|
76
|
+
drawing = false;
|
|
77
|
+
material?.revertChanges();
|
|
78
|
+
outlineMesh.visible = false;
|
|
79
|
+
// Reset cursor position so it doesn't appear at old location when reactivated
|
|
80
|
+
outlineMaterial.uniforms.uStart.value.set(Infinity, Infinity);
|
|
81
|
+
outlineMaterial.uniforms.uEnd.value.set(Infinity, Infinity);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Update outline material uniforms (but don't control visibility here - let draw() handle it)
|
|
86
|
+
$effect(() => {
|
|
87
|
+
if (!mapSize) return;
|
|
88
|
+
|
|
89
|
+
// Use .set() to avoid allocating new objects
|
|
90
|
+
outlineMaterial.uniforms.uTextureSize.value.set(mapSize.width, mapSize.height);
|
|
91
|
+
outlineMaterial.uniforms.uOutlineColor.value.set(props.outline.color);
|
|
92
|
+
outlineMaterial.uniforms.uOutlineThickness.value = props.outline.thickness;
|
|
93
|
+
outlineMaterial.uniforms.uOutlineOpacity.value = props.outline.opacity;
|
|
94
|
+
outlineMaterial.uniforms.uShapeType.value = props.tool.type;
|
|
95
|
+
outlineMaterial.uniforms.uBrushSize.value = toolSizePixels;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
function onMouseDown(e: Event, p: THREE.Vector2 | null) {
|
|
99
|
+
e.preventDefault();
|
|
100
|
+
lastPos = p;
|
|
101
|
+
drawing = true;
|
|
102
|
+
hasFinishedDrawing = false;
|
|
103
|
+
|
|
104
|
+
draw(e, p);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function onMouseUp(_e: Event, p: THREE.Vector2 | null) {
|
|
108
|
+
// If using shapes, draw the shape outline when the mouse button is released
|
|
109
|
+
if (props.tool.type === ToolType.Ellipse || props.tool.type === ToolType.Rectangle) {
|
|
110
|
+
if (p && drawing && lastPos) {
|
|
111
|
+
material?.drawPath(p, lastPos, true);
|
|
112
|
+
outlineMesh.visible = false;
|
|
113
|
+
hasFinishedDrawing = true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (hasFinishedDrawing) {
|
|
118
|
+
onFogUpdate(toPng());
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Reset the drawing state
|
|
122
|
+
lastPos = null;
|
|
123
|
+
drawing = false;
|
|
124
|
+
hasFinishedDrawing = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function onMouseLeave() {
|
|
128
|
+
lastPos = null;
|
|
129
|
+
drawing = false;
|
|
130
|
+
outlineMesh.visible = false;
|
|
131
|
+
material?.revertChanges();
|
|
132
|
+
|
|
133
|
+
// Hide cursor when mouse leaves
|
|
134
|
+
outlineMaterial.uniforms.uStart.value.set(Infinity, Infinity);
|
|
135
|
+
outlineMaterial.uniforms.uEnd.value.set(Infinity, Infinity);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function draw(e: Event, p: THREE.Vector2 | null) {
|
|
139
|
+
// If the mouse is not within the drawing area, do nothing
|
|
140
|
+
if (!p) {
|
|
141
|
+
// Move cursor off-screen when mouse is outside
|
|
142
|
+
outlineMaterial.uniforms.uStart.value.set(Infinity, Infinity);
|
|
143
|
+
outlineMaterial.uniforms.uEnd.value.set(Infinity, Infinity);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (props.tool.type === ToolType.Ellipse || props.tool.type === ToolType.Rectangle) {
|
|
148
|
+
// Shapes don't use lazy brush
|
|
149
|
+
outlineMaterial.uniforms.uStart.value.copy(p);
|
|
150
|
+
outlineMaterial.uniforms.uEnd.value.copy(lastPos ?? p);
|
|
151
|
+
|
|
152
|
+
// When using shapes, draw the shape outline while the mouse button is held down
|
|
153
|
+
if (drawing) {
|
|
154
|
+
outlineMesh.visible = true;
|
|
155
|
+
material?.drawPath(p, lastPos);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// For freehand tools, always show the cursor
|
|
159
|
+
outlineMesh.visible = true;
|
|
160
|
+
|
|
161
|
+
// For freehand drawing
|
|
162
|
+
if (drawing) {
|
|
163
|
+
if (!lastPos) {
|
|
164
|
+
lastPos = p.clone();
|
|
165
|
+
}
|
|
166
|
+
material?.drawPath(p, lastPos, true);
|
|
167
|
+
hasFinishedDrawing = true;
|
|
168
|
+
lastPos = p.clone();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Always show cursor at current position
|
|
172
|
+
outlineMaterial.uniforms.uStart.value.copy(p);
|
|
173
|
+
outlineMaterial.uniforms.uEnd.value.copy(p);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Clears all fog, revealing the entire map underneath
|
|
179
|
+
*/
|
|
180
|
+
export function clearFog() {
|
|
181
|
+
material?.clear();
|
|
182
|
+
onFogUpdate(toPng());
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Resets the fog to fill the entire layer
|
|
187
|
+
*/
|
|
188
|
+
export function resetFog() {
|
|
189
|
+
material?.fill();
|
|
190
|
+
onFogUpdate(toPng());
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Serializes the fog of war image data into a binary buffer
|
|
195
|
+
* @return A binary buffer
|
|
196
|
+
*/
|
|
197
|
+
export async function toPng(): Promise<Blob> {
|
|
198
|
+
return (await material?.toPng()) ?? new Blob();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Exports the fog of war state as RLE-encoded data
|
|
203
|
+
* @returns RLE encoded Uint8Array
|
|
204
|
+
*/
|
|
205
|
+
export async function toRLE(): Promise<Uint8Array> {
|
|
206
|
+
return (await material?.toRLE()) ?? new Uint8Array();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Loads RLE-encoded data into the fog of war
|
|
211
|
+
* @param rleData RLE encoded data
|
|
212
|
+
* @param width Image width
|
|
213
|
+
* @param height Image height
|
|
214
|
+
*/
|
|
215
|
+
export async function fromRLE(rleData: Uint8Array, width: number, height: number) {
|
|
216
|
+
return material?.fromRLE(rleData, width, height);
|
|
217
|
+
}
|
|
218
|
+
</script>
|
|
219
|
+
|
|
220
|
+
<LayerInput
|
|
221
|
+
id="fogOfWar"
|
|
222
|
+
{isActive}
|
|
223
|
+
layerSize={mapSize}
|
|
224
|
+
target={mesh}
|
|
225
|
+
{onMouseDown}
|
|
226
|
+
onMouseMove={draw}
|
|
227
|
+
{onMouseUp}
|
|
228
|
+
{onMouseLeave}
|
|
229
|
+
/>
|
|
230
|
+
|
|
231
|
+
<!--
|
|
232
|
+
Invisible mesh used for input detection.
|
|
233
|
+
The plane geometry is larger than the map size to allow cursor
|
|
234
|
+
events to be detected outside of the fog of war layer.
|
|
235
|
+
-->
|
|
236
|
+
<T.Mesh bind:ref={mesh} name="fogOfWarInput" layer={SceneLayer.Input}>
|
|
237
|
+
<T.MeshBasicMaterial visible={false} />
|
|
238
|
+
<T.PlaneGeometry args={[10, 10]} />
|
|
239
|
+
</T.Mesh>
|
|
240
|
+
|
|
241
|
+
<T.Mesh bind:ref={outlineMesh} name="fogOfWarToolOutline" layers={[SceneLayer.Overlay]}>
|
|
242
|
+
<T is={outlineMaterial} transparent={true} opacity={0.0} depthTest={false} />
|
|
243
|
+
<T.PlaneGeometry />
|
|
244
|
+
</T.Mesh>
|
|
245
|
+
|
|
246
|
+
<T.Mesh name="fogOfWar" {...meshProps} layers={[SceneLayer.Main]}>
|
|
247
|
+
<FogOfWarMaterial bind:this={material} {props} {mapSize} />
|
|
248
|
+
<T.PlaneGeometry />
|
|
249
|
+
</T.Mesh>
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { T, useTask } from '@threlte/core';
|
|
4
|
+
import { getContext, onDestroy } from 'svelte';
|
|
5
|
+
import DrawingMaterial from '../DrawingLayer/DrawingMaterial.svelte';
|
|
6
|
+
import { type FogOfWarLayerProps } from './types';
|
|
7
|
+
import type { Size } from '../../types';
|
|
8
|
+
import { clippingPlaneStore } from '../../helpers/clippingPlaneStore.svelte';
|
|
9
|
+
import { InitialState } from '../DrawingLayer/types';
|
|
10
|
+
import { StageMode } from '../Stage/types';
|
|
11
|
+
import fogVertexShader from '../../shaders/default.vert?raw';
|
|
12
|
+
import fogFragmentShader from '../../shaders/Fog.frag?raw';
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
props: FogOfWarLayerProps;
|
|
16
|
+
mapSize: Size | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { props, mapSize }: Props = $props();
|
|
20
|
+
|
|
21
|
+
const stage = getContext<{ mode: StageMode }>('stage');
|
|
22
|
+
let drawMaterial: DrawingMaterial;
|
|
23
|
+
|
|
24
|
+
// Convert percentage-based tool.size to texture pixels
|
|
25
|
+
// tool.size is a percentage (5-20), mapSize gives texture dimensions
|
|
26
|
+
const toolSizePixels = $derived.by(() => {
|
|
27
|
+
if (!mapSize) return props.tool.size;
|
|
28
|
+
const textureSize = Math.min(mapSize.width, mapSize.height);
|
|
29
|
+
return Math.round(textureSize * (props.tool.size / 100));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Create derived props with converted tool size
|
|
33
|
+
const drawingProps = $derived({
|
|
34
|
+
...props,
|
|
35
|
+
tool: {
|
|
36
|
+
...props.tool,
|
|
37
|
+
size: toolSizePixels
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Material used for rendering the fog of war
|
|
42
|
+
let fogMaterial = new THREE.ShaderMaterial({
|
|
43
|
+
uniforms: {
|
|
44
|
+
uMaskTexture: { value: null },
|
|
45
|
+
uTime: { value: 0.0 },
|
|
46
|
+
uBaseColor: { value: new THREE.Color(props.noise.baseColor) },
|
|
47
|
+
uFogColor1: { value: new THREE.Color(props.noise.fogColor1) },
|
|
48
|
+
uFogColor2: { value: new THREE.Color(props.noise.fogColor2) },
|
|
49
|
+
uFogColor3: { value: new THREE.Color(props.noise.fogColor3) },
|
|
50
|
+
uFogColor4: { value: new THREE.Color(props.noise.fogColor4) },
|
|
51
|
+
uFogSpeed: { value: props.noise.speed },
|
|
52
|
+
uEdgeMinMipMapLevel: { value: props.edge.minMipMapLevel },
|
|
53
|
+
uEdgeMaxMipMapLevel: { value: props.edge.maxMipMapLevel },
|
|
54
|
+
uEdgeFrequency: { value: props.edge.frequency },
|
|
55
|
+
uEdgeAmplitude: { value: props.edge.amplitude },
|
|
56
|
+
uEdgeOffset: { value: props.edge.offset },
|
|
57
|
+
uEdgeSpeed: { value: props.edge.speed },
|
|
58
|
+
uPersistence: { value: props.noise.persistence },
|
|
59
|
+
uLacunarity: { value: props.noise.lacunarity },
|
|
60
|
+
uFrequency: { value: props.noise.frequency },
|
|
61
|
+
uOffset: { value: props.noise.offset },
|
|
62
|
+
uAmplitude: { value: props.noise.amplitude },
|
|
63
|
+
uLevels: { value: props.noise.levels },
|
|
64
|
+
uOpacity: { value: stage.mode === StageMode.DM ? props.opacity.dm : props.opacity.player },
|
|
65
|
+
uClippingPlanes: new THREE.Uniform(
|
|
66
|
+
clippingPlaneStore.value.map((p) => new THREE.Vector4(p.normal.x, p.normal.y, p.normal.z, p.constant))
|
|
67
|
+
)
|
|
68
|
+
},
|
|
69
|
+
transparent: true,
|
|
70
|
+
fragmentShader: fogFragmentShader,
|
|
71
|
+
vertexShader: fogVertexShader
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Track opacity separately to ensure it updates properly
|
|
75
|
+
let currentOpacity = $derived(stage.mode === StageMode.DM ? props.opacity.dm : props.opacity.player);
|
|
76
|
+
|
|
77
|
+
// Update opacity when it changes
|
|
78
|
+
$effect(() => {
|
|
79
|
+
fogMaterial.uniforms.uOpacity.value = currentOpacity;
|
|
80
|
+
fogMaterial.uniformsNeedUpdate = true;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Whenever the fog of war props change, we need to update the material
|
|
84
|
+
$effect(() => {
|
|
85
|
+
// Use .set() to avoid allocating new Color objects
|
|
86
|
+
fogMaterial.uniforms.uBaseColor.value.set(props.noise.baseColor);
|
|
87
|
+
fogMaterial.uniforms.uFogColor1.value.set(props.noise.fogColor1);
|
|
88
|
+
fogMaterial.uniforms.uFogColor2.value.set(props.noise.fogColor2);
|
|
89
|
+
fogMaterial.uniforms.uFogColor3.value.set(props.noise.fogColor3);
|
|
90
|
+
fogMaterial.uniforms.uFogColor4.value.set(props.noise.fogColor4);
|
|
91
|
+
|
|
92
|
+
fogMaterial.uniforms.uEdgeMinMipMapLevel.value = props.edge.minMipMapLevel;
|
|
93
|
+
fogMaterial.uniforms.uEdgeMaxMipMapLevel.value = props.edge.maxMipMapLevel;
|
|
94
|
+
fogMaterial.uniforms.uEdgeFrequency.value = props.edge.frequency;
|
|
95
|
+
fogMaterial.uniforms.uEdgeAmplitude.value = props.edge.amplitude;
|
|
96
|
+
fogMaterial.uniforms.uEdgeOffset.value = props.edge.offset;
|
|
97
|
+
fogMaterial.uniforms.uEdgeSpeed.value = props.edge.speed;
|
|
98
|
+
fogMaterial.uniforms.uFogSpeed.value = props.noise.speed;
|
|
99
|
+
fogMaterial.uniforms.uFrequency.value = props.noise.frequency;
|
|
100
|
+
fogMaterial.uniforms.uPersistence.value = props.noise.persistence;
|
|
101
|
+
fogMaterial.uniforms.uLacunarity.value = props.noise.lacunarity;
|
|
102
|
+
fogMaterial.uniforms.uLevels.value = props.noise.levels;
|
|
103
|
+
fogMaterial.uniforms.uOffset.value = props.noise.offset;
|
|
104
|
+
fogMaterial.uniforms.uAmplitude.value = props.noise.amplitude;
|
|
105
|
+
|
|
106
|
+
// Update clipping planes in place
|
|
107
|
+
const planes = clippingPlaneStore.value;
|
|
108
|
+
for (let i = 0; i < planes.length; i++) {
|
|
109
|
+
const p = planes[i];
|
|
110
|
+
fogMaterial.uniforms.uClippingPlanes.value[i].set(p.normal.x, p.normal.y, p.normal.z, p.constant);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Force shader to update with new uniform values
|
|
114
|
+
fogMaterial.uniformsNeedUpdate = true;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
useTask((delta) => {
|
|
118
|
+
fogMaterial.uniforms.uTime.value += delta;
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reverts the changes made to the fog of war
|
|
123
|
+
*/
|
|
124
|
+
export function revertChanges() {
|
|
125
|
+
drawMaterial.revert();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Clears the fog of war
|
|
130
|
+
*/
|
|
131
|
+
export function clear() {
|
|
132
|
+
drawMaterial.clear();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Fills the fog of war
|
|
137
|
+
*/
|
|
138
|
+
export function fill() {
|
|
139
|
+
drawMaterial.fill();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Draws a path on the fog of war
|
|
144
|
+
* @param start The start position of the path
|
|
145
|
+
* @param last The last position of the path
|
|
146
|
+
* @param persist Whether to persist the current state
|
|
147
|
+
*/
|
|
148
|
+
export function drawPath(start: THREE.Vector2, last: THREE.Vector2 | null = null, persist: boolean = false) {
|
|
149
|
+
drawMaterial.drawPath(start, last, persist);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Serializes the current fog of war state to a binary buffer
|
|
154
|
+
* @returns A binary buffer representation of the fog of war textuare
|
|
155
|
+
*/
|
|
156
|
+
export async function toPng(): Promise<Blob> {
|
|
157
|
+
return drawMaterial.toPng();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Exports the fog of war state as RLE-encoded data
|
|
162
|
+
* @returns RLE encoded Uint8Array
|
|
163
|
+
*/
|
|
164
|
+
export async function toRLE(): Promise<Uint8Array> {
|
|
165
|
+
return drawMaterial.toRLE();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Loads RLE-encoded data into the fog of war
|
|
170
|
+
* @param rleData RLE encoded data
|
|
171
|
+
* @param width Image width
|
|
172
|
+
* @param height Image height
|
|
173
|
+
*/
|
|
174
|
+
export async function fromRLE(rleData: Uint8Array, width: number, height: number) {
|
|
175
|
+
return drawMaterial.fromRLE(rleData, width, height);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
onDestroy(() => {
|
|
179
|
+
fogMaterial.dispose();
|
|
180
|
+
});
|
|
181
|
+
</script>
|
|
182
|
+
|
|
183
|
+
<DrawingMaterial
|
|
184
|
+
bind:this={drawMaterial}
|
|
185
|
+
props={drawingProps}
|
|
186
|
+
size={mapSize}
|
|
187
|
+
initialState={InitialState.Fill}
|
|
188
|
+
onRender={(texture) => {
|
|
189
|
+
fogMaterial.uniforms.uMaskTexture.value = texture;
|
|
190
|
+
fogMaterial.uniformsNeedUpdate = true;
|
|
191
|
+
}}
|
|
192
|
+
/>
|
|
193
|
+
|
|
194
|
+
{#snippet attachMaterial()}
|
|
195
|
+
{fogMaterial}
|
|
196
|
+
{/snippet}
|
|
197
|
+
|
|
198
|
+
<T is={fogMaterial}>
|
|
199
|
+
{@render attachMaterial()}
|
|
200
|
+
</T>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { DrawingLayerProps } from '../DrawingLayer/types';
|
|
2
|
+
|
|
3
|
+
export interface FogOfWarLayerProps extends DrawingLayerProps {
|
|
4
|
+
/**
|
|
5
|
+
* The outline settings
|
|
6
|
+
*/
|
|
7
|
+
outline: {
|
|
8
|
+
/**
|
|
9
|
+
* The color of the outline
|
|
10
|
+
*/
|
|
11
|
+
color: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The opacity of the outline
|
|
15
|
+
*/
|
|
16
|
+
opacity: number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The thickness of the outline
|
|
20
|
+
*/
|
|
21
|
+
thickness: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The edge settings
|
|
26
|
+
*/
|
|
27
|
+
edge: {
|
|
28
|
+
/**
|
|
29
|
+
* The minimum mip map level to use for the edge mask
|
|
30
|
+
*/
|
|
31
|
+
minMipMapLevel: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The maximum mip map level to use for the edge mask
|
|
35
|
+
*/
|
|
36
|
+
maxMipMapLevel: number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The frequency of the noise added to the mask edge
|
|
40
|
+
*/
|
|
41
|
+
frequency: { x: number; y: number; z: number; w: number };
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The amplitude of the noise added to the mask edge
|
|
45
|
+
*/
|
|
46
|
+
amplitude: { x: number; y: number; z: number; w: number };
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The offset of the noise added to the mask edge
|
|
50
|
+
*/
|
|
51
|
+
offset: number;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The speed of the noise added to the mask edge
|
|
55
|
+
*/
|
|
56
|
+
speed: number;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The noise settings
|
|
61
|
+
*/
|
|
62
|
+
noise: {
|
|
63
|
+
/**
|
|
64
|
+
* Color of the fog
|
|
65
|
+
*/
|
|
66
|
+
baseColor: string;
|
|
67
|
+
fogColor1: string;
|
|
68
|
+
fogColor2: string;
|
|
69
|
+
fogColor3: string;
|
|
70
|
+
fogColor4: string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Controls the speed of the fog
|
|
74
|
+
*/
|
|
75
|
+
speed: { x: number; y: number; z: number; w: number };
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Controls the frequency of the fog
|
|
79
|
+
*/
|
|
80
|
+
frequency: { x: number; y: number; z: number; w: number };
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Controls the persistence of the fog
|
|
84
|
+
*/
|
|
85
|
+
persistence: { x: number; y: number; z: number; w: number };
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Controls the lacunarity of the fog
|
|
89
|
+
*/
|
|
90
|
+
lacunarity: { x: number; y: number; z: number; w: number };
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Controls the levels of the fog
|
|
94
|
+
*/
|
|
95
|
+
levels: { x: number; y: number; z: number; w: number };
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Controls the offset of the fog
|
|
99
|
+
*/
|
|
100
|
+
offset: { x: number; y: number; z: number; w: number };
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Controls the amplitude of the fog
|
|
104
|
+
*/
|
|
105
|
+
amplitude: { x: number; y: number; z: number; w: number };
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface FogOfWarExports {
|
|
110
|
+
clearFog: () => void;
|
|
111
|
+
resetFog: () => void;
|
|
112
|
+
toPng: () => Promise<Blob>;
|
|
113
|
+
toRLE: () => Promise<Uint8Array>;
|
|
114
|
+
fromRLE: (rleData: Uint8Array, width: number, height: number) => Promise<void>;
|
|
115
|
+
isDrawing: () => boolean;
|
|
116
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { T, type Props as ThrelteProps } from '@threlte/core';
|
|
4
|
+
import { type GridLayerProps } from './types';
|
|
5
|
+
import { type DisplayProps } from '../Stage/types';
|
|
6
|
+
import GridMaterial from './GridMaterial.svelte';
|
|
7
|
+
|
|
8
|
+
interface Props extends ThrelteProps<typeof THREE.Mesh> {
|
|
9
|
+
grid: GridLayerProps;
|
|
10
|
+
display: DisplayProps;
|
|
11
|
+
sceneZoom: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { grid, display, sceneZoom, ...meshProps }: Props = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<T.Mesh name="gridLayer" scale={[display.resolution.x, display.resolution.y, 1]} {...meshProps}>
|
|
18
|
+
<GridMaterial {grid} {display} {sceneZoom} />
|
|
19
|
+
<T.PlaneGeometry />
|
|
20
|
+
</T.Mesh>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import type { GridLayerProps } from './types';
|
|
4
|
+
import type { DisplayProps } from '../Stage/types';
|
|
5
|
+
import fragmentShader from '../../shaders/GridShader.frag?raw';
|
|
6
|
+
import vertexShader from '../../shaders/default.vert?raw';
|
|
7
|
+
import { T, useThrelte } from '@threlte/core';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
grid: GridLayerProps;
|
|
11
|
+
display: DisplayProps;
|
|
12
|
+
sceneZoom: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { invalidate } = useThrelte();
|
|
16
|
+
const { grid, display, sceneZoom }: Props = $props();
|
|
17
|
+
|
|
18
|
+
let material = new THREE.ShaderMaterial({
|
|
19
|
+
uniforms: {
|
|
20
|
+
uOpacity: new THREE.Uniform(grid.opacity),
|
|
21
|
+
uGridType: new THREE.Uniform(grid.gridType),
|
|
22
|
+
uGridMode: new THREE.Uniform(grid.gridMode || 0),
|
|
23
|
+
uSpacing_in: new THREE.Uniform(grid.spacing),
|
|
24
|
+
uPadding_px: new THREE.Uniform(display.padding),
|
|
25
|
+
uLineThickness: new THREE.Uniform(grid.lineThickness),
|
|
26
|
+
uLineColor: new THREE.Uniform(new THREE.Color(grid.lineColor)),
|
|
27
|
+
uShadowOpacity: new THREE.Uniform(grid.shadowOpacity),
|
|
28
|
+
uShadowBlur: new THREE.Uniform(grid.shadowBlur),
|
|
29
|
+
uShadowSpread: new THREE.Uniform(grid.shadowSpread),
|
|
30
|
+
uShadowColor: new THREE.Uniform(new THREE.Color(grid.shadowColor)),
|
|
31
|
+
uSceneScale: new THREE.Uniform(1),
|
|
32
|
+
uResolution_px: new THREE.Uniform(new THREE.Vector2(0, 0)),
|
|
33
|
+
uDisplaySize_in: new THREE.Uniform(new THREE.Vector2(0, 0)),
|
|
34
|
+
uFixedGridCountX: new THREE.Uniform(grid.fixedGridCount?.x || 24),
|
|
35
|
+
uFixedGridCountY: new THREE.Uniform(grid.fixedGridCount?.y || 17)
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
$effect(() => {
|
|
40
|
+
material.uniforms.uOpacity.value = grid.opacity;
|
|
41
|
+
material.uniforms.uSceneScale.value = sceneZoom;
|
|
42
|
+
material.uniforms.uGridType.value = grid.gridType;
|
|
43
|
+
material.uniforms.uGridMode.value = grid.gridMode || 0;
|
|
44
|
+
material.uniforms.uSpacing_in.value = grid.spacing;
|
|
45
|
+
material.uniforms.uPadding_px.value = display.padding;
|
|
46
|
+
material.uniforms.uLineThickness.value = grid.lineThickness;
|
|
47
|
+
// Use .set() to avoid allocating new objects
|
|
48
|
+
material.uniforms.uLineColor.value.set(grid.lineColor);
|
|
49
|
+
material.uniforms.uShadowOpacity.value = grid.shadowOpacity;
|
|
50
|
+
material.uniforms.uShadowBlur.value = grid.shadowBlur;
|
|
51
|
+
material.uniforms.uShadowSpread.value = grid.shadowSpread;
|
|
52
|
+
material.uniforms.uShadowColor.value.set(grid.shadowColor);
|
|
53
|
+
material.uniforms.uResolution_px.value.set(display.resolution.x, display.resolution.y);
|
|
54
|
+
material.uniforms.uDisplaySize_in.value.set(display.size.x, display.size.y);
|
|
55
|
+
material.uniforms.uFixedGridCountX.value = grid.fixedGridCount?.x || 24;
|
|
56
|
+
material.uniforms.uFixedGridCountY.value = grid.fixedGridCount?.y || 17;
|
|
57
|
+
|
|
58
|
+
invalidate();
|
|
59
|
+
});
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
{#snippet attachMaterial()}
|
|
63
|
+
{material}
|
|
64
|
+
{/snippet}
|
|
65
|
+
|
|
66
|
+
<!-- Export the material to be used in the parent component -->
|
|
67
|
+
<T is={material} {fragmentShader} {vertexShader} transparent={true} depthTest={false}>
|
|
68
|
+
{@render attachMaterial()}
|
|
69
|
+
</T>
|