Skip to content

Commit

Permalink
Move nested light area calculation into LightSource
Browse files Browse the repository at this point in the history
this allows us to consistently avoid magnifying darkness and auras without having to constantly check these conditions
in `ZoneView`.
  • Loading branch information
kwvanderlinde committed May 28, 2024
1 parent a744a82 commit 26ebf42
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 46 deletions.
33 changes: 6 additions & 27 deletions src/main/java/net/rptools/maptool/client/ui/zone/ZoneView.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,17 +330,13 @@ private List<ContributedLight> calculateLitAreas(Token lightSourceToken, double

private List<ContributedLight> calculateLitAreaForLightSource(
@Nonnull Token lightSourceToken, double multiplier, @Nonnull LightSource lightSource) {
// TODO Make the call adjust multiplier for non-NORMAL lights if necessary. In here we should
// just apply the request regardless of the light source.

if (lightSource.getType() != LightSource.Type.NORMAL) {
return Collections.emptyList();
}

final var p = FogUtil.calculateVisionCenter(lightSourceToken, zone);
final var translateTransform = AffineTransform.getTranslateInstance(p.x, p.y);

// Jamz: OK, let not have lowlight vision type multiply darkness radius TODO Huh???
// Calculate exposed area
final var lightSourceArea = lightSource.getArea(lightSourceToken, zone, multiplier);
lightSourceArea.transform(translateTransform);
Expand All @@ -364,33 +360,16 @@ private List<ContributedLight> calculateLitAreaForLightSource(

final var litAreas = new ArrayList<ContributedLight>();

// Tracks the cummulative inner ranges of light sources so that we can cut them out of the
// outer ranges and end up with disjoint sets, even when magnifying.
// Note that this "hole punching" has nothing to do with lumen strength, it's just a way of
// making smaller ranges act as lower bounds for larger ranges.
final var cummulativeNotTransformedArea = new Area();
for (final var light : lightSource.getLightList()) {
final var notScaledLightArea =
light.getArea(lightSourceToken, zone, lightSource.isScaleWithToken());

// Lowlight vision does not magnify darkness.
final var shouldMagnify = // multiplier != 1 &&
lightSource.getType() == LightSource.Type.NORMAL && light.getLumens() >= 0;
for (final var lightArea : lightSource.getLightAreas(lightSourceToken, zone, multiplier)) {
var area = lightArea.area();
var light = lightArea.light();

final var lightArea =
shouldMagnify
? light.getArea(lightSourceToken, zone, multiplier, lightSource.isScaleWithToken())
: new Area(notScaledLightArea);

lightArea.subtract(cummulativeNotTransformedArea);
lightArea.transform(translateTransform);
lightArea.intersect(lightSourceVisibleArea);
area.transform(translateTransform);
area.intersect(lightSourceVisibleArea);

litAreas.add(
new ContributedLight(
new LitArea(light.getLumens(), lightArea), new LightInfo(lightSource, light)));

cummulativeNotTransformedArea.add(notScaledLightArea);
new LitArea(light.getLumens(), area), new LightInfo(lightSource, light)));
}

// Magnification can cause different ranges for a single light source to overlap. This is not
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/net/rptools/maptool/model/Light.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,16 @@ public double getArcAngle() {

public @Nonnull Area getArea(
@Nonnull Token token, @Nonnull Zone zone, double multiplier, boolean scaleWithToken) {
// TODO Methinks we don't apply multiplier if darkness.
var radius = getRadius();
// Darkness does not get magnified.
if (lumens >= 0) {
radius *= multiplier;
}
return zone.getGrid()
.getShapedArea(
getShape(),
token,
multiplier * getRadius(),
radius,
getWidth(),
getArcAngle(),
(int) getFacingOffset(),
Expand Down
62 changes: 45 additions & 17 deletions src/main/java/net/rptools/maptool/model/LightSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,50 @@ public boolean isIgnoresVBL() {
return ignoresVBL;
}

public record LightArea(Light light, Area area) {}

public @Nonnull List<LightArea> getLightAreas(
@Nonnull Token token, @Nonnull Zone zone, double multiplier) {
// Tracks the cumulative inner ranges of light sources so that we can cut them out of the
// outer ranges and end up with disjoint sets, even when magnifying.
// Note that this "hole punching" has nothing to do with lumen strength, it's just a way of
// making smaller ranges act as lower bounds for larger ranges.

// Auras do not get magnified.
if (type != Type.NORMAL) {
multiplier = 1.0;
}

final var result = new ArrayList<LightArea>();
final var cummulativeNotTransformedArea = new Area();

for (final var light : lightList) {
final var notScaledLightArea = light.getArea(token, zone, scaleWithToken);

final var lightArea = light.getArea(token, zone, multiplier, scaleWithToken);
lightArea.subtract(cummulativeNotTransformedArea);
result.add(new LightArea(light, lightArea));

cummulativeNotTransformedArea.add(notScaledLightArea);
}
return result;
}

/* Area for all lights combined */
public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone, double multiplier) {
// Auras do not get magnified.
if (type != Type.NORMAL) {
multiplier = 1.0;
}

Area area = new Area();
for (Light light : lightList) {
area.add(light.getArea(token, zone, multiplier, isScaleWithToken()));
}

return area;
}

/*
* Area for a single light, subtracting any previous lights
*/
Expand All @@ -230,25 +274,9 @@ public boolean isIgnoresVBL() {
return area;
}

/* Area for all lights combined */
public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone, double multiplier) {
// TODO Methinks we don't apply multiplier if not NORMAL.
Area area = new Area();
for (Light light : lightList) {
area.add(light.getArea(token, zone, multiplier, isScaleWithToken()));
}

return area;
}

/* Area for all lights combined */
public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone) {
Area area = new Area();
for (Light light : lightList) {
area.add(light.getArea(token, zone, isScaleWithToken()));
}

return area;
return getArea(token, zone, 1.0);
}

@SuppressWarnings("unchecked")
Expand Down

0 comments on commit 26ebf42

Please sign in to comment.