00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.gui.map;
00023
00024 import com.realtime.crossfire.jxclient.faces.Face;
00025 import com.realtime.crossfire.jxclient.faces.FacesProvider;
00026 import com.realtime.crossfire.jxclient.faces.SmoothFaces;
00027 import com.realtime.crossfire.jxclient.map.CfMap;
00028 import com.realtime.crossfire.jxclient.map.CfMapSquare;
00029 import java.awt.Graphics;
00030 import java.util.Arrays;
00031 import javax.swing.ImageIcon;
00032 import org.jetbrains.annotations.NotNull;
00033
00039 public class SmoothingRenderer {
00040
00044 private static final int BORDER_WEST = 1;
00045
00049 private static final int BORDER_NORTH = 2;
00050
00054 private static final int BORDER_EAST = 4;
00055
00059 private static final int BORDER_SOUTH = 8;
00060
00064 private static final int CORNER_NORTHWEST = 1;
00065
00069 private static final int CORNER_NORTHEAST = 2;
00070
00074 private static final int CORNER_SOUTHEAST = 4;
00075
00079 private static final int CORNER_SOUTHWEST = 8;
00080
00084 @NotNull
00085 private static final int[] DX = {
00086 1,
00087 2,
00088 2,
00089 2,
00090 1,
00091 0,
00092 0,
00093 0,
00094 };
00095
00099 @NotNull
00100 private static final int[] DY = {
00101 0,
00102 0,
00103 1,
00104 2,
00105 2,
00106 2,
00107 1,
00108 0,
00109 };
00110
00115 @NotNull
00116 private static final int[] BORDER_WEIGHT = {
00117 BORDER_NORTH,
00118 0,
00119 BORDER_EAST,
00120 0,
00121 BORDER_SOUTH,
00122 0,
00123 BORDER_WEST,
00124 0,
00125 };
00126
00131 @NotNull
00132 private static final int[] CORNER_WEIGHT = {
00133 0,
00134 CORNER_NORTHEAST,
00135 0,
00136 CORNER_SOUTHEAST,
00137 0,
00138 CORNER_SOUTHWEST,
00139 0,
00140 CORNER_NORTHWEST,
00141 };
00142
00146 @NotNull
00147 private static final int[] BORDER_CORNER_EXCLUDE = {
00148 CORNER_NORTHWEST+CORNER_NORTHEAST,
00149 0,
00150 CORNER_NORTHEAST+CORNER_SOUTHEAST,
00151 0,
00152 CORNER_SOUTHEAST+CORNER_SOUTHWEST,
00153 0,
00154 CORNER_SOUTHWEST+CORNER_NORTHWEST,
00155 0
00156 };
00157
00161 @NotNull
00162 private final SmoothFaces smoothFaces;
00163
00167 @NotNull
00168 private final FacesProvider facesProvider;
00169
00174 @NotNull
00175 private final CfMapSquare[][] layerNode = new CfMapSquare[3][3];
00176
00181 @NotNull
00182 private final int[] smoothValue = new int[8];
00183
00188 @NotNull
00189 private final int[] smoothFace = new int[8];
00190
00194 @NotNull
00195 private final boolean[] done = new boolean[8];
00196
00200 @NotNull
00201 private final boolean[] isUnknownImage = new boolean[1];
00202
00208 protected SmoothingRenderer(@NotNull final SmoothFaces smoothFaces, @NotNull final FacesProvider facesProvider) {
00209 this.smoothFaces = smoothFaces;
00210 this.facesProvider = facesProvider;
00211 }
00212
00226 public void paintSmooth(@NotNull final Graphics graphics, final int x, final int y, final int px, final int py, final int layer, @NotNull final CfMap map, final int tileSize) {
00227 final int level = map.getSmooth(x, y, layer);
00228 if (level <= 0) {
00229 return;
00230 }
00231 for (int deltaX = 0; deltaX <= 2; deltaX++) {
00232 for (int deltaY = 0; deltaY <= 2; deltaY++) {
00233 if (deltaX != 0 || deltaY != 0) {
00234 final CfMapSquare mapSquare = map.getMapSquare(x+deltaX-1, y+deltaY-1);
00235
00236
00237 layerNode[deltaX][deltaY] = mapSquare.getSmooth(layer) > 0 ? mapSquare : null;
00238 }
00239 }
00240 }
00241
00242 for (int i = 0; i < 8; i++) {
00243 final CfMapSquare node = layerNode[DX[i]][DY[i]];
00244 if (node == null) {
00245 smoothValue[i] = 0;
00246 smoothFace[i] = 0;
00247 } else {
00248 final int smoothlevel = node.getSmooth(layer);
00249 if (smoothlevel <= level) {
00250 smoothValue[i] = 0;
00251 smoothFace[i] = 0;
00252 } else {
00253 smoothValue[i] = smoothlevel;
00254 final Face nodeFace = node.getFace(layer);
00255 smoothFace[i] = nodeFace == null ? 0 : smoothFaces.getSmoothFace(nodeFace.getFaceNum());
00256 }
00257 }
00258 }
00259
00260
00261
00262
00263 Arrays.fill(done, false);
00264 while (true) {
00265 int lowest = -1;
00266 for (int i = 0; i < 8; i++) {
00267 if (smoothValue[i] > 0 && !done[i] && (lowest < 0 || smoothValue[i] < smoothValue[lowest])) {
00268 lowest = i;
00269 }
00270 }
00271 if (lowest < 0) {
00272
00273
00274 break;
00275 }
00276 final int currentSmoothFace = smoothFace[lowest];
00277
00278
00279
00280 int weight = 0;
00281 int weightC = 15;
00282 for (int i = 0; i < 8; i++) {
00283 if (smoothValue[i] == smoothValue[lowest] && smoothFace[i] == currentSmoothFace) {
00284 done[i] = true;
00285 weight += BORDER_WEIGHT[i];
00286 weightC &= ~BORDER_CORNER_EXCLUDE[i];
00287 } else {
00288 weightC &= ~CORNER_WEIGHT[i];
00289 }
00290 }
00291 if (currentSmoothFace == 0) {
00292 continue;
00293 }
00294
00295 final ImageIcon imageIcon = facesProvider.getImageIcon(currentSmoothFace, isUnknownImage);
00296 if (isUnknownImage[0]) {
00297 map.squarePendingFace(x, y, currentSmoothFace);
00298 } else {
00299 if (weight > 0) {
00300 drawImage(graphics, px, py, tileSize*weight, 0, imageIcon, tileSize);
00301 }
00302 if (weightC > 0) {
00303 drawImage(graphics, px, py, tileSize*weightC, tileSize, imageIcon, tileSize);
00304 }
00305 }
00306 }
00307 }
00308
00320 private static void drawImage(@NotNull final Graphics graphics, final int dstX, final int dstY, final int srcX, final int srcY, @NotNull final ImageIcon imageIcon, final int tileSize) {
00321 graphics.drawImage(imageIcon.getImage(), dstX, dstY, dstX+tileSize, dstY+tileSize, srcX, srcY, srcX+tileSize, srcY+tileSize, null);
00322 }
00323
00324 }