Gridarta Editor
AbstractFlatMapRenderer.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.var.crossfire.gui.map.renderer;
21 
22 import java.awt.Color;
23 import java.awt.Dimension;
24 import java.awt.Graphics;
25 import java.awt.Point;
26 import java.awt.Rectangle;
27 import java.awt.image.BufferedImage;
28 import java.util.Collection;
29 import java.util.HashSet;
30 import java.util.Set;
44 import net.sf.gridarta.utils.Size2D;
49 import org.jetbrains.annotations.NotNull;
50 import org.jetbrains.annotations.Nullable;
51 
59 public abstract class AbstractFlatMapRenderer extends AbstractMapRenderer<GameObject, MapArchObject, Archetype> {
60 
64  private static final long serialVersionUID = 1L;
65 
71  @NotNull
72  private final Point borderOffset = new Point();
73 
78  @NotNull
80 
84  @NotNull
86 
91  @NotNull
92  private Size2D mapSize;
93 
97  @NotNull
98  private final MapGrid mapGrid;
99 
104  @NotNull
105  private final Point tmpPoint = new Point();
106 
110  @NotNull
112 
117  @NotNull
118  private final Rectangle tmpRec = new Rectangle();
119 
124  @NotNull
126 
127  @Override
128  public void gridVisibleChanged(final boolean gridVisible) {
129  forceRepaint();
130  }
131 
132  @Override
133  public void lightVisibleChanged(final boolean lightVisible) {
134  forceRepaint();
135  }
136 
137  @Override
138  public void smoothingChanged(final boolean smoothing) {
139  forceRepaint();
140  }
141 
142  @Override
143  public void tileStretchingChanged(final boolean tileStretching) {
144  // does not render tile-stretching
145  }
146 
147  @Override
148  public void doubleFacesChanged(final boolean doubleFaces) {
149  // does not render double faces
150  }
151 
152  @Override
153  public void alphaTypeChanged(final int alphaType) {
154  // does not render alpha types
155  }
156 
157  @Override
158  public void editTypeChanged(final int editType) {
159  // changed game objects will be rendered
160  }
161 
162  @Override
163  public void autojoinChanged(final boolean autojoin) {
164  // does not affect rendering
165  }
166 
167  };
168 
172  @NotNull
174 
175  @Override
176  public void mapSizeChanged(@NotNull final Size2D newSize) {
177  // ignore: will trigger an mapGridChanged() callback
178  }
179 
180  @Override
181  public void mapSquaresChanged(@NotNull final Set<MapSquare<GameObject, MapArchObject, Archetype>> mapSquares) {
182  final Collection<MapSquare<GameObject, MapArchObject, Archetype>> toRepaint = new HashSet<>();
183  for (final MapSquare<GameObject, MapArchObject, Archetype> mapSquare : mapSquares) {
184  getSquaresToRepaint(mapSquare, toRepaint);
185  }
186  for (final MapSquare<GameObject, MapArchObject, Archetype> mapSquare : toRepaint) {
187  paintSquare(mapSquare);
188  }
189  }
190 
191  @Override
192  public void mapObjectsChanged(@NotNull final Set<GameObject> gameObjects, @NotNull final Set<GameObject> transientGameObjects) {
193  final Collection<MapSquare<GameObject, MapArchObject, Archetype>> toRepaint = new HashSet<>();
194  addMapSquares(gameObjects, toRepaint);
195  addMapSquares(transientGameObjects, toRepaint);
196  for (final MapSquare<GameObject, MapArchObject, Archetype> mapSquare : toRepaint) {
197  paintSquare(mapSquare);
198  }
199  }
200 
207  private void addMapSquares(@NotNull final Iterable<GameObject> gameObjects, @NotNull final Collection<MapSquare<GameObject, MapArchObject, Archetype>> toRepaint) {
208  for (final net.sf.gridarta.model.gameobject.GameObject<GameObject, MapArchObject, Archetype> gameObject : gameObjects) {
209  if (!gameObject.isInContainer()) {
210  for (net.sf.gridarta.model.gameobject.GameObject<GameObject, MapArchObject, Archetype> gameObjectPart = gameObject; gameObjectPart != null; gameObjectPart = gameObjectPart.getMultiNext()) {
211  final MapSquare<GameObject, MapArchObject, Archetype> square = gameObjectPart.getMapSquare();
212  if (square != null) {
213  getSquaresToRepaint(square, toRepaint);
214  }
215  }
216  }
217  }
218  }
219 
226  private void getSquaresToRepaint(@NotNull final MapSquare<GameObject, MapArchObject, Archetype> mapSquare, @NotNull final Collection<MapSquare<GameObject, MapArchObject, Archetype>> toRepaint) {
227  if (mapViewSettings.isSmoothing()) {
228  final MapArchObject mapArchObject = mapModel.getMapArchObject();
229  final Point point = new Point();
230  for (int dx = -1; dx <= 1; dx++) {
231  for (int dy = -1; dy <= 1; dy++) {
232  mapSquare.getMapLocation(point, dx, dy);
233  if (mapArchObject.isPointValid(point)) {
234  toRepaint.add(mapModel.getMapSquare(point));
235  }
236  }
237  }
238  } else {
239  toRepaint.add(mapSquare);
240  }
241  }
242 
243  @Override
244  public void errorsChanged(@NotNull final ErrorCollector<GameObject, MapArchObject, Archetype> errors) {
245  // ignore
246  }
247 
248  @Override
249  public void mapFileChanged(@Nullable final MapFile oldMapFile) {
250  // ignore
251  }
252 
253  @Override
254  public void modifiedChanged() {
255  // ignore
256  }
257 
258  };
259 
263  @NotNull
265 
266  @Override
267  public void mapGridChanged(@NotNull final MapGridEvent e) {
268  final Rectangle recChange = mapGrid.getRecChange();
269  updateSquares(recChange);
270  repaint(0L, borderOffset.x + recChange.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + recChange.y * IGUIConstants.SQUARE_HEIGHT, recChange.width * IGUIConstants.SQUARE_WIDTH, recChange.height * IGUIConstants.SQUARE_HEIGHT);
271  }
272 
273  @Override
274  public void mapGridResized(@NotNull final MapGridEvent e) {
275  resizeMapGrid();
276  }
277 
278  };
279 
290  protected AbstractFlatMapRenderer(@NotNull final MapViewSettings mapViewSettings, @NotNull final MapModel<GameObject, MapArchObject, Archetype> mapModel, @NotNull final MapGrid mapGrid, final int borderSize, @NotNull final GridMapSquarePainter gridMapSquarePainter, @NotNull final GameObjectParser<GameObject, MapArchObject, Archetype> gameObjectParser) {
291  super(mapModel, gameObjectParser);
292  this.mapViewSettings = mapViewSettings;
293  this.mapModel = mapModel;
294  this.gridMapSquarePainter = gridMapSquarePainter;
295  mapSize = this.mapModel.getMapArchObject().getMapSize();
296  this.mapGrid = mapGrid;
297 
298  mapViewSettings.addMapViewSettingsListener(mapViewSettingsListener);
299 
300  setToolTipText("dummy");
301  setFocusable(true);
302  borderOffset.setLocation(borderSize, borderSize);
303  }
304 
308  protected void init() {
309  resizeMapGrid();
310  mapModel.addMapModelListener(mapModelListener);
311  mapGrid.addMapGridListener(mapGridListener);
312  }
313 
314  @Override
315  public void closeNotify() {
316  mapModel.removeMapModelListener(mapModelListener);
317  mapGrid.removeMapGridListener(mapGridListener);
318  mapViewSettings.removeMapViewSettingsListener(mapViewSettingsListener);
319  }
320 
321  @NotNull
322  @Override
323  public BufferedImage getFullImage() {
324  final int viewWidth = IGUIConstants.SQUARE_WIDTH * mapSize.getWidth();
325  final int viewHeight = IGUIConstants.SQUARE_HEIGHT * mapSize.getHeight();
326 
327  // first create a storing place for the image
328  final BufferedImage bufImage = new BufferedImage(viewWidth, viewHeight, BufferedImage.TYPE_INT_ARGB);
329  final Graphics graphics = bufImage.getGraphics();
330  try {
331  graphics.setColor(Color.white);
332  graphics.fillRect(0, 0, viewWidth, viewHeight);
333 
334  // paint the map view into the image
335  final Point storeOffset = new Point(borderOffset);
336  try {
337  borderOffset.setLocation(0, 0);
338  paintComponent(graphics, true, false);
339  } finally {
340  borderOffset.setLocation(storeOffset);
341  }
342  } finally {
343  graphics.dispose();
344  }
345  return bufImage;
346  }
347 
351  @Override
352  public abstract void paintComponent(@NotNull Graphics g);
353 
354  @Override
355  public void forceRepaint() {
356  updateAll();
357  repaint();
358  }
359 
360  @NotNull
361  @Override
362  public Rectangle getSquareBounds(@NotNull final Point p) {
363  tmpRec.x = borderOffset.x + p.x * IGUIConstants.SQUARE_WIDTH;
364  tmpRec.y = borderOffset.y + p.y * IGUIConstants.SQUARE_HEIGHT;
365  tmpRec.width = IGUIConstants.SQUARE_WIDTH;
366  tmpRec.height = IGUIConstants.SQUARE_HEIGHT;
367  return tmpRec;
368  }
369 
374  private void paintSquare(@NotNull final MapSquare<GameObject, MapArchObject, Archetype> square) {
375  final Point pos = square.getMapLocation();
376  updateSquare(pos);
377  repaint(0L, borderOffset.x + pos.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + pos.y * IGUIConstants.SQUARE_HEIGHT, IGUIConstants.SQUARE_WIDTH, IGUIConstants.SQUARE_HEIGHT);
378  }
379 
388  protected void paintComponent(@NotNull final Graphics graphics, final boolean isSnapshot, final boolean checkClip) {
389  graphics.setColor(getBackground());
390  graphics.fillRect(0, 0, getWidth(), getHeight());
391  paintMap(graphics, checkClip);
392  if (!isSnapshot) {
393  paintMapGrid(graphics);
394  paintMapSelection(graphics);
395  }
396  }
397 
404  protected void paintSquareGrid(@NotNull final Graphics graphics, @NotNull final Point point) {
405  if (mapViewSettings.isGridVisible()) {
406  graphics.drawLine(borderOffset.x + point.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + point.y * IGUIConstants.SQUARE_HEIGHT, borderOffset.x + point.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + point.y * IGUIConstants.SQUARE_HEIGHT + IGUIConstants.SQUARE_HEIGHT);
407  graphics.drawLine(borderOffset.x + point.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + point.y * IGUIConstants.SQUARE_HEIGHT, borderOffset.x + point.x * IGUIConstants.SQUARE_WIDTH + IGUIConstants.SQUARE_WIDTH, borderOffset.y + point.y * IGUIConstants.SQUARE_HEIGHT);
408  }
409  }
410 
416  protected void paintSquareSelection(@NotNull final Graphics graphics, @NotNull final Point point) {
417  final int gridFlags = mapGrid.getFlags(point.x, point.y);
418  final boolean light = (isLightVisible() ^ mapViewSettings.isLightVisible()) && mapModel.getMapSquare(point).isLight();
419  gridMapSquarePainter.paint(graphics, gridFlags, light, borderOffset.x + point.x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + point.y * IGUIConstants.SQUARE_HEIGHT, this);
420  }
421 
428  private void paintMap(@NotNull final Graphics graphics, final boolean checkClip) {
429  for (tmpPoint.y = 0; tmpPoint.y < mapGrid.getSize().getHeight(); tmpPoint.y++) {
430  final int y = borderOffset.y + tmpPoint.y * IGUIConstants.SQUARE_HEIGHT;
431  for (tmpPoint.x = 0; tmpPoint.x < mapGrid.getSize().getWidth(); tmpPoint.x++) {
432  final int x = borderOffset.x + tmpPoint.x * IGUIConstants.SQUARE_WIDTH;
433  if (!checkClip || graphics.hitClip(x, y, IGUIConstants.SQUARE_WIDTH, IGUIConstants.SQUARE_HEIGHT)) {
434  paintSquare(graphics, x, y, mapModel.getMapSquare(tmpPoint));
435  }
436  }
437  }
438  }
439 
446  private void paintMapSelection(@NotNull final Graphics graphics) {
447  for (tmpPoint.y = 0; tmpPoint.y < mapSize.getHeight(); tmpPoint.y++) {
448  final int y = borderOffset.y + tmpPoint.y * IGUIConstants.SQUARE_HEIGHT;
449  for (tmpPoint.x = 0; tmpPoint.x < mapSize.getWidth(); tmpPoint.x++) {
450  final int x = borderOffset.x + tmpPoint.x * IGUIConstants.SQUARE_WIDTH;
451  if (graphics.hitClip(x, y, IGUIConstants.SQUARE_WIDTH, IGUIConstants.SQUARE_HEIGHT)) {
452  paintSquareSelection(graphics, tmpPoint);
453  }
454  }
455  }
456  }
457 
464  private void paintMapGrid(@NotNull final Graphics graphics) {
465  if (mapViewSettings.isGridVisible()) {
466  final Size2D tmpMapSize = mapGrid.getSize();
467  final int mapWidth = tmpMapSize.getWidth();
468  final int mapHeight = tmpMapSize.getHeight();
469  for (int x = 0; x <= mapWidth; x++) {
470  graphics.drawLine(borderOffset.x + x * IGUIConstants.SQUARE_WIDTH, borderOffset.y, borderOffset.x + x * IGUIConstants.SQUARE_WIDTH, borderOffset.y + mapHeight * IGUIConstants.SQUARE_HEIGHT);
471  }
472  for (int y = 0; y <= mapHeight; y++) {
473  graphics.drawLine(borderOffset.x, borderOffset.y + y * IGUIConstants.SQUARE_HEIGHT, borderOffset.x + mapWidth * IGUIConstants.SQUARE_WIDTH, borderOffset.y + y * IGUIConstants.SQUARE_HEIGHT);
474  }
475  }
476  }
477 
478  @Override
479  public boolean getSquareLocationAt(@NotNull final Point point, @NotNull final Point retPoint) {
480  final int x = point.x - borderOffset.x;
481  final int y = point.y - borderOffset.y;
482  if (x < 0 || y < 0) {
483  return false;
484  }
485  final int xm = x / IGUIConstants.SQUARE_WIDTH;
486  final int ym = y / IGUIConstants.SQUARE_HEIGHT;
487  if (xm >= mapSize.getWidth() || ym >= mapSize.getHeight()) {
488  return false;
489  }
490 
491  retPoint.setLocation(xm, ym);
492  return true;
493  }
494 
500  protected abstract void resizeBackBuffer(@NotNull Dimension size);
501 
509  protected abstract void paintSquare(@NotNull Graphics g, int x, int y, @NotNull MapSquare<GameObject, MapArchObject, Archetype> square);
510 
514  private void resizeMapGrid() {
515  // define how much drawing space we need for the map
516  mapSize = mapGrid.getSize();
517  final Dimension forcedSize = new Dimension(mapSize.getWidth() * IGUIConstants.SQUARE_WIDTH + 2 * borderOffset.x, mapSize.getHeight() * IGUIConstants.SQUARE_HEIGHT + 2 * borderOffset.y);
518  resizeBackBuffer(forcedSize);
519  setPreferredSize(forcedSize);
520  setMinimumSize(forcedSize);
521  revalidate();
522  forceRepaint();
523  }
524 
529  protected abstract void updateSquare(@NotNull Point point);
530 
535  protected abstract void updateSquares(@NotNull Rectangle rectangle);
536 
540  protected abstract void updateAll();
541 
546  protected int getBorderOffsetX() {
547  return borderOffset.x;
548  }
549 
554  protected int getBorderOffsetY() {
555  return borderOffset.y;
556  }
557 
558 }
A MapModel reflects the data of a map.
Definition: MapModel.java:75
boolean isLight()
Returns whether this map square is affected by any light emitting game objects.
Definition: MapSquare.java:389
final MapViewSettingsListener mapViewSettingsListener
The MapViewSettingsListener attached to mapViewSettings.
Graphical User Interface of Gridarta.
Reading and writing of maps, handling of paths.
void paintSquareGrid(@NotNull final Graphics graphics, @NotNull final Point point)
Paints the grid for one square.
final MapModel< GameObject, MapArchObject, Archetype > mapModel
The MapModel to render.
This package contains the framework for validating maps.
int SQUARE_HEIGHT
The height of a square in pixels.
void resizeMapGrid()
Updates cached information to new map grid size.
void paintMap(@NotNull final Graphics graphics, final boolean checkClip)
Paints the whole map.
void paintSquareSelection(@NotNull final Graphics graphics, @NotNull final Point point)
Paints the selection for one square.
MapArchObject contains the specific meta data about a map that is stored in the map-arch, at the very beginning of the map file.
Handles the Crossfire variants of GameObjects and Archetypes.
Interface for listeners listening on MapModel events.
boolean lightVisible
Whether the setting for lighted map squares is inverted.
Interface for classes that read or write GameObject instances.
boolean getSquareLocationAt(@NotNull final Point point, @NotNull final Point retPoint)
Returns the map location at the given point.
abstract void paintComponent(@NotNull Graphics g)
AbstractMethodOverridesConcreteMethod
int getFlags(final int x, final int y)
Returns the flags of a square.
Definition: MapGrid.java:476
void forceRepaint()
Repaint the view because some view parameters may have changed.
void removeMapGridListener(@NotNull final MapGridListener listener)
Removes a MapGridListener.
Definition: MapGrid.java:198
boolean isLightVisible()
Get the visibility of the light.
void paintSquare(@NotNull final MapSquare< GameObject, MapArchObject, Archetype > square)
Paints one square.
void paintMapSelection(@NotNull final Graphics graphics)
Paints the selection for the whole map.
void addMapModelListener(@NotNull MapModelListener< G, A, R > listener)
Register a map listener.
Size2D getSize()
Returns size of grid.
Definition: MapGrid.java:504
boolean isSmoothing()
Returns the smoothing setting.
boolean isPointValid(@Nullable final Point pos)
Checks whether the given coordinate is within map bounds.
Base package of all Gridarta classes.
Abstract base class for classes implementing MapRenderer.
Reflects a game object (object on a map).
Definition: GameObject.java:36
Interface for listeners listening to MapGridEvents.
boolean isGridVisible()
Get the visibility of the grid.
abstract void resizeBackBuffer(@NotNull Dimension size)
Resizes the backing buffer to the new grid size.
void addMapGridListener(@NotNull final MapGridListener listener)
Registers a MapGridListener.
Definition: MapGrid.java:190
void paintComponent(@NotNull final Graphics graphics, final boolean isSnapshot, final boolean checkClip)
Paints this component.
AbstractFlatMapRenderer(@NotNull final MapViewSettings mapViewSettings, @NotNull final MapModel< GameObject, MapArchObject, Archetype > mapModel, @NotNull final MapGrid mapGrid, final int borderSize, @NotNull final GridMapSquarePainter gridMapSquarePainter, @NotNull final GameObjectParser< GameObject, MapArchObject, Archetype > gameObjectParser)
Creates a new instance.
Interface for event listeners that are interested in changes on MapViewSettings.
void removeMapViewSettingsListener(@NotNull MapViewSettingsListener listener)
Unregister a MapViewSettingsListener.
Rectangle getSquareBounds(@NotNull final Point p)
Returns coordinates, length and width of map square.
Container for settings that affect the rendering of maps.
final MapModelListener< GameObject, MapArchObject, Archetype > mapModelListener
The MapModelListener to track changes in mapModel.
MapSquare< G, A, R > getMapSquare(@NotNull Point pos)
Get the square at a specified location.
BufferedImage getFullImage()
Returns an image of the entire map view.
GameObjects are the objects based on Archetypes found on maps.
final MapViewSettings mapViewSettings
The MapViewSettings instance to use.
int getWidth()
Returns the width of the area.
Definition: Size2D.java:96
2D-Grid containing flags for selection, pre-selection, cursor, warnings and errors.
Definition: MapGrid.java:45
Defines common UI constants used in different dialogs and all used icon files.
void paint(@NotNull final Graphics graphics, final int gridFlags, final boolean light, final int x, final int y, @NotNull final ImageObserver imageObserver)
Paints overlay images for one grid square.
final MapGridListener mapGridListener
The MapGridListener to track changes in mapGrid.
final GameObjectParser< G, A, R > gameObjectParser
The GameObjectParser for creating tooltip information or.
Base classes for rendering maps.
Main package of Gridarta4Crossfire, contains all classes specific to the Crossfire version of the Gri...
void removeMapModelListener(@NotNull MapModelListener< G, A, R > listener)
Unregister a map listener.
abstract void updateSquare(@NotNull Point point)
Callback function that is called when a square may have changed.
abstract void updateAll()
Callback function that is called when any square may have changed.
A getMapArchObject()
Returns the Map Arch Object with the meta information about the map.
abstract void updateSquares(@NotNull Rectangle rectangle)
Callback function that is called when multiple squares may have changed.
boolean isLightVisible()
Returns whether the setting for lighted map squares should be inverted.
An interface for classes that collect errors.
int getHeight()
Returns the height of the area.
Definition: Size2D.java:104
final GridMapSquarePainter gridMapSquarePainter
The GridMapSquarePainter to use.
void paintMapGrid(@NotNull final Graphics graphics)
Paints the grid of the whole map.
Rectangle getRecChange()
Returns a rectangle where the grid was changed.
Definition: MapGrid.java:495
The location of a map file with a map directory.
Definition: MapFile.java:31
int SQUARE_WIDTH
The width of a square in pixels.
The class Size2D represents a 2d rectangular area.
Definition: Size2D.java:30
This event is created by MapGrid.