Skip to content

Commit 842f478

Browse files
authored
Merge pull request #5978 from kwvanderlinde/feature/5977-marker-portrait-without-player-notes
Show marker portraits without requiring player notes
2 parents 8cba72b + 75f432b commit 842f478

6 files changed

Lines changed: 115 additions & 64 deletions

File tree

src/main/java/net/rptools/maptool/client/tool/PointerTool.java

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import net.rptools.lib.AwtUtil;
3939
import net.rptools.lib.CodeTimer;
4040
import net.rptools.lib.MD5Key;
41-
import net.rptools.lib.StringUtil;
4241
import net.rptools.maptool.client.*;
4342
import net.rptools.maptool.client.events.TokenHoverEnter;
4443
import net.rptools.maptool.client.events.TokenHoverExit;
@@ -49,6 +48,7 @@
4948
import net.rptools.maptool.client.ui.theme.Images;
5049
import net.rptools.maptool.client.ui.theme.RessourceManager;
5150
import net.rptools.maptool.client.ui.zone.FogUtil;
51+
import net.rptools.maptool.client.ui.zone.Marker;
5252
import net.rptools.maptool.client.ui.zone.PlayerView;
5353
import net.rptools.maptool.client.ui.zone.renderer.ZoneRenderer;
5454
import net.rptools.maptool.events.MapToolEventBus;
@@ -88,7 +88,7 @@ public class PointerTool extends DefaultTool {
8888
private boolean mouseButtonDown = false;
8989

9090
private Token tokenUnderMouse;
91-
private Token markerUnderMouse;
91+
private Marker markerUnderMouse;
9292
private int keysDown; // used to record whether Shift/Ctrl/Meta keys are down
9393

9494
private final TokenStackPanel tokenStackPanel = new TokenStackPanel();
@@ -400,7 +400,7 @@ public void mousePressed(MouseEvent e) {
400400
if (isShowingHover) {
401401
isShowingHover = false;
402402
hoverTokenNotes = null;
403-
markerUnderMouse = renderer.getMarkerAt(e.getX(), e.getY());
403+
markerUnderMouse = renderer.getViewModel().getMarkerAt(e.getX(), e.getY());
404404
repaint();
405405
}
406406
if (isShowingTokenStackPopup) {
@@ -668,14 +668,11 @@ public void mouseMoved(MouseEvent e) {
668668
SwingUtil.isShiftDown(keysDown),
669669
SwingUtil.isControlDown(keysDown)));
670670
}
671-
Token marker = renderer.getMarkerAt(mouseX, mouseY);
672-
if (!AppUtil.tokenIsVisible(renderer.getZone(), marker, renderer.getPlayerView())) {
673-
marker = null;
674-
}
671+
Marker marker = renderer.getViewModel().getMarkerAt(mouseX, mouseY);
675672
if (marker != markerUnderMouse && marker != null) {
676673
markerUnderMouse = marker;
677674
renderer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
678-
MapTool.getFrame().setStatusMessage(markerUnderMouse.getName());
675+
MapTool.getFrame().setStatusMessage(markerUnderMouse.name());
679676
} else if (marker == null && markerUnderMouse != null) {
680677
markerUnderMouse = null;
681678
renderer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
@@ -1678,42 +1675,36 @@ && new StatSheetManager().isLegacyStatSheet(tokenUnderMouse.getStatSheet())) {
16781675
}
16791676
}
16801677

1681-
private String createHoverNote(Token marker) {
1682-
var notes = HTMLUtil.htmlize(marker.getNotes(), marker.getNotesType());
1683-
var gmNotes = HTMLUtil.htmlize(marker.getGMNotes(), marker.getGmNotesType());
1684-
1685-
boolean showGMNotes = MapTool.getPlayer().isGM() && !StringUtil.isEmpty(gmNotes);
1686-
boolean showNotes = !StringUtil.isEmpty(notes);
1678+
private String createHoverNote(Marker marker) {
1679+
boolean showGMNotes = marker.gmNotes() != null;
1680+
boolean showNotes = marker.playerNotes() != null;
16871681

16881682
StringBuilder builder = new StringBuilder();
16891683

1690-
if (marker.getPortraitImage() != null) {
1684+
if (marker.imageKey() != null) {
16911685
builder.append("<table><tr><td valign=top>");
16921686
}
16931687
if (showGMNotes || showNotes) {
1694-
builder.append("<b><span class='title'>").append(marker.getName());
1695-
if (MapTool.getPlayer().isGM()
1696-
&& !StringUtil.isEmpty(marker.getGMName())
1697-
&& !marker.getName().equals(marker.getGMName())) {
1698-
builder.append(" (").append(marker.getGMName()).append(")");
1688+
builder.append("<b><span class='title'>").append(marker.name());
1689+
if (marker.gmName() != null && !marker.name().equals(marker.gmName())) {
1690+
builder.append(" (").append(marker.gmName()).append(")");
16991691
}
17001692
builder.append("</span></b><br>");
17011693
}
1694+
17021695
if (showNotes) {
1703-
builder.append(notes);
1704-
// add a gap between player and gmNotes
1705-
if (showGMNotes) {
1706-
builder.append("<br><br>");
1707-
}
1696+
builder.append(
1697+
HTMLUtil.htmlize(marker.playerNotes().note(), marker.playerNotes().mimeType()));
17081698
}
17091699
if (showGMNotes) {
17101700
if (showNotes) {
1711-
builder.append("<b><span class='title'>GM Notes</span></b><br>");
1701+
// add a gap and heading between player and gmNotes
1702+
builder.append("<br><br><b><span class='title'>GM Notes</span></b><br>");
17121703
}
1713-
builder.append(gmNotes);
1704+
builder.append(HTMLUtil.htmlize(marker.gmNotes().note(), marker.gmNotes().mimeType()));
17141705
}
1715-
if (marker.getPortraitImage() != null) {
1716-
BufferedImage image = ImageManager.getImageAndWait(marker.getPortraitImage());
1706+
if (marker.imageKey() != null) {
1707+
BufferedImage image = ImageManager.getImageAndWait(marker.imageKey());
17171708
Dimension imgSize = new Dimension(image.getWidth(), image.getHeight());
17181709
if (imgSize.width > AppConstants.NOTE_PORTRAIT_SIZE
17191710
|| imgSize.height > AppConstants.NOTE_PORTRAIT_SIZE) {
@@ -1722,15 +1713,14 @@ private String createHoverNote(Token marker) {
17221713
builder.append("</td><td valign=top>");
17231714
builder
17241715
.append("<img src='asset://")
1725-
.append(marker.getPortraitImage())
1716+
.append(marker.imageKey())
17261717
.append("' width=")
17271718
.append(imgSize.width)
17281719
.append(" height=")
17291720
.append(imgSize.height)
17301721
.append("></tr></table>");
17311722
}
1732-
String hoverText = builder.toString();
1733-
return hoverText;
1723+
return builder.toString();
17341724
}
17351725

17361726
private static final class TokenDragOp {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* This software Copyright by the RPTools.net development team, and
3+
* licensed under the Affero GPL Version 3 or, at your option, any later
4+
* version.
5+
*
6+
* MapTool Source Code is distributed in the hope that it will be
7+
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9+
*
10+
* You should have received a copy of the GNU Affero General Public
11+
* License * along with this source Code. If not, please visit
12+
* <http://www.gnu.org/licenses/> and specifically the Affero license
13+
* text at <http://www.gnu.org/licenses/agpl.html>.
14+
*/
15+
package net.rptools.maptool.client.ui.zone;
16+
17+
import java.awt.geom.Area;
18+
import javax.annotation.Nullable;
19+
import net.rptools.lib.MD5Key;
20+
21+
public record Marker(
22+
Area bounds,
23+
String name,
24+
@Nullable String gmName,
25+
@Nullable Notes playerNotes,
26+
@Nullable Notes gmNotes,
27+
@Nullable MD5Key imageKey) {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* This software Copyright by the RPTools.net development team, and
3+
* licensed under the Affero GPL Version 3 or, at your option, any later
4+
* version.
5+
*
6+
* MapTool Source Code is distributed in the hope that it will be
7+
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8+
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9+
*
10+
* You should have received a copy of the GNU Affero General Public
11+
* License * along with this source Code. If not, please visit
12+
* <http://www.gnu.org/licenses/> and specifically the Affero license
13+
* text at <http://www.gnu.org/licenses/agpl.html>.
14+
*/
15+
package net.rptools.maptool.client.ui.zone;
16+
17+
public record Notes(String note, String mimeType) {}

src/main/java/net/rptools/maptool/client/ui/zone/ZoneViewModel.java

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public static TokenPosition fromToken(Token token, Zone zone) {
118118
private final Map<Zone.Layer, List<TokenPosition>> tokenPositionsByLayer =
119119
CollectionUtil.newFilledEnumMap(Zone.Layer.class, l -> new LinkedList<>());
120120

121-
private final List<TokenPosition> markerList = new ArrayList<>();
121+
private final List<Marker> markerList = new ArrayList<>();
122122
private final Map<Token, Set<Token>> tokenStackMap = new HashMap<>();
123123

124124
private final Map<Zone.Layer, Set<GUID>> visibleTokensByLayer =
@@ -229,8 +229,14 @@ public List<TokenPosition> getTokenPositionsForLayer(Zone.Layer layer) {
229229
tokenPositionsByLayer.getOrDefault(layer, Collections.emptyList()));
230230
}
231231

232-
public List<TokenPosition> getMarkerPositions() {
233-
return Collections.unmodifiableList(markerList);
232+
public @Nullable Marker getMarkerAt(int x, int y) {
233+
var zonePoint = zoneScale.toWorldSpace(x, y);
234+
for (var marker : markerList.reversed()) {
235+
if (marker.bounds().contains(zonePoint)) {
236+
return marker;
237+
}
238+
}
239+
return null;
234240
}
235241

236242
public Map<Token, Set<Token>> getTokenStackMap() {
@@ -277,7 +283,7 @@ public void update() {
277283
updateVisibleArea();
278284
updateMovingTokens();
279285
updateTokenPositions();
280-
updateMarkerPositions();
286+
updateMarkerList();
281287
updateTokenStacks();
282288
updateVisibleTokens();
283289
updateLightPosition();
@@ -397,17 +403,48 @@ private void updateTokenPositions() {
397403
}
398404
}
399405

400-
/** Updates {@link #markerList} based on {@link #tokenPositionsByLayer}. */
401-
private void updateMarkerPositions() {
406+
/**
407+
* Updates {@link #markerList} based on {@link #playerView}, {@link #tokenPositionsByLayer}, and
408+
* {@link #visibleTokensByLayer}
409+
*/
410+
private void updateMarkerList() {
411+
var isGM = playerView.isGMView();
412+
402413
markerList.clear();
403414

404-
for (var list : tokenPositionsByLayer.values()) {
405-
for (var tokenPosition : list) {
415+
for (var entry : tokenPositionsByLayer.entrySet()) {
416+
var layer = entry.getKey();
417+
if (!layer.isMarkerLayer()) {
418+
// No markers in this layer, so don't bother iterating over them.
419+
continue;
420+
}
421+
422+
for (var tokenPosition : entry.getValue()) {
406423
var token = tokenPosition.token();
407-
var playerCanSeeMarker =
408-
MapTool.getPlayer().isGM() || !StringUtil.isEmpty(token.getNotes());
409-
if (tokenPosition.token().isMarker() && playerCanSeeMarker) {
410-
markerList.add(tokenPosition);
424+
if (!visibleTokensByLayer.get(layer).contains(token.getId())) {
425+
// No value in storing markers the player can't see.
426+
continue;
427+
}
428+
429+
var marker =
430+
new Marker(
431+
tokenPosition.transformedBounds(),
432+
token.getName(),
433+
isGM && !StringUtil.isEmpty(token.getGMName()) ? token.getGMName() : null,
434+
StringUtil.isEmpty(token.getNotes())
435+
? null
436+
: new Notes(token.getNotes(), token.getNotesType()),
437+
StringUtil.isEmpty(token.getGMNotes()) || !isGM
438+
? null
439+
: new Notes(token.getGMNotes(), token.getGmNotesType()),
440+
token.getPortraitImage());
441+
442+
// A GM sees a marker if it has any notes or a portrait.
443+
// A player sees a marker only if it has player notes.
444+
if (marker.playerNotes() != null
445+
|| marker.imageKey() != null
446+
|| (isGM && marker.gmNotes() != null)) {
447+
markerList.add(marker);
411448
}
412449
}
413450
}

src/main/java/net/rptools/maptool/client/ui/zone/renderer/ZoneRenderer.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,20 +2162,6 @@ public Rectangle getLabelBounds(Label label) {
21622162
return null;
21632163
}
21642164

2165-
public @Nullable Token getMarkerAt(int x, int y) {
2166-
var zonePoint = viewModel.getZoneScale().toWorldSpace(x, y);
2167-
2168-
List<ZoneViewModel.TokenPosition> positionList =
2169-
new ArrayList<>(viewModel.getMarkerPositions());
2170-
Collections.reverse(positionList);
2171-
for (ZoneViewModel.TokenPosition position : positionList) {
2172-
if (position.transformedBounds().contains(zonePoint)) {
2173-
return position.token();
2174-
}
2175-
}
2176-
return null;
2177-
}
2178-
21792165
public List<Token> getTokenStackAt(int x, int y) {
21802166
var tokenStackMap = viewModel.getTokenStackMap();
21812167

src/main/java/net/rptools/maptool/model/Token.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import javax.swing.ImageIcon;
4444
import net.rptools.CaseInsensitiveHashMap;
4545
import net.rptools.lib.MD5Key;
46-
import net.rptools.lib.StringUtil;
4746
import net.rptools.lib.image.ImageUtil;
4847
import net.rptools.lib.transferable.TokenTransferData;
4948
import net.rptools.maptool.client.AppUtil;
@@ -613,11 +612,6 @@ public int getHeight() {
613612
}
614613
}
615614

616-
public boolean isMarker() {
617-
return getLayer().isMarkerLayer()
618-
&& (!StringUtil.isEmpty(notes) || !StringUtil.isEmpty(gmNotes) || portraitImage != null);
619-
}
620-
621615
public String getPropertyType() {
622616
return propertyType;
623617
}

0 commit comments

Comments
 (0)