Skip to content

Commit

Permalink
Merge pull request #3952 from kwvanderlinde/bugfix/3905-cme-canSeeTok…
Browse files Browse the repository at this point in the history
…en-1.13
  • Loading branch information
cwisniew authored Apr 17, 2023
2 parents e561f8f + 8f3246e commit 7c40324
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 242 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* This software Copyright by the RPTools.net development team, and
* licensed under the Affero GPL Version 3 or, at your option, any later
* version.
*
* MapTool Source Code is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public
* License * along with this source Code. If not, please visit
* <http://www.gnu.org/licenses/> and specifically the Affero license
* text at <http://www.gnu.org/licenses/agpl.html>.
*/
package net.rptools.maptool.client.ui.zone;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import net.rptools.maptool.model.GUID;
import net.rptools.maptool.model.Light;
import net.rptools.maptool.model.LightSource;

/**
* Manages the light sources and illuminations of a zone, for a given set of illumniator parameters.
*
* <p>This needs to be kept in sync with the associated {@code Zone} in order for the results to
* make sense
*
* <p>No caching is done here, this is purely a data structure.
*/
public class IlluminationModel {
/**
* Associates a LitArea stored in an Illuminator with the Light that it was created for.
*
* <p>This is used to represent normal lights, personal lights, and day light. In the case of
* daylight, lightInfo will be null since it doesn't originate from an actual light, and should
* never be rendered.
*
* @param litArea
* @param lightInfo
*/
public record ContributedLight(Illuminator.LitArea litArea, LightInfo lightInfo) {}

/**
* Combines a LightSource and a Light for easy referencing in ContributedLight.
*
* @param lightSource
* @param light
*/
public record LightInfo(LightSource lightSource, Light light) {}

/**
* The data structure for calculating lit areas according to lumens. Lit areas can be added and
* removed from this structure.
*/
private final Illuminator illuminator = new Illuminator();

/**
* The list of all non-personal lights contributing to the the illuminator.
*
* <p>This is used to associate the LitAreas added to the Illuminator with the original lighting
* parameters that created it. We can use this information to generate DrawableLights for
* rendering.
*/
private final Map<GUID, List<ContributedLight>> contributedLightsByToken = new HashMap<>();

public void removeToken(GUID tokenId) {
final var contributions =
Objects.requireNonNullElse(
contributedLightsByToken.remove(tokenId), Collections.<ContributedLight>emptyList());
// Remove each contribution from the illuminator as well.
for (final var contributedLight : contributions) {
illuminator.remove(contributedLight.litArea());
}
}

public boolean hasToken(GUID tokenId) {
return contributedLightsByToken.containsKey(tokenId);
}

public void addToken(GUID tokenId, List<ContributedLight> contributions) {
for (final var contribution : contributions) {
illuminator.add(contribution.litArea());
contributedLightsByToken.computeIfAbsent(tokenId, id -> new ArrayList<>()).add(contribution);
}
}

public Stream<ContributedLight> getContributions() {
return contributedLightsByToken.values().stream().flatMap(Collection::stream);
}

public Illumination getIllumination() {
return illuminator.getIllumination();
}
}
41 changes: 8 additions & 33 deletions src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,7 @@ public void centerOn(CellPoint point) {
/**
* Remove the token from: {@link #tokenLocationCache}, {@link #flipImageMap}, {@link
* #flipIsoImageMap}, {@link #labelRenderingCache}. Set the {@link #visibleScreenArea}, {@link
* #tokenStackMap}, {@link #drawableLights}, {@link #drawableAuras} to null. Flush the token from
* the zoneView.
* #tokenStackMap} to null. Flush the token from {@link #zoneView}.
*
* @param token the token to flush
*/
Expand All @@ -639,9 +638,6 @@ public void flush(Token token) {
// This could also be smarter
tokenStackMap = null;

drawableLights = null;
drawableAuras = null;

zoneView.flush(token);
}

Expand All @@ -668,20 +664,13 @@ public void flush() {
flushDrawableRenderer();
flipImageMap.clear();
flipIsoImageMap.clear();
drawableLights = null;
drawableAuras = null;
zoneView.flushFog();

isLoaded = false;
}

/**
* Set the {@link #drawableLights} and {@link #drawableAuras} to null, flush the zoneView, and
* repaint.
*/
/** Flush the {@link #zoneView} and repaint. */
public void flushLight() {
drawableLights = null;
drawableAuras = null;
zoneView.flush();
repaintDebouncer.dispatch();
}
Expand Down Expand Up @@ -1045,12 +1034,10 @@ public Rectangle zoneExtents(PlayerView view) {
}

/**
* This method clears {@link #drawableLights}, {@link #drawableAuras}, {@link #visibleScreenArea},
* and {@link #lastView}. It also flushes the {@link #zoneView}.
* This method clears {@link #visibleScreenArea} and {@link #lastView}. It also flushes the {@link
* #zoneView}.
*/
public void invalidateCurrentViewCache() {
drawableLights = null;
drawableAuras = null;
visibleScreenArea = null;
lastView = null;
}
Expand Down Expand Up @@ -1423,12 +1410,8 @@ private enum LightOverlayClipStyle {
private void renderLights(Graphics2D g, PlayerView view) {
// Collect and organize lights
timer.start("renderLights:getLights");
if (drawableLights == null) {
timer.start("renderLights:populateCache");
drawableLights = new ArrayList<>(zoneView.getDrawableLights(view));
timer.stop("renderLights:populateCache");
}
timer.start("renderLights:filterLights");
final var drawableLights = zoneView.getDrawableLights(view);
timer.stop("renderLights:getLights");

if (AppState.isShowLights()) {
// Lighting enabled.
Expand Down Expand Up @@ -1482,24 +1465,16 @@ private void renderLights(Graphics2D g, PlayerView view) {
}
}

/** Caches the lights to be drawn as returned ZoneView. */
private List<DrawableLight> drawableLights;
/** Holds the auras from lightSourceMap after they have been combined. */
private List<DrawableLight> drawableAuras;

/**
* Get the list of auras from lightSourceMap, combine them, store them in drawableAuras, and draw
* them.
* Render the auras.
*
* @param g the Graphics2D object.
* @param view the player view.
*/
private void renderAuras(Graphics2D g, PlayerView view) {
// Setup
timer.start("renderAuras:getAuras");
if (drawableAuras == null) {
drawableAuras = new ArrayList<>(zoneView.getDrawableAuras());
}
final var drawableAuras = zoneView.getDrawableAuras();
timer.stop("renderAuras:getAuras");

timer.start("renderAuras:renderAuraOverlay");
Expand Down
Loading

0 comments on commit 7c40324

Please sign in to comment.