@woosh/meep-engine 2.165.7 → 2.167.0
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/build/bundle-worker-image-decoder.js +1 -1
- package/package.json +1 -1
- package/src/CORRECTNESS_HUNT_2026_07_24.md +142 -0
- package/src/core/binary/BinaryBuffer.js +1 -1
- package/src/core/binary/EncodingBinaryBuffer.d.ts.map +1 -1
- package/src/core/binary/EncodingBinaryBuffer.js +3 -1
- package/src/core/cache/Cache.d.ts.map +1 -1
- package/src/core/cache/Cache.js +0 -4
- package/src/core/cache/CacheElement.d.ts.map +1 -1
- package/src/core/cache/CacheElement.js +4 -0
- package/src/core/cache/FrequencySketch.d.ts +0 -21
- package/src/core/cache/FrequencySketch.d.ts.map +1 -1
- package/src/core/cache/FrequencySketch.js +66 -65
- package/src/core/cache/wtinylfu/CacheElementWTinylfu.d.ts +17 -0
- package/src/core/cache/wtinylfu/CacheElementWTinylfu.d.ts.map +1 -0
- package/src/core/cache/wtinylfu/CacheElementWTinylfu.js +18 -0
- package/src/core/cache/wtinylfu/CacheRegionType.d.ts +10 -0
- package/src/core/cache/wtinylfu/CacheRegionType.d.ts.map +1 -0
- package/src/core/cache/wtinylfu/CacheRegionType.js +10 -0
- package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts +66 -0
- package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts.map +1 -0
- package/src/core/cache/wtinylfu/CacheRegionWTinylfu.js +183 -0
- package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts +279 -0
- package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts.map +1 -0
- package/src/core/cache/wtinylfu/CacheWTinylfu.js +807 -0
- package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +243 -0
- package/src/core/cache/wtinylfu/wtinylfuDecisions.d.ts +80 -0
- package/src/core/cache/wtinylfu/wtinylfuDecisions.d.ts.map +1 -0
- package/src/core/cache/wtinylfu/wtinylfuDecisions.js +102 -0
- package/src/core/collection/RingBuffer.d.ts.map +1 -1
- package/src/core/collection/RingBuffer.js +15 -3
- package/src/core/collection/map/HashMap.d.ts +1 -1
- package/src/core/collection/map/HashMap.d.ts.map +1 -1
- package/src/core/collection/map/HashMap.js +5 -17
- package/src/core/geom/2d/line/line2_compute_segment_point_distance_sqr.d.ts.map +1 -1
- package/src/core/geom/2d/line/line2_compute_segment_point_distance_sqr.js +5 -0
- package/src/core/geom/ConicRay.d.ts.map +1 -1
- package/src/core/geom/ConicRay.js +9 -2
- package/src/core/geom/Quaternion.d.ts.map +1 -1
- package/src/core/geom/Quaternion.js +7 -3
- package/src/core/math/build_gaussian_kernel_1d.d.ts +2 -2
- package/src/core/math/build_gaussian_kernel_1d.d.ts.map +1 -1
- package/src/core/math/build_gaussian_kernel_1d.js +4 -2
- package/src/core/math/build_gaussian_kernel_2d.d.ts +2 -2
- package/src/core/math/build_gaussian_kernel_2d.d.ts.map +1 -1
- package/src/core/math/build_gaussian_kernel_2d.js +4 -2
- package/src/core/math/gaussian.d.ts +2 -2
- package/src/core/math/gaussian.js +2 -2
- package/src/core/math/spline/spline3_bezier_bounds.d.ts.map +1 -1
- package/src/core/math/spline/spline3_bezier_bounds.js +10 -3
- package/src/core/math/spline/spline3_bezier_to_hermite.d.ts +8 -7
- package/src/core/math/spline/spline3_bezier_to_hermite.d.ts.map +1 -1
- package/src/core/math/spline/spline3_bezier_to_hermite.js +13 -12
- package/src/core/math/spline/spline3_hermite_bounds.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_bounds.js +10 -3
- package/src/core/math/spline/spline3_hermite_bounds_t.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_bounds_t.js +115 -109
- package/src/core/math/spline/spline3_hermite_to_bezier.d.ts +2 -0
- package/src/core/math/spline/spline3_hermite_to_bezier.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_to_bezier.js +2 -0
- package/src/core/math/statistics/computeStatisticalMean.js +1 -1
- package/src/core/math/statistics/gaussian_amplitude.d.ts.map +1 -1
- package/src/core/math/statistics/gaussian_amplitude.js +3 -1
- package/src/engine/animation/clip/ecd_bind_animation_curve.d.ts.map +1 -1
- package/src/engine/animation/clip/ecd_bind_animation_curve.js +10 -1
- package/src/engine/animation/clip/hemisphere_align_quaternion_values.d.ts +20 -0
- package/src/engine/animation/clip/hemisphere_align_quaternion_values.d.ts.map +1 -0
- package/src/engine/animation/clip/hemisphere_align_quaternion_values.js +37 -0
- package/src/engine/animation/keyed2/AnimationTrackPlayback.d.ts.map +1 -1
- package/src/engine/animation/keyed2/AnimationTrackPlayback.js +5 -1
- package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
- package/src/engine/ecs/EntityComponentDataset.js +5 -21
- package/src/engine/ecs/fow/FogOfWar.d.ts +22 -0
- package/src/engine/ecs/fow/FogOfWar.d.ts.map +1 -1
- package/src/engine/ecs/fow/FogOfWar.js +202 -54
- package/src/engine/ecs/fow/FogOfWarEdgeMode.d.ts +16 -0
- package/src/engine/ecs/fow/FogOfWarEdgeMode.d.ts.map +1 -0
- package/src/engine/ecs/fow/FogOfWarEdgeMode.js +39 -0
- package/src/engine/ecs/fow/FogOfWarSystem.d.ts.map +1 -1
- package/src/engine/ecs/fow/FogOfWarSystem.js +1 -0
- package/src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.d.ts.map +1 -1
- package/src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js +3 -0
- package/src/engine/ecs/fow/shader/FogOfWarRenderer.d.ts +7 -0
- package/src/engine/ecs/fow/shader/FogOfWarRenderer.d.ts.map +1 -1
- package/src/engine/ecs/fow/shader/FogOfWarRenderer.js +155 -145
- package/src/engine/ecs/fow/shader/screenSpaceFogOfWarShader.d.ts.map +1 -1
- package/src/engine/ecs/fow/shader/screenSpaceFogOfWarShader.js +33 -8
- package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts.map +1 -1
- package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js +3 -1
- package/src/engine/graphics/GraphicsEngine.d.ts +5 -1
- package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
- package/src/engine/graphics/GraphicsEngine.js +14 -3
- package/src/engine/graphics/composit/CompositLayer.d.ts.map +1 -1
- package/src/engine/graphics/composit/CompositLayer.js +258 -255
- package/src/engine/graphics/composit/LayerCompositer.d.ts +12 -0
- package/src/engine/graphics/composit/LayerCompositer.d.ts.map +1 -1
- package/src/engine/graphics/composit/LayerCompositer.js +19 -10
- package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.d.ts +1 -1
- package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +10 -4
- package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.d.ts +6 -0
- package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.d.ts.map +1 -1
- package/src/engine/graphics/ecs/highlight/renderer/OutlineRenderer.js +21 -0
- package/src/engine/graphics/ecs/path/ribbon/RibbonPathBuilder.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/ribbon/RibbonPathBuilder.js +5 -23
- package/src/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/tube/build/estimatePathViaIterativeIntegral.js +6 -4
- package/src/engine/graphics/ecs/water/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/WaterSystem.js +9 -3
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts +12 -0
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +46 -9
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.d.ts +5 -0
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +8 -0
- package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.d.ts +7 -0
- package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/shader/MaterialRecord.js +8 -0
- package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.d.ts +10 -2
- package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.d.ts.map +1 -1
- package/src/engine/graphics/particles/particular/engine/shader/ShaderManager.js +42 -10
- package/src/engine/graphics/render/buffer/FrameBuffer.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/FrameBuffer.js +5 -2
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts +13 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +40 -7
- package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +10 -4
- package/src/engine/graphics/render/forward_plus/LightManager.d.ts.map +1 -1
- package/src/engine/graphics/render/forward_plus/LightManager.js +1235 -1232
- package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +5 -0
- package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts.map +1 -1
- package/src/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +11 -10
- package/src/engine/graphics/trail/tube/TubeX.d.ts.map +1 -1
- package/src/engine/graphics/trail/tube/TubeX.js +557 -555
- package/src/engine/graphics/trail/x/RibbonXPlugin.d.ts +12 -1
- package/src/engine/graphics/trail/x/RibbonXPlugin.d.ts.map +1 -1
- package/src/engine/graphics/trail/x/RibbonXPlugin.js +15 -8
- package/src/engine/input/ecs/systems/InputControllerSystem.d.ts.map +1 -1
- package/src/engine/input/ecs/systems/InputControllerSystem.js +9 -6
- package/src/engine/navigation/ecs/components/Path.d.ts +5 -2
- package/src/engine/navigation/ecs/components/Path.d.ts.map +1 -1
- package/src/engine/navigation/ecs/components/Path.js +10 -4
- package/src/engine/navigation/ecs/path_following/PathFollowingSystem.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimationTrackPlayback.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/keyed2/AnimationTrackPlayback.js"],"names":[],"mappings":";AAGA;IACI;;;;;;;;OAQG;IACH,4EAuBC;IAtBG,sBAAkB;IAClB,cAA+B;IAE/B,oBAAoC;IACpC,kBAAgC;IAEhC,uBAAuB;IACvB,8BAA8B;IAE9B,uBAAuB;IACvB,sBAAsB;IAEtB,gBAAmB;IAEnB,4BAA0D;IAG1D;;MAEC;IAKL;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,gBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;OAGG;IACH,WAFW,OAAO,QAIjB;IAED,cAEC;IAED;;;OAGG;IACH,kBAFW,MAAM,QA2BhB;IAED;;;OAGG;IACH,cAFa,OAAO,CA2CnB;IAED;;;OAGG;IACH,mBAFW,MAAM,
|
|
1
|
+
{"version":3,"file":"AnimationTrackPlayback.d.ts","sourceRoot":"","sources":["../../../../../src/engine/animation/keyed2/AnimationTrackPlayback.js"],"names":[],"mappings":";AAGA;IACI;;;;;;;;OAQG;IACH,4EAuBC;IAtBG,sBAAkB;IAClB,cAA+B;IAE/B,oBAAoC;IACpC,kBAAgC;IAEhC,uBAAuB;IACvB,8BAA8B;IAE9B,uBAAuB;IACvB,sBAAsB;IAEtB,gBAAmB;IAEnB,4BAA0D;IAG1D;;MAEC;IAKL;;;OAGG;IACH,oBAEC;IAED;;;OAGG;IACH,gBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;OAGG;IACH,WAFW,OAAO,QAIjB;IAED,cAEC;IAED;;;OAGG;IACH,kBAFW,MAAM,QA2BhB;IAED;;;OAGG;IACH,cAFa,OAAO,CA2CnB;IAED;;;OAGG;IACH,mBAFW,MAAM,QAmChB;IAED,eAOC;IAED;;;OAGG;IACH,0BAFW,MAAM,EAAE,QA2ClB;CACJ;mBApPkB,uCAAuC"}
|
|
@@ -159,7 +159,11 @@ class AnimationTrackPlayback {
|
|
|
159
159
|
if (timeDelta < 0) {
|
|
160
160
|
//negative delta, going back in time
|
|
161
161
|
this.setPosition(newPosition);
|
|
162
|
-
|
|
162
|
+
// the `>= timeEnd` term catches a frame that lands EXACTLY on the end: __nextKeyTime equals
|
|
163
|
+
// timeEnd on the final segment, so the strict `> __nextKeyTime` test would skip it, and the
|
|
164
|
+
// one-shot `ended` (guarded by position < timeEnd) would then never fire. Mid-track exact
|
|
165
|
+
// landings do not reach timeEnd, so they stay on the plain else branch as before.
|
|
166
|
+
} else if (newPosition > this.__nextKeyTime || newPosition >= this.track.timeEnd) {
|
|
163
167
|
|
|
164
168
|
if (newPosition >= this.track.timeEnd) {
|
|
165
169
|
if (this.__loop) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntityComponentDataset.d.ts","sourceRoot":"","sources":["../../../../src/engine/ecs/EntityComponentDataset.js"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../core/assert.js";
|
|
2
2
|
import { BitSet } from "../../core/binary/BitSet.js";
|
|
3
3
|
import { array_set_diff } from "../../core/collection/array/array_set_diff.js";
|
|
4
|
-
import { array_shrink_to_size } from "../../core/collection/array/array_shrink_to_size.js";
|
|
5
4
|
import { findSignalHandlerIndexByHandle } from "../../core/events/signal/findSignalHandlerIndexByHandle.js";
|
|
6
5
|
import {
|
|
7
6
|
findSignalHandlerIndexByHandleAndContext
|
|
@@ -107,18 +106,6 @@ function buildObserverCallbackArgs(entityIndex, mask, componentIndexMap, compone
|
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
* @type {number[]}
|
|
113
|
-
*/
|
|
114
|
-
const scratch_indices = [];
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Used for constructing arguments prior to traversal visitor call
|
|
118
|
-
* @type {*[]}
|
|
119
|
-
*/
|
|
120
|
-
const scratch_args = [];
|
|
121
|
-
|
|
122
109
|
/**
|
|
123
110
|
* Represents a storage for entities and their associated components.
|
|
124
111
|
* Entities are just integer IDs and components are stored in a virtual table, where each component type has a separate column and each entity is a row in that table.
|
|
@@ -1327,8 +1314,10 @@ export class EntityComponentDataset {
|
|
|
1327
1314
|
|
|
1328
1315
|
let entityIndex, i;
|
|
1329
1316
|
|
|
1330
|
-
//
|
|
1331
|
-
|
|
1317
|
+
// Local arrays rather than the module-shared scratch pools: the visitor may itself call
|
|
1318
|
+
// traverseEntities (an ordinary "for each A, scan the B entities" pattern), and a shared pool
|
|
1319
|
+
// would let the inner call clobber this call's indices/args mid-scan. Matches traverseEntitiesExact.
|
|
1320
|
+
const indices = [];
|
|
1332
1321
|
|
|
1333
1322
|
// prepare sorted array of component indices
|
|
1334
1323
|
const numClasses = classes.length;
|
|
@@ -1348,12 +1337,7 @@ export class EntityComponentDataset {
|
|
|
1348
1337
|
indices[i] = componentIndex;
|
|
1349
1338
|
}
|
|
1350
1339
|
|
|
1351
|
-
const args =
|
|
1352
|
-
|
|
1353
|
-
// crop args array to the right length (since we're re-using a scratch array)
|
|
1354
|
-
const args_length_intended = numClasses + 1;
|
|
1355
|
-
|
|
1356
|
-
array_shrink_to_size(scratch_args, args_length_intended);
|
|
1340
|
+
const args = [];
|
|
1357
1341
|
|
|
1358
1342
|
const entityOccupancy = this.entityOccupancy;
|
|
1359
1343
|
|
|
@@ -28,6 +28,18 @@ export class FogOfWar {
|
|
|
28
28
|
*/
|
|
29
29
|
size: Vector2;
|
|
30
30
|
color: Vector4;
|
|
31
|
+
/**
|
|
32
|
+
* What the fog does outside the fogged area — see {@link FogOfWarEdgeMode}.
|
|
33
|
+
*
|
|
34
|
+
* NOT serialized: it is configuration the owner sets when it builds the
|
|
35
|
+
* component, not accumulated reveal state, and adding it to the binary format
|
|
36
|
+
* would cost a version bump plus an updater for every existing save. A
|
|
37
|
+
* deserialized FogOfWar therefore comes back as Conceal; a consumer that
|
|
38
|
+
* wants Extend sets it after loading, in the same place it sets {@link color}.
|
|
39
|
+
*
|
|
40
|
+
* @type {FogOfWarEdgeMode}
|
|
41
|
+
*/
|
|
42
|
+
edge_mode: FogOfWarEdgeMode;
|
|
31
43
|
/**
|
|
32
44
|
* Contains indices of pixes that are currently being updated
|
|
33
45
|
* @type {RowFirstTable}
|
|
@@ -74,6 +86,14 @@ export class FogOfWar {
|
|
|
74
86
|
* @param {number} radius
|
|
75
87
|
*/
|
|
76
88
|
conceal(x: number, y: number, radius: number): void;
|
|
89
|
+
/**
|
|
90
|
+
* Rebuild the cell -> fade row index from the current {@link fadeMask}
|
|
91
|
+
* contents. Must be invoked whenever the fade mask is populated without
|
|
92
|
+
* going through {@link reveal}/{@link conceal}/{@link revealPoint} (e.g.
|
|
93
|
+
* after deserialization), otherwise those methods could stack duplicate
|
|
94
|
+
* fade rows for a cell.
|
|
95
|
+
*/
|
|
96
|
+
rebuildFadeIndex(): void;
|
|
77
97
|
dispose(): void;
|
|
78
98
|
updateTexture(): void;
|
|
79
99
|
/**
|
|
@@ -117,6 +137,7 @@ export class FogOfWar {
|
|
|
117
137
|
* @param scale
|
|
118
138
|
*/
|
|
119
139
|
resize(w: number, h: number, scale: any): void;
|
|
140
|
+
#private;
|
|
120
141
|
}
|
|
121
142
|
export namespace FogOfWar {
|
|
122
143
|
let typeName: string;
|
|
@@ -125,6 +146,7 @@ import { DataTexture } from "three";
|
|
|
125
146
|
import Vector1 from "../../../core/geom/Vector1.js";
|
|
126
147
|
import Vector2 from "../../../core/geom/Vector2.js";
|
|
127
148
|
import Vector4 from "../../../core/geom/Vector4.js";
|
|
149
|
+
import { FogOfWarEdgeMode } from "./FogOfWarEdgeMode.js";
|
|
128
150
|
import { RowFirstTable } from "../../../core/collection/table/RowFirstTable.js";
|
|
129
151
|
import Signal from "../../../core/events/signal/Signal.js";
|
|
130
152
|
import { Sampler2D } from "../../graphics/texture/sampler/Sampler2D.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FogOfWar.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWar.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FogOfWar.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWar.js"],"names":[],"mappings":"AAgDA;;GAEG;AACH;IAEI;;;OAGG;IACH,oBAFU,OAAO,CAES;IAC1B;;;OAGG;IACH,0BAFU,OAAO,CAEgB;IAEjC;;;OAGG;IACH,SAFU,WAAW,GAAC,IAAI,CAEX;IAEf;;;OAGG;IACH,OAFU,OAAO,CAEM;IAEvB;;;OAGG;IACH,MAFU,OAAO,CAEQ;IAEzB,eAAsC;IAEtC;;;;;;;;;;OAUG;IACH,WAFU,gBAAgB,CAEW;IAErC;;;OAGG;IACH,UAFU,aAAa,CAE2B;IAWlD;;MAEE;IAEF;;;OAGG;IACH,SAFU,SAAS,CAEgB;IAEnC;;;OAGG;IACH,iBAFU,SAAS,CAEwB;IAE3C;;;OAGG;IACH,sBAFW,MAAM,QA6EhB;IA4DD;;;;OAIG;IACH,eAHW,MAAM,KACN,MAAM,QAUhB;IAED,cAQC;IAED,kBAQC;IAED,mBAEC;IAED;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,UACN,MAAM,QAmChB;IAED;;;;;OAKG;IACH,WAJW,MAAM,KACN,MAAM,UACN,MAAM,QAmChB;IAED;;;;;;OAMG;IACH,yBAcC;IAED,gBAIC;IAmDD,sBA2CC;IAED;;;OAGG;IACH,kBAFW,MAAM,QAYhB;IAED;;;OAGG;IACH,0DA+BC;IAED;;;;;OAKG;IACH,yBAJW,MAAM,KACN,MAAM,UACN,MAAM,EAAE,QAelB;IAED;;;;;OAKG;IACH,yEAFW,MAAM,WA+EhB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CASlB;IAED,6BAKC;IAED,+BASC;IAED,uBAyBC;IAGD;;;;;OAKG;IACH,UAJW,MAAM,KACN,MAAM,oBAahB;;CACJ;;;;4BA5uB2F,OAAO;oBAM/E,+BAA+B;oBAC/B,+BAA+B;oBAC/B,+BAA+B;iCAOlB,uBAAuB;8BAZ1B,iDAAiD;mBAE5D,uCAAuC;0BAQhC,6CAA6C"}
|
|
@@ -13,6 +13,7 @@ import { min2 } from "../../../core/math/min2.js";
|
|
|
13
13
|
import { computeUnsignedDistanceField } from "../../graphics/texture/sampler/distance/computeUnsignedDistanceField.js";
|
|
14
14
|
import { Sampler2D } from "../../graphics/texture/sampler/Sampler2D.js";
|
|
15
15
|
import { writeSample2DDataToDataTexture } from "../../graphics/texture/sampler/writeSampler2DDataToDataTexture.js";
|
|
16
|
+
import { FogOfWarEdgeMode } from "./FogOfWarEdgeMode.js";
|
|
16
17
|
|
|
17
18
|
const samplePosition = [];
|
|
18
19
|
|
|
@@ -81,12 +82,34 @@ export class FogOfWar {
|
|
|
81
82
|
|
|
82
83
|
color = new Vector4(0.1, 0.1, 0.1, 1);
|
|
83
84
|
|
|
85
|
+
/**
|
|
86
|
+
* What the fog does outside the fogged area — see {@link FogOfWarEdgeMode}.
|
|
87
|
+
*
|
|
88
|
+
* NOT serialized: it is configuration the owner sets when it builds the
|
|
89
|
+
* component, not accumulated reveal state, and adding it to the binary format
|
|
90
|
+
* would cost a version bump plus an updater for every existing save. A
|
|
91
|
+
* deserialized FogOfWar therefore comes back as Conceal; a consumer that
|
|
92
|
+
* wants Extend sets it after loading, in the same place it sets {@link color}.
|
|
93
|
+
*
|
|
94
|
+
* @type {FogOfWarEdgeMode}
|
|
95
|
+
*/
|
|
96
|
+
edge_mode = FogOfWarEdgeMode.Conceal;
|
|
97
|
+
|
|
84
98
|
/**
|
|
85
99
|
* Contains indices of pixes that are currently being updated
|
|
86
100
|
* @type {RowFirstTable}
|
|
87
101
|
*/
|
|
88
102
|
fadeMask = new RowFirstTable(revealMaskTableSpec);
|
|
89
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Maps a sampler cell index to the row index of its in-progress fade in
|
|
106
|
+
* {@link fadeMask}. Enforces at most one fade row per cell, so that the
|
|
107
|
+
* latest reveal/conceal command for a cell re-aims its existing fade
|
|
108
|
+
* instead of stacking a second, opposing row.
|
|
109
|
+
* @type {Map<number, number>}
|
|
110
|
+
*/
|
|
111
|
+
#fadeRowByCell = new Map();
|
|
112
|
+
|
|
90
113
|
on = {
|
|
91
114
|
textureChanged: new Signal()
|
|
92
115
|
};
|
|
@@ -112,6 +135,8 @@ export class FogOfWar {
|
|
|
112
135
|
|
|
113
136
|
const fadeMask = this.fadeMask;
|
|
114
137
|
|
|
138
|
+
const rowByCell = this.#fadeRowByCell;
|
|
139
|
+
|
|
115
140
|
let numRows = fadeMask.length;
|
|
116
141
|
|
|
117
142
|
let i = 0;
|
|
@@ -130,25 +155,24 @@ export class FogOfWar {
|
|
|
130
155
|
|
|
131
156
|
let writeValue = value | 0;
|
|
132
157
|
|
|
133
|
-
//
|
|
158
|
+
//store the advanced precise value
|
|
134
159
|
fadeMask.writeCellValue(i, 1, value);
|
|
135
160
|
|
|
161
|
+
let completed = false;
|
|
162
|
+
|
|
136
163
|
if (value <= 0) {
|
|
164
|
+
writeValue = 0;
|
|
165
|
+
|
|
137
166
|
if (speed < 0) {
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
i--;
|
|
141
|
-
numRows--;
|
|
167
|
+
//revealing fade reached the bottom
|
|
168
|
+
completed = true;
|
|
142
169
|
}
|
|
143
|
-
writeValue = 0;
|
|
144
170
|
} else if (value >= 255) {
|
|
145
171
|
writeValue = 255;
|
|
146
172
|
|
|
147
173
|
if (speed > 0) {
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
i--;
|
|
151
|
-
numRows--;
|
|
174
|
+
//concealing fade reached the top
|
|
175
|
+
completed = true;
|
|
152
176
|
}
|
|
153
177
|
}
|
|
154
178
|
|
|
@@ -157,41 +181,108 @@ export class FogOfWar {
|
|
|
157
181
|
samplerData[index] = writeValue;
|
|
158
182
|
this.textureNeedsUpdate = true;
|
|
159
183
|
}
|
|
184
|
+
|
|
185
|
+
if (completed) {
|
|
186
|
+
//Drop the finished row while keeping the cell->row index
|
|
187
|
+
//consistent. Swap the last row into this slot (O(1)) instead of
|
|
188
|
+
//shifting the whole tail forward, so only one other row's index
|
|
189
|
+
//needs to be patched in the map.
|
|
190
|
+
rowByCell.delete(index);
|
|
191
|
+
|
|
192
|
+
const lastRow = numRows - 1;
|
|
193
|
+
|
|
194
|
+
if (i !== lastRow) {
|
|
195
|
+
const movedCell = fadeMask.readCellValue(lastRow, 0);
|
|
196
|
+
|
|
197
|
+
fadeMask.copyRow(lastRow, i);
|
|
198
|
+
|
|
199
|
+
rowByCell.set(movedCell, i);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
fadeMask.removeRows(lastRow, 1);
|
|
203
|
+
|
|
204
|
+
i--;
|
|
205
|
+
numRows--;
|
|
206
|
+
}
|
|
160
207
|
}
|
|
161
208
|
}
|
|
162
209
|
|
|
163
210
|
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
211
|
+
* Schedule (or re-aim) a fade for a single sampler cell so that it converges
|
|
212
|
+
* to `target`. Guarantees at most one fade row per cell: if the cell already
|
|
213
|
+
* has an in-progress fade its direction is updated in place, so the latest
|
|
214
|
+
* command wins instead of stacking a second, opposing row.
|
|
215
|
+
* @param {number} index sampler cell index
|
|
216
|
+
* @param {number} target target sampler value, either 0 (revealed) or 255 (concealed)
|
|
217
|
+
* @returns {boolean} whether the visible sampler value was changed (i.e. the distance field may need a rebuild)
|
|
167
218
|
*/
|
|
168
|
-
|
|
219
|
+
#scheduleCellFade(index, target) {
|
|
169
220
|
const fadeMask = this.fadeMask;
|
|
221
|
+
const rowByCell = this.#fadeRowByCell;
|
|
170
222
|
|
|
171
|
-
const
|
|
223
|
+
const speed = target === 0 ? -FADE_SPEED : FADE_SPEED;
|
|
172
224
|
|
|
173
|
-
const
|
|
225
|
+
const existingRow = rowByCell.get(index);
|
|
174
226
|
|
|
175
|
-
|
|
227
|
+
if (existingRow !== undefined) {
|
|
228
|
+
//A fade is already in progress for this cell, re-aim it in place.
|
|
229
|
+
//The precise value column is left untouched so the fade resumes from
|
|
230
|
+
//its current progress and never snaps back through the far end.
|
|
231
|
+
fadeMask.writeCellValue(existingRow, 2, speed);
|
|
176
232
|
|
|
177
|
-
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const samplerData = this.sampler.data;
|
|
237
|
+
|
|
238
|
+
const current = samplerData[index];
|
|
239
|
+
|
|
240
|
+
if (current === target) {
|
|
241
|
+
//already fully at the target, nothing to fade
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let seedValue = current;
|
|
246
|
+
let visibleChanged = false;
|
|
178
247
|
|
|
179
|
-
if (
|
|
248
|
+
if (target === 0 && current === 255) {
|
|
249
|
+
//pre-fade off the fully-concealed value so the distance field
|
|
250
|
+
//immediately treats this cell as being revealed
|
|
251
|
+
seedValue = INITIAL_FADE_VALUE;
|
|
180
252
|
samplerData[index] = INITIAL_FADE_VALUE;
|
|
253
|
+
visibleChanged = true;
|
|
254
|
+
}
|
|
181
255
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
256
|
+
//add record to fade mask
|
|
257
|
+
fadeRow[0] = index;
|
|
258
|
+
fadeRow[1] = seedValue;
|
|
259
|
+
fadeRow[2] = speed;
|
|
186
260
|
|
|
187
|
-
|
|
261
|
+
const rowIndex = fadeMask.addRow(fadeRow);
|
|
262
|
+
|
|
263
|
+
rowByCell.set(index, rowIndex);
|
|
264
|
+
|
|
265
|
+
return visibleChanged;
|
|
266
|
+
}
|
|
188
267
|
|
|
268
|
+
/**
|
|
269
|
+
*
|
|
270
|
+
* @param {number} x
|
|
271
|
+
* @param {number} y
|
|
272
|
+
*/
|
|
273
|
+
revealPoint(x, y) {
|
|
274
|
+
const samplerWidth = this.sampler.width;
|
|
275
|
+
|
|
276
|
+
const index = (y + 1) * samplerWidth + (x + 1);
|
|
277
|
+
|
|
278
|
+
if (this.#scheduleCellFade(index, 0)) {
|
|
189
279
|
this.distanceFieldNeedsUpdate = true;
|
|
190
280
|
}
|
|
191
281
|
}
|
|
192
282
|
|
|
193
283
|
clear() {
|
|
194
284
|
this.fadeMask.clear();
|
|
285
|
+
this.#fadeRowByCell.clear();
|
|
195
286
|
|
|
196
287
|
this.sampler.data.fill(255);
|
|
197
288
|
|
|
@@ -201,6 +292,7 @@ export class FogOfWar {
|
|
|
201
292
|
|
|
202
293
|
revealAll() {
|
|
203
294
|
this.fadeMask.clear();
|
|
295
|
+
this.#fadeRowByCell.clear();
|
|
204
296
|
|
|
205
297
|
this.sampler.data.fill(0);
|
|
206
298
|
|
|
@@ -230,11 +322,8 @@ export class FogOfWar {
|
|
|
230
322
|
const lastPixelX = samplerWidth - 1;
|
|
231
323
|
|
|
232
324
|
let changeFlag = false;
|
|
233
|
-
const samplerData = sampler.data;
|
|
234
325
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
sampler.traverseCircle(x + 1, y + 1, radius, function (x, y, sampler) {
|
|
326
|
+
sampler.traverseCircle(x + 1, y + 1, radius, (x, y) => {
|
|
238
327
|
|
|
239
328
|
if (x <= 0 || x >= lastPixelX || y <= 0 || y >= lastPixelY) {
|
|
240
329
|
//edges are reserved to preserve cover outside of the working area
|
|
@@ -243,16 +332,7 @@ export class FogOfWar {
|
|
|
243
332
|
|
|
244
333
|
const index = y * samplerWidth + x;
|
|
245
334
|
|
|
246
|
-
if (
|
|
247
|
-
samplerData[index] = INITIAL_FADE_VALUE;
|
|
248
|
-
|
|
249
|
-
//add record to fade mask
|
|
250
|
-
fadeRow[0] = index;
|
|
251
|
-
fadeRow[1] = INITIAL_FADE_VALUE;
|
|
252
|
-
fadeRow[2] = -FADE_SPEED;
|
|
253
|
-
|
|
254
|
-
fadeMask.addRow(fadeRow);
|
|
255
|
-
|
|
335
|
+
if (this.#scheduleCellFade(index, 0)) {
|
|
256
336
|
changeFlag = true;
|
|
257
337
|
}
|
|
258
338
|
|
|
@@ -283,11 +363,8 @@ export class FogOfWar {
|
|
|
283
363
|
const lastPixelX = samplerWidth - 1;
|
|
284
364
|
|
|
285
365
|
let changeFlag = false;
|
|
286
|
-
const samplerData = sampler.data;
|
|
287
|
-
|
|
288
|
-
const fadeMask = this.fadeMask;
|
|
289
366
|
|
|
290
|
-
sampler.traverseCircle(x + 1, y + 1, radius,
|
|
367
|
+
sampler.traverseCircle(x + 1, y + 1, radius, (x, y) => {
|
|
291
368
|
|
|
292
369
|
if (x <= 0 || x >= lastPixelX || y <= 0 || y >= lastPixelY) {
|
|
293
370
|
//edges are reserved to preserve cover outside of the working area
|
|
@@ -296,17 +373,7 @@ export class FogOfWar {
|
|
|
296
373
|
|
|
297
374
|
const index = y * samplerWidth + x;
|
|
298
375
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
if (value !== 255) {
|
|
302
|
-
|
|
303
|
-
//add record to fade mask
|
|
304
|
-
fadeRow[0] = index;
|
|
305
|
-
fadeRow[1] = value;
|
|
306
|
-
fadeRow[2] = FADE_SPEED;
|
|
307
|
-
|
|
308
|
-
fadeMask.addRow(fadeRow);
|
|
309
|
-
|
|
376
|
+
if (this.#scheduleCellFade(index, 255)) {
|
|
310
377
|
changeFlag = true;
|
|
311
378
|
}
|
|
312
379
|
|
|
@@ -319,13 +386,91 @@ export class FogOfWar {
|
|
|
319
386
|
}
|
|
320
387
|
}
|
|
321
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Rebuild the cell -> fade row index from the current {@link fadeMask}
|
|
391
|
+
* contents. Must be invoked whenever the fade mask is populated without
|
|
392
|
+
* going through {@link reveal}/{@link conceal}/{@link revealPoint} (e.g.
|
|
393
|
+
* after deserialization), otherwise those methods could stack duplicate
|
|
394
|
+
* fade rows for a cell.
|
|
395
|
+
*/
|
|
396
|
+
rebuildFadeIndex() {
|
|
397
|
+
const rowByCell = this.#fadeRowByCell;
|
|
398
|
+
|
|
399
|
+
rowByCell.clear();
|
|
400
|
+
|
|
401
|
+
const fadeMask = this.fadeMask;
|
|
402
|
+
|
|
403
|
+
const numRows = fadeMask.length;
|
|
404
|
+
|
|
405
|
+
for (let i = 0; i < numRows; i++) {
|
|
406
|
+
const index = fadeMask.readCellValue(i, 0);
|
|
407
|
+
|
|
408
|
+
rowByCell.set(index, i);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
322
412
|
dispose() {
|
|
323
413
|
if (this.texture !== null) {
|
|
324
414
|
this.texture.dispose();
|
|
325
415
|
}
|
|
326
416
|
}
|
|
327
417
|
|
|
418
|
+
/**
|
|
419
|
+
* Copy the sampler's outermost REAL cells out into the 1-cell ring that
|
|
420
|
+
* {@link rebuildSampler} pads it with.
|
|
421
|
+
*
|
|
422
|
+
* That ring is padding — it exists so the shader's 5x5 blur and the distance
|
|
423
|
+
* field have something to read past the edge — and it is filled with full
|
|
424
|
+
* concealment. The blur then drags that concealment ~2 cells back INTO the
|
|
425
|
+
* fogged area, so the outermost cells of the world can never read as fully
|
|
426
|
+
* revealed however thoroughly they are explored; and every lookup from outside
|
|
427
|
+
* the area clamps onto it, which is what paints the void. Mirroring makes the
|
|
428
|
+
* padding agree with the edge it pads, on both counts.
|
|
429
|
+
*
|
|
430
|
+
* O(perimeter), and only on frames that upload a new texture.
|
|
431
|
+
*
|
|
432
|
+
* @private
|
|
433
|
+
*/
|
|
434
|
+
#mirrorBorderRing() {
|
|
435
|
+
const s = this.sampler;
|
|
436
|
+
|
|
437
|
+
const w = s.width;
|
|
438
|
+
const h = s.height;
|
|
439
|
+
|
|
440
|
+
if (w < 3 || h < 3) {
|
|
441
|
+
// no interior to mirror from
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const data = s.data;
|
|
446
|
+
|
|
447
|
+
const last_row = (h - 1) * w;
|
|
448
|
+
const second_last_row = (h - 2) * w;
|
|
449
|
+
|
|
450
|
+
// top and bottom edges, corners excluded — those come from the sides below
|
|
451
|
+
for (let x = 1; x < w - 1; x++) {
|
|
452
|
+
data[x] = data[w + x];
|
|
453
|
+
data[last_row + x] = data[second_last_row + x];
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// left and right edges, corners INCLUDED: the row above and below have
|
|
457
|
+
// already been mirrored, so a corner ends up with its diagonal neighbour's
|
|
458
|
+
// value rather than an arbitrary one
|
|
459
|
+
for (let y = 0; y < h; y++) {
|
|
460
|
+
const row = y * w;
|
|
461
|
+
|
|
462
|
+
data[row] = data[row + 1];
|
|
463
|
+
data[row + w - 1] = data[row + w - 2];
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
328
467
|
updateTexture() {
|
|
468
|
+
if (this.edge_mode === FogOfWarEdgeMode.Extend) {
|
|
469
|
+
// do this HERE, at the single point every reveal path funnels through
|
|
470
|
+
// on its way to the GPU, rather than in each of them
|
|
471
|
+
this.#mirrorBorderRing();
|
|
472
|
+
}
|
|
473
|
+
|
|
329
474
|
const s = this.sampler;
|
|
330
475
|
|
|
331
476
|
/**
|
|
@@ -594,7 +739,10 @@ export class FogOfWar {
|
|
|
594
739
|
this.size.set(w, h);
|
|
595
740
|
this.scale.set(scale);
|
|
596
741
|
|
|
597
|
-
//TODO update fade mask as necessary
|
|
742
|
+
//TODO update fade mask as necessary - the sampler indices change with the
|
|
743
|
+
//new width, so any in-progress fade rows (and the #fadeRowByCell index that
|
|
744
|
+
//mirrors them) would need remapping or clearing. Only reachable at link time
|
|
745
|
+
//today, when both are empty.
|
|
598
746
|
|
|
599
747
|
this.rebuildSampler();
|
|
600
748
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the fog of war does AT, and beyond, the edge of the fogged area.
|
|
3
|
+
*
|
|
4
|
+
* The fog is a screen-space effect (see screenSpaceFogOfWarShader): per pixel it
|
|
5
|
+
* reconstructs a world position from the depth buffer and reads that position out
|
|
6
|
+
* of the fog sampler. Neither end of that pipeline is defined outside the fogged
|
|
7
|
+
* rectangle — a pixel with no geometry has no world position to reconstruct, and
|
|
8
|
+
* a world position outside the sampler has no cell to read — so what happens
|
|
9
|
+
* there is a POLICY rather than a fact, and this is the knob for it.
|
|
10
|
+
*/
|
|
11
|
+
export type FogOfWarEdgeMode = number;
|
|
12
|
+
export namespace FogOfWarEdgeMode {
|
|
13
|
+
let Conceal: number;
|
|
14
|
+
let Extend: number;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=FogOfWarEdgeMode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FogOfWarEdgeMode.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWarEdgeMode.js"],"names":[],"mappings":";;;;;;;;;;+BAUU,MAAM"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the fog of war does AT, and beyond, the edge of the fogged area.
|
|
3
|
+
*
|
|
4
|
+
* The fog is a screen-space effect (see screenSpaceFogOfWarShader): per pixel it
|
|
5
|
+
* reconstructs a world position from the depth buffer and reads that position out
|
|
6
|
+
* of the fog sampler. Neither end of that pipeline is defined outside the fogged
|
|
7
|
+
* rectangle — a pixel with no geometry has no world position to reconstruct, and
|
|
8
|
+
* a world position outside the sampler has no cell to read — so what happens
|
|
9
|
+
* there is a POLICY rather than a fact, and this is the knob for it.
|
|
10
|
+
*
|
|
11
|
+
* @enum {number}
|
|
12
|
+
*/
|
|
13
|
+
export const FogOfWarEdgeMode = {
|
|
14
|
+
/**
|
|
15
|
+
* Everything outside the fogged area is CONCEALED: the sampler's border ring
|
|
16
|
+
* is left at full concealment, and a pixel with no geometry takes whatever
|
|
17
|
+
* the clamped lookup returns — which is that same border.
|
|
18
|
+
*
|
|
19
|
+
* The default, and the behaviour of every release before this option existed.
|
|
20
|
+
* Right for a world that fills the screen, where "outside" is somewhere the
|
|
21
|
+
* player is never shown.
|
|
22
|
+
*/
|
|
23
|
+
Conceal: 0,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The fog EXTENDS outward instead: the border ring mirrors the cells just
|
|
27
|
+
* inside it, and pixels with no geometry are left alone entirely.
|
|
28
|
+
*
|
|
29
|
+
* For a world with a VISIBLE boundary — a finite arena the camera can see
|
|
30
|
+
* past. Under {@link FogOfWarEdgeMode.Conceal} such a scene gets a hard black
|
|
31
|
+
* rectangle drawn exactly on its boundary (the concealed border ring, clamped
|
|
32
|
+
* across the whole void), which both advertises where the map stops and paints
|
|
33
|
+
* over anything drawn earlier to hide it — this layer composites last, over
|
|
34
|
+
* every other effect. Under Extend the fog agrees with the ground it borders:
|
|
35
|
+
* explored terrain stays clear right out past the boundary, unexplored terrain
|
|
36
|
+
* stays dark, and nothing marks where the geometry ends.
|
|
37
|
+
*/
|
|
38
|
+
Extend: 1,
|
|
39
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FogOfWarSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWarSystem.js"],"names":[],"mappings":"AAwBA;IACI;;;OAGG;IACH,sCA0BC;IAvBG;;;OAGG;IACH,yBAAwB;IAExB,mDAAuC;IAEvC,gEAEC;IAED,mCAAoD;IAIpD;;;OAGG;IACH,eAFU,aAAa,CAEE;IAEzB,uBAAuB;IAG3B;;;OAGG;IACH,yBAFa,gBAAgB,CAuE5B;IAsBG,kBAAgC;
|
|
1
|
+
{"version":3,"file":"FogOfWarSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/fow/FogOfWarSystem.js"],"names":[],"mappings":"AAwBA;IACI;;;OAGG;IACH,sCA0BC;IAvBG;;;OAGG;IACH,yBAAwB;IAExB,mDAAuC;IAEvC,gEAEC;IAED,mCAAoD;IAIpD;;;OAGG;IACH,eAFU,aAAa,CAEE;IAEzB,uBAAuB;IAG3B;;;OAGG;IACH,yBAFa,gBAAgB,CAuE5B;IAsBG,kBAAgC;IAgEpC,4CAEC;IAED;;;;;OAKG;IACH,UAJW,QAAQ,WACR,OAAO,UACP,MAAM,QAmBhB;IAED,kDAQC;IAED,6BAUC;CACJ;uBA1PsB,cAAc;oBACjB,2BAA2B;yBACtB,eAAe;4CAdI,oDAAoD;iCAS/D,sDAAsD;8BAPzD,0CAA0C"}
|
|
@@ -178,6 +178,7 @@ export class FogOfWarSystem extends System {
|
|
|
178
178
|
fogOfWarRenderer.setResolution(fow.size.x, fow.size.y);
|
|
179
179
|
fogOfWarRenderer.setUvTransformFromFog(fow);
|
|
180
180
|
fogOfWarRenderer.setFogColor(fow.color);
|
|
181
|
+
fogOfWarRenderer.setEdgeMode(fow.edge_mode);
|
|
181
182
|
|
|
182
183
|
|
|
183
184
|
//stop traversal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FogOfWarSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js"],"names":[],"mappings":"AAQA;;IAEI,uBAAiB;IAGjB,oDAA2D;IAE3D;;;;OAIG;IACH,uCAFW,QAAQ,QAyBlB;IAED;;;;OAIG;IACH,yCAFW,QAAQ,
|
|
1
|
+
{"version":3,"file":"FogOfWarSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/serialization/FogOfWarSerializationAdapter.js"],"names":[],"mappings":"AAQA;;IAEI,uBAAiB;IAGjB,oDAA2D;IAE3D;;;;OAIG;IACH,uCAFW,QAAQ,QAyBlB;IAED;;;;OAIG;IACH,yCAFW,QAAQ,QAmClB;CACJ;gDApF+C,yDAAyD;yBAChF,gBAAgB;8CAKlC,kFAAkF"}
|
|
@@ -75,6 +75,9 @@ export class FogOfWarSerializationAdapter extends BinaryClassSerializationAdapte
|
|
|
75
75
|
//deserialize reveal state
|
|
76
76
|
deserializeRowFirstTable(buffer, value.fadeMask);
|
|
77
77
|
|
|
78
|
+
//rebuild the cell -> fade row index to match the restored fade mask
|
|
79
|
+
value.rebuildFadeIndex();
|
|
80
|
+
|
|
78
81
|
//
|
|
79
82
|
value.textureNeedsUpdate = true;
|
|
80
83
|
value.rebuildDistanceSampler();
|
|
@@ -47,6 +47,12 @@ export class FogOfWarRenderer {
|
|
|
47
47
|
* @param {Vector4} color
|
|
48
48
|
*/
|
|
49
49
|
setFogColor(color: Vector4): void;
|
|
50
|
+
/**
|
|
51
|
+
* What the fog does outside the fogged area. See {@link FogOfWarEdgeMode}.
|
|
52
|
+
*
|
|
53
|
+
* @param {FogOfWarEdgeMode} mode
|
|
54
|
+
*/
|
|
55
|
+
setEdgeMode(mode: FogOfWarEdgeMode): void;
|
|
50
56
|
/**
|
|
51
57
|
*
|
|
52
58
|
* @param {WebGLRenderer} renderer
|
|
@@ -59,4 +65,5 @@ export class FogOfWarRenderer {
|
|
|
59
65
|
import { Mesh } from "three";
|
|
60
66
|
import { OrthographicCamera } from "three";
|
|
61
67
|
import { Scene } from "three";
|
|
68
|
+
import { FogOfWarEdgeMode } from "../FogOfWarEdgeMode.js";
|
|
62
69
|
//# sourceMappingURL=FogOfWarRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FogOfWarRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/shader/FogOfWarRenderer.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FogOfWarRenderer.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/fow/shader/FogOfWarRenderer.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,+EAFoB,MAAM,QAAE,MAAM,QAAE,MAAM,QAAE,MAAM,gBAiBjD;AAED;IAEQ;;;OAGG;IACH,yBAAgD;IAEhD,2DAAkE;IAElE,2BAAwD;IACxD,aAAwB;IAI5B;;;OAGG;IACH,2CAKC;IAED;;;;;;OAMG;IACH,wBALW,MAAM,WACN,MAAM,UACN,MAAM,UACN,MAAM,QAqBhB;IAED;;;OAGG;IACH,uCAIC;IAED;;;OAGG;IACH,oCAGC;IAED;;;;OAIG;IACH,iBAHW,MAAM,KACN,MAAM,QAIhB;IAED;;;OAGG;IACH,kCAEC;IAED;;;;OAIG;IACH,kBAFW,gBAAgB,QAI1B;IAED;;;;;;OAMG;IACH,wCAJW,oBAAkB,kBAAkB,SACpC,KAAK,mCAqBf;CACJ;qBA1J+C,OAAO;mCAAP,OAAO;sBAAP,OAAO;iCAItB,wBAAwB"}
|