Skip to content

Commit

Permalink
Merge pull request #4803 from kwvanderlinde/bugfix/257-short-cone-art…
Browse files Browse the repository at this point in the history
…ifacts

Magnify light source radius rather than shape
  • Loading branch information
cwisniew authored May 30, 2024
2 parents 52c493c + 26ebf42 commit 4afc0b4
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 41 deletions.
38 changes: 7 additions & 31 deletions src/main/java/net/rptools/maptool/client/ui/zone/ZoneView.java
Original file line number Diff line number Diff line change
Expand Up @@ -336,14 +336,9 @@ private List<ContributedLight> calculateLitAreaForLightSource(

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

final var lightSourceArea = lightSource.getArea(lightSourceToken, zone);
// Calculate exposed area
// Jamz: OK, let not have lowlight vision type multiply darkness radius
if (multiplier != 1 && lightSource.getType() == LightSource.Type.NORMAL) {
lightSourceArea.transform(magnifyTransform);
}
final var lightSourceArea = lightSource.getArea(lightSourceToken, zone, multiplier);
lightSourceArea.transform(translateTransform);

Area lightSourceVisibleArea = lightSourceArea;
Expand All @@ -365,35 +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());
if (notScaledLightArea == null) {
continue;
}
final var lightArea = new Area(notScaledLightArea);

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

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
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ public void render(Graphics2D g, PlayerView view, Token tokenUnderMouse) {

private void renderWorld(Graphics2D worldG, PlayerView view, Token token) {
// The vision of the token is not necessarily related to the current view.
// final var tokenView = view.derive(Collections.singleton(token));
final var tokenView = new PlayerView(view.getRole(), List.of(token));

Area currentTokenVisionArea = zoneView.getVisibleArea(token, tokenView);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/rptools/maptool/model/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.swing.Action;
import javax.swing.KeyStroke;
import net.rptools.lib.FileUtil;
Expand Down Expand Up @@ -352,7 +353,7 @@ public void setSize(int size) {
* @param scaleWithToken used to increase the area based on token footprint
* @return Area
*/
public Area getShapedArea(
public @Nonnull Area getShapedArea(
ShapeType shape,
Token token,
double range,
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/net/rptools/maptool/model/Light.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,28 @@ public double getArcAngle() {
return shape;
}

public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone, boolean scaleWithToken) {
public @Nonnull Area getArea(
@Nonnull Token token, @Nonnull Zone zone, double multiplier, boolean scaleWithToken) {
var radius = getRadius();
// Darkness does not get magnified.
if (lumens >= 0) {
radius *= multiplier;
}
return zone.getGrid()
.getShapedArea(
getShape(),
token,
getRadius(),
radius,
getWidth(),
getArcAngle(),
(int) getFacingOffset(),
scaleWithToken);
}

public @Nonnull Area getArea(@Nonnull Token token, @Nonnull Zone zone, boolean scaleWithToken) {
return getArea(token, zone, 1.0, scaleWithToken);
}

public boolean isGM() {
return isGM;
}
Expand Down
51 changes: 45 additions & 6 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 @@ -232,12 +276,7 @@ public boolean isIgnoresVBL() {

/* 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 4afc0b4

Please sign in to comment.