Skip to content

Commit

Permalink
Merge pull request #4058 from kwvanderlinde/bugfix/4057-flush-aura-ca…
Browse files Browse the repository at this point in the history
…che-when-auras-removed
  • Loading branch information
cwisniew authored May 13, 2023
2 parents 85ef04d + f6c6f61 commit 738eb86
Showing 1 changed file with 69 additions and 69 deletions.
138 changes: 69 additions & 69 deletions src/main/java/net/rptools/maptool/client/ui/zone/ZoneView.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ private record IlluminationKey(double multiplier) {}

// region These fields track light sources and their illuminated areas.

/** Map light source type to all tokens with that type. */
/**
* Map light source type to all tokens with that type. Will always have entries for each light
* type, so no need to check whether they exist.
*/
private final Map<LightSource.Type, Set<GUID>> lightSourceMap = new HashMap<>();

// endregion
Expand Down Expand Up @@ -135,6 +138,10 @@ private record IlluminationKey(double multiplier) {}
*/
public ZoneView(Zone zone) {
this.zone = zone;

for (final var type : LightSource.Type.values()) {
lightSourceMap.put(type, new HashSet<>());
}
findLightSources();

new MapToolEventBus().getMainEventBus().register(this);
Expand Down Expand Up @@ -265,9 +272,7 @@ private IlluminationModel getIlluminationModel(IlluminationKey illuminationKey)

// We need to get all lights ordered by lumens. From there, we can do darkness subtraction and
// build drawable lights for each, and then build a lumens map.
final var lightSourceTokenGuids =
new ArrayList<>(
lightSourceMap.getOrDefault(LightSource.Type.NORMAL, Collections.emptySet()));
final var lightSourceTokenGuids = lightSourceMap.get(LightSource.Type.NORMAL);
final var lightSourceTokens =
lightSourceTokenGuids.stream()
.map(zone::getToken)
Expand Down Expand Up @@ -493,9 +498,7 @@ private Illumination getIllumination(IlluminationKey illuminationKey) {
}

if (token.hasLightSources()
&& !lightSourceMap
.getOrDefault(LightSource.Type.NORMAL, Collections.emptySet())
.contains(token.getId())) {
&& !lightSourceMap.get(LightSource.Type.NORMAL).contains(token.getId())) {
// This accounts for temporary tokens (such as during an Expose Last Path)
personalLights.addAll(calculateLitAreas(token, sight.getMultiplier()));
}
Expand Down Expand Up @@ -642,62 +645,59 @@ public Area getVisibleArea(Token token, PlayerView view) {
public List<DrawableLight> getDrawableAuras() {
if (drawableAuras == null) {
List<DrawableLight> lightList = new LinkedList<DrawableLight>();
final var auraTokenGUIDs = lightSourceMap.get(LightSource.Type.AURA);
if (auraTokenGUIDs != null) {
for (GUID lightSourceToken : auraTokenGUIDs) {
Token token = zone.getToken(lightSourceToken);
if (token == null) {
for (GUID lightSourceToken : lightSourceMap.get(LightSource.Type.AURA)) {
Token token = zone.getToken(lightSourceToken);
if (token == null) {
continue;
}
Point p = FogUtil.calculateVisionCenter(token, zone);

for (AttachedLightSource als : token.getLightSources()) {
LightSource lightSource = MapTool.getCampaign().getLightSource(als.getLightSourceId());
if (lightSource == null) {
continue;
}
// Token can also have non-auras lights, we don't want those.
if (lightSource.getType() != LightSource.Type.AURA) {
continue;
}
Point p = FogUtil.calculateVisionCenter(token, zone);

for (AttachedLightSource als : token.getLightSources()) {
LightSource lightSource = MapTool.getCampaign().getLightSource(als.getLightSourceId());
if (lightSource == null) {
Area lightSourceArea = lightSource.getArea(token, zone);
lightSourceArea.transform(AffineTransform.getTranslateInstance(p.x, p.y));
Area visibleArea =
FogUtil.calculateVisibility(
p,
lightSourceArea,
getTopologyTree(Zone.TopologyType.WALL_VBL),
getTopologyTree(Zone.TopologyType.HILL_VBL),
getTopologyTree(Zone.TopologyType.PIT_VBL));

// This needs to be cached somehow
for (Light light : lightSource.getLightList()) {
// If there is no paint, it's a "bright aura" that just shows whatever is beneath it
// and doesn't need to be rendered.
if (light.getPaint() == null) {
continue;
}
// Token can also have non-auras lights, we don't want those.
if (lightSource.getType() != LightSource.Type.AURA) {
boolean isOwner = token.getOwners().contains(MapTool.getPlayer().getName());
if ((light.isGM() && !MapTool.getPlayer().isEffectiveGM())) {
continue;
}

Area lightSourceArea = lightSource.getArea(token, zone);
lightSourceArea.transform(AffineTransform.getTranslateInstance(p.x, p.y));
Area visibleArea =
FogUtil.calculateVisibility(
p,
lightSourceArea,
getTopologyTree(Zone.TopologyType.WALL_VBL),
getTopologyTree(Zone.TopologyType.HILL_VBL),
getTopologyTree(Zone.TopologyType.PIT_VBL));

// This needs to be cached somehow
for (Light light : lightSource.getLightList()) {
// If there is no paint, it's a "bright aura" that just shows whatever is beneath it
// and doesn't need to be rendered.
if (light.getPaint() == null) {
continue;
}
boolean isOwner = token.getOwners().contains(MapTool.getPlayer().getName());
if ((light.isGM() && !MapTool.getPlayer().isEffectiveGM())) {
continue;
}
if ((!token.isVisible()) && !MapTool.getPlayer().isEffectiveGM()) {
continue;
}
if (token.isVisibleOnlyToOwner() && !AppUtil.playerOwns(token)) {
continue;
}
if (light.isOwnerOnly() && !isOwner && !MapTool.getPlayer().isEffectiveGM()) {
continue;
}

// Calculate the area covered by this particular range.
Area lightArea = lightSource.getArea(token, zone, light);
lightArea.transform(AffineTransform.getTranslateInstance(p.x, p.y));
lightArea.intersect(visibleArea);
lightList.add(new DrawableLight(light.getPaint(), lightArea, light.getLumens()));
if ((!token.isVisible()) && !MapTool.getPlayer().isEffectiveGM()) {
continue;
}
if (token.isVisibleOnlyToOwner() && !AppUtil.playerOwns(token)) {
continue;
}
if (light.isOwnerOnly() && !isOwner && !MapTool.getPlayer().isEffectiveGM()) {
continue;
}

// Calculate the area covered by this particular range.
Area lightArea = lightSource.getArea(token, zone, light);
lightArea.transform(AffineTransform.getTranslateInstance(p.x, p.y));
lightArea.intersect(visibleArea);
lightList.add(new DrawableLight(light.getPaint(), lightArea, light.getLumens()));
}
}
}
Expand All @@ -712,7 +712,9 @@ public List<DrawableLight> getDrawableAuras() {
* Find the light sources from all appropriate tokens, and store them in {@link #lightSourceMap}.
*/
private void findLightSources() {
lightSourceMap.clear();
for (final var set : lightSourceMap.values()) {
set.clear();
}

for (Token token : zone.getAllTokens()) {
if (token.hasLightSources() && token.isVisible()) {
Expand All @@ -722,9 +724,7 @@ private void findLightSources() {
if (lightSource == null) {
continue;
}
Set<GUID> lightSet =
lightSourceMap.computeIfAbsent(lightSource.getType(), k -> new HashSet<>());
lightSet.add(token.getId());
lightSourceMap.get(lightSource.getType()).add(token.getId());
}
}
}
Expand Down Expand Up @@ -832,14 +832,19 @@ public void flush(Token token) {
visibleAreaMap.clear();
// TODO Could we instead only clear those views that include the token?
drawableLights.clear();
drawableAuras = null;
} else if (token.getHasSight()) {
contributedPersonalLightsByToken.remove(token.getId());
// TODO Could we instead only clear those views that include the token?
illuminationsPerView.clear();
exposedAreaMap.clear();
visibleAreaMap.clear();
drawableLights.clear();
}

// If the token had auras as well, we'll need to recompute them. This could be more precise
// (i.e., only do the ones for this token) but that's more complicated than it's worth for now.
if (lightSourceMap.get(LightSource.Type.AURA).contains(token.getId())
|| token.hasLightSourceType(LightSource.Type.AURA)) {
drawableAuras = null;
}
}
Expand Down Expand Up @@ -900,10 +905,7 @@ private void onTokensRemoved(TokensRemoved event) {
if (lightSource == null) {
continue;
}
Set<GUID> lightSet = lightSourceMap.get(lightSource.getType());
if (lightSet != null) {
lightSet.remove(token.getId());
}
lightSourceMap.get(lightSource.getType()).remove(token.getId());
}
}

Expand Down Expand Up @@ -958,12 +960,10 @@ private boolean processTokenAddChangeEvent(List<Token> tokens) {
if (lightSource != null) {
Set<GUID> lightSet = lightSourceMap.get(lightSource.getType());
if (hasLightSource) {
if (lightSet == null) {
lightSet = new HashSet<GUID>();
lightSourceMap.put(lightSource.getType(), lightSet);
}
lightSet.add(token.getId());
} else if (lightSet != null) lightSet.remove(token.getId());
} else {
lightSet.remove(token.getId());
}
}
}
hasSight |= token.getHasSight();
Expand Down

0 comments on commit 738eb86

Please sign in to comment.