Gridarta Editor
SmoothingRenderer.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2023 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.Graphics;
23 import java.awt.Point;
24 import javax.swing.ImageIcon;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36 
42 public class SmoothingRenderer {
43 
44  private static final int @NotNull [] DX = { 1, 2, 2, 2, 1, 0, 0, 0, };
45 
46  private static final int @NotNull [] DY = { 0, 0, 1, 2, 2, 2, 1, 0, };
47 
48  private static final int @NotNull [] B_WEIGHTS = { 2, 0, 4, 0, 8, 0, 1, 0, };
49 
50  private static final int @NotNull [] C_WEIGHTS = { 0, 2, 0, 4, 0, 8, 0, 1, };
51 
52  private static final int @NotNull [] BC_EXCLUDE = { 1 + 2, /*north exclude northwest (bit0) and northeast(bit1)*/
53  0, 2 + 4, /*east exclude northeast and southeast*/
54  0, 4 + 8, /*and so on*/
55  0, 8 + 1, 0 };
56 
60  @NotNull
62 
66  @NotNull
67  private final SmoothFaces smoothFaces;
68 
72  @NotNull
74 
75  @Nullable
76  private final net.sf.gridarta.model.gameobject.GameObject<?, ?, ?> @NotNull [] @NotNull [] layerNode = new net.sf.gridarta.model.gameobject.GameObject<?, ?, ?>[3][3];
77 
78  private final int @NotNull [] sLevels = new int[8];
79 
80  @Nullable
81  private final FaceObject @NotNull [] sFaces = new FaceObject[8];
82 
91  this.mapModel = mapModel;
92  this.smoothFaces = smoothFaces;
93  this.faceObjectProviders = faceObjectProviders;
94  }
95 
110  public void paintSmooth(@NotNull final Graphics graphics, @NotNull final Point pos, final int level, final int firstLayer, final boolean allLayers, final int borderOffsetX, final int borderOffsetY) {
111  int layer = firstLayer;
112  while (true) {
113  final MapArchObject mapArchObject = mapModel.getMapArchObject();
114  boolean foundLayer = false;
115  final Point where = new Point();
116  for (int deltaX = -1; deltaX <= 1; deltaX++) {
117  where.x = pos.x + deltaX;
118  for (int deltaY = -1; deltaY <= 1; deltaY++) {
119  where.y = pos.y + deltaY;
120  //false warning: cannot annotate with @Nullable
121  //noinspection AssignmentToNull
122  layerNode[deltaX + 1][deltaY + 1] = null;
123  if (mapArchObject.isPointValid(where)) {
124  int currentLayer = -1;
125  for (final net.sf.gridarta.model.gameobject.GameObject<GameObject, MapArchObject, Archetype> node : mapModel.getMapSquare(where)) {
126  if (node.getAttributeInt(GameObject.INVISIBLE, true) == 0) {
127  currentLayer++;
128  if (currentLayer == layer) {
129  foundLayer = true;
130  if (node.getAttributeInt(GameObject.SMOOTHLEVEL, true) > 0) {
131  layerNode[deltaX + 1][deltaY + 1] = node;
132  }
133  break;
134  }
135  }
136  }
137  }
138  }
139  }
140 
141  /*surrounding nodes having smoothlevel >0 found*/
142  /*below is ripped and adapted from sdl client smooth renderer*/
143  for (int i = 0; i < 8; i++) {
144  final net.sf.gridarta.model.gameobject.GameObject<?, ?, ?> node = layerNode[DX[i]][DY[i]];
145  if (node == null) {
146  sLevels[i] = 0;
147  //false warning: cannot annotate with @Nullable
148  //noinspection AssignmentToNull
149  sFaces[i] = null; /*black picture*/
150  } else {
151  final int smoothlevel = node.getAttributeInt(GameObject.SMOOTHLEVEL, true);
152  if (smoothlevel <= level) {
153  sLevels[i] = 0;
154  //false warning: cannot annotate with @Nullable
155  //noinspection AssignmentToNull
156  sFaces[i] = null; /*black picture*/
157  } else {
158  sLevels[i] = smoothlevel;
159  sFaces[i] = smoothFaces.getSmoothFace(node);
160  }
161  }
162  }
163 
164  /* ok, now we have a list of smoothlevel higher than current square.
165  * there are at most 8 different levels. so... let's check 8 times
166  * for the lowest one (we draw from bottom to top!).
167  */
168  final boolean[] partDone = { false, false, false, false, false, false, false, false, };
169  while (true) {
170  int lowest = -1;
171  for (int i = 0; i < 8; i++) {
172  if (sLevels[i] > 0 && !partDone[i] && (lowest < 0 || sLevels[i] < sLevels[lowest])) {
173  lowest = i;
174  }
175  }
176  if (lowest < 0) {
177  /*no more smooth to do on this square*/
178  /*here we know 'what' to smooth*/
179  break;
180  }
181  final NamedObject smoothFace = sFaces[lowest];
182  /* we need to calculate the weight for border and weight for corners.
183  * then we 'mark done' the corresponding squares
184  */
185  /*first, the border, which may exclude some corners*/
186  int weight = 0;
187  int weightC = 15;
188  for (int i = 0; i < 8; i++) { /*check all nearby squares*/
189  if (sLevels[i] == sLevels[lowest] && sFaces[i] == smoothFace) {
190  partDone[i] = true;
191  weight += B_WEIGHTS[i];
192  weightC &= ~BC_EXCLUDE[i];
193  } else {
194  /*must remove the weight of a corner if not in smoothing*/
195  weightC &= ~C_WEIGHTS[i];
196  }
197  }
198  if (smoothFace == null) {
199  continue; /*Can't smooth black*/
200  }
201  /* now, it's quite easy. We must draw using a 32x32 part of
202  * the picture smooth face.
203  * This part is located using the 2 weights calculated:
204  * (32*weight,0) and (32*weightC,32)
205  */
206  final ImageIcon img = faceObjectProviders.getDisplayIcon(smoothFace);
207  if (weight > 0) {
208  drawImage(graphics, pos, borderOffsetX, borderOffsetY, IGUIConstants.SQUARE_WIDTH * weight, 0, img);
209  }
210  if (weightC > 0) {
211  drawImage(graphics, pos, borderOffsetX, borderOffsetY, IGUIConstants.SQUARE_WIDTH * weightC, IGUIConstants.SQUARE_HEIGHT, img);
212  }
213  } /*while there's some smooth to do*/
214 
215  if (!allLayers || !foundLayer) {
216  break;
217  }
218 
219  layer++;
220  }
221  }
222 
223  private void drawImage(@NotNull final Graphics graphics, @NotNull final Point pos, final int borderOffsetX, final int borderOffsetY, final int srcX, final int srcY, @NotNull final ImageIcon img) {
224  graphics.drawImage(img.getImage(), borderOffsetX + pos.x * IGUIConstants.SQUARE_WIDTH, borderOffsetY + pos.y * IGUIConstants.SQUARE_HEIGHT, borderOffsetX + pos.x * IGUIConstants.SQUARE_WIDTH + IGUIConstants.SQUARE_WIDTH, borderOffsetY + pos.y * IGUIConstants.SQUARE_HEIGHT + IGUIConstants.SQUARE_HEIGHT, srcX, srcY, srcX + IGUIConstants.SQUARE_WIDTH, srcY + IGUIConstants.SQUARE_HEIGHT, null);
225  }
226 
227 }
net.sf.gridarta.model.mapmodel.MapModel
A MapModel reflects the data of a map.
Definition: MapModel.java:75
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.mapModel
final MapModel< GameObject, MapArchObject, Archetype > mapModel
The MapModel to render.
Definition: SmoothingRenderer.java:61
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.C_WEIGHTS
static final int[] C_WEIGHTS
Definition: SmoothingRenderer.java:50
net.sf.gridarta.var.crossfire.model.archetype
Definition: Archetype.java:20
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.sLevels
final int[] sLevels
Definition: SmoothingRenderer.java:78
net.sf.gridarta.model.maparchobject.AbstractMapArchObject.isPointValid
boolean isPointValid(@Nullable final Point pos)
Definition: AbstractMapArchObject.java:598
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.B_WEIGHTS
static final int[] B_WEIGHTS
Definition: SmoothingRenderer.java:48
net.sf
net.sf.gridarta.model.mapmodel
Definition: AboveFloorInsertionMode.java:20
net.sf.gridarta.model.smoothface
Definition: DuplicateSmoothFaceException.java:20
net.sf.gridarta.model.face.FaceObjectProviders
Provider for faces of GameObjects and Archetypes.
Definition: FaceObjectProviders.java:46
net.sf.gridarta.model.gameobject.GameObject
Reflects a game object (object on a map).
Definition: GameObject.java:36
net.sf.gridarta.var
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.faceObjectProviders
final FaceObjectProviders faceObjectProviders
The FaceObjectProviders for looking up faces.
Definition: SmoothingRenderer.java:73
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.DX
static final int[] DX
Definition: SmoothingRenderer.java:44
net.sf.gridarta.model.data.NamedObject
An.
Definition: NamedObject.java:32
net.sf.gridarta.var.crossfire.IGUIConstants
Defines common UI constants used in different dialogs and all used icon files.
Definition: IGUIConstants.java:30
net.sf.gridarta.model.gameobject
GameObjects are the objects based on Archetypes found on maps.
Definition: AbstractGameObject.java:20
net
net.sf.gridarta.var.crossfire.model.archetype.Archetype
Implements Crossfire archetypes.
Definition: Archetype.java:30
net.sf.gridarta.var.crossfire.model.maparchobject.MapArchObject
MapArchObject contains the specific meta data about a map that is stored in the map-arch,...
Definition: MapArchObject.java:39
net.sf.gridarta.var.crossfire
Main package of Gridarta4Crossfire, contains all classes specific to the Crossfire version of the Gri...
net.sf.gridarta.var.crossfire.model
net.sf.gridarta.var.crossfire.IGUIConstants.SQUARE_WIDTH
int SQUARE_WIDTH
The width of a square in pixels.
Definition: IGUIConstants.java:35
net.sf.gridarta.model.data
Classes for handling data that is organized in a tree.
Definition: AbstractNamedObject.java:20
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.BC_EXCLUDE
static final int[] BC_EXCLUDE
Definition: SmoothingRenderer.java:52
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.paintSmooth
void paintSmooth(@NotNull final Graphics graphics, @NotNull final Point pos, final int level, final int firstLayer, final boolean allLayers, final int borderOffsetX, final int borderOffsetY)
Draw the smoothing information at given position of map, for a given limit smoothlevel,...
Definition: SmoothingRenderer.java:110
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.DY
static final int[] DY
Definition: SmoothingRenderer.java:46
net.sf.gridarta.var.crossfire.model.gameobject.GameObject.SMOOTHLEVEL
static final String SMOOTHLEVEL
The name of the "smoothlevel" attribute.
Definition: GameObject.java:70
net.sf.gridarta.var.crossfire.model.gameobject.GameObject.INVISIBLE
static final String INVISIBLE
The name of the "invisible" attribute.
Definition: GameObject.java:64
net.sf.gridarta.model.face.FaceObject
Common interface for FaceObject.
Definition: FaceObject.java:30
net.sf.gridarta.model
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.layerNode
final net.sf.gridarta.model.gameobject.GameObject<?, ?, ?>[][] layerNode
Definition: SmoothingRenderer.java:76
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer
Renderer for smoothed faces as used by Crossfire.
Definition: SmoothingRenderer.java:42
net.sf.gridarta.model.smoothface.SmoothFaces
Collection of all smoothing information.
Definition: SmoothFaces.java:37
net.sf.gridarta.var.crossfire.model.maparchobject
Definition: DefaultMapArchObjectFactory.java:20
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.SmoothingRenderer
SmoothingRenderer(@NotNull final MapModel< GameObject, MapArchObject, Archetype > mapModel, @NotNull final SmoothFaces smoothFaces, @NotNull final FaceObjectProviders faceObjectProviders)
Creates a new instance.
Definition: SmoothingRenderer.java:90
net.sf.gridarta.var.crossfire.model.gameobject
Handles the Crossfire variants of GameObjects and Archetypes.
Definition: DefaultGameObjectFactory.java:20
net.sf.gridarta.model.face
The face is the appearance of an object.
Definition: AbstractFaceObjects.java:20
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.drawImage
void drawImage(@NotNull final Graphics graphics, @NotNull final Point pos, final int borderOffsetX, final int borderOffsetY, final int srcX, final int srcY, @NotNull final ImageIcon img)
Definition: SmoothingRenderer.java:223
net.sf.gridarta.var.crossfire.model.gameobject.GameObject
Handles the Crossfire GameObjects.
Definition: GameObject.java:41
net.sf.gridarta.model.face.FaceObjectProviders.getDisplayIcon
ImageIcon getDisplayIcon(@NotNull final NamedObject namedObject)
Returns the display icon for a NamedObject.
Definition: FaceObjectProviders.java:377
net.sf.gridarta.model.smoothface.SmoothFaces.getSmoothFace
FaceObject getSmoothFace(@NotNull final GameObject<?, ?, ?> gameObject)
Returns the smooth faces for a GameObject.
Definition: SmoothFaces.java:84
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.smoothFaces
final SmoothFaces smoothFaces
The SmoothFaces to use.
Definition: SmoothingRenderer.java:67
net.sf.gridarta.var.crossfire.gui.map.renderer.SmoothingRenderer.sFaces
final FaceObject[] sFaces
Definition: SmoothingRenderer.java:81
net.sf.gridarta.var.crossfire.IGUIConstants.SQUARE_HEIGHT
int SQUARE_HEIGHT
The height of a square in pixels.
Definition: IGUIConstants.java:40