package com.wing.game.mapeditor.draw;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.wing.game.mapeditor.dialog.PropertyData;
import com.wing.game.mapeditor.dialog.PropertyDialog;
import com.wing.game.mapeditor.dialog.PropertyDialog.OnPropertyDialogActionListener;
import com.wing.game.mapeditor.layer.MapTile;
import com.wing.game.mapeditor.layer.TiledMapLayer;
import com.wing.game.mapeditor.property.AltasResourceManager;
import com.wing.game.mapeditor.property.TileProperty;
import com.wing.game.mapeditor.property.AltasResourceManager.AltasResource;
import com.wing.game.mapeditor.property.TiledMap;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.ObservableList;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TitledPane;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
public class MapCanvas extends Canvas {
private GraphicsContext gContext2D;
private double tileWidth, tileHeight;
private AltasResource nowAltasResource;
private List<TiledMapLayer> mapLayerList = new ArrayList<TiledMapLayer>();
private SimpleListProperty<Integer> nowChooseProperty = new SimpleListProperty<>();
private SimpleIntegerProperty nowSelectLayerProperty = new SimpleIntegerProperty(-1);
private SimpleIntegerProperty brushTypeProperty = new SimpleIntegerProperty(0);
private SimpleBooleanProperty showGridProperty = new SimpleBooleanProperty(true);
private SimpleDoubleProperty scaleProperty = new SimpleDoubleProperty(1.0);
private int mouseCols = 0, mouseRows = 0;
private int nowPropertyCols = 0, nowPropertyRows = 0;
private double mouseX, mouseY;
private boolean isDrawAltasList = true;
private static final int rectIndex = -100;
private PropertyDialog mPropertyDialog = new PropertyDialog();
public MapCanvas(double width, double height) {
super(width, height);
init();
}
public MapCanvas() {
this(0, 0);
}
private void init() {
mPropertyDialog.setOnPropertyDialogActionListener(new OnPropertyDialogActionListener() {
@Override
public void onDeletePropertyAction() {
}
@Override
public void onAddPropertyAction() {
}
@Override
public void onOkDialogAction(ObservableList<PropertyData> propertyDatas) {
// 获取指定行列的属性
TileProperty nowProperty = TiledMap.getInstance().getProperty(nowPropertyCols, nowPropertyRows);
if (propertyDatas.size() > 0) {
// 如果没有则创建一个
if (nowProperty == null) {
nowProperty = new TileProperty();
nowProperty.setRow(nowPropertyRows);
nowProperty.setCol(nowPropertyCols);
TiledMap.getInstance().getPropertyList().add(nowProperty);
}
// 清空属性
nowProperty.getValueMap().clear();
// 将键值对属性存入
for (PropertyData data : propertyDatas) {
nowProperty.insertValue(data.getKey(), data.getValue());
}
} else {
TiledMap.getInstance().getPropertyList().remove(nowProperty);
}
}
@Override
public void onInit(ObservableList<PropertyData> propertyDatas, TitledPane mTitledPane) {
System.out.println(nowPropertyCols + "," + nowPropertyRows);
// 获取指定行列的属性
TileProperty nowProperty = TiledMap.getInstance().getProperty(nowPropertyCols, nowPropertyRows);
propertyDatas.clear();
mTitledPane.setText("属性列表:" + nowPropertyCols + "," + nowPropertyRows);
// 如果没有则创建一个
if (nowProperty != null) {
Iterator<String> iterator = nowProperty.getValueMap().keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = nowProperty.getValueMap().get(key);
propertyDatas.add(new PropertyData(key, value));
}
}
}
});
final ContextMenu contextMenu = new ContextMenu();
MenuItem propertyItem = new MenuItem("属性");
propertyItem.setOnAction(e -> {
mPropertyDialog.showDialog();
});
contextMenu.getItems().add(propertyItem);
gContext2D = getGraphicsContext2D();
setOnMouseClicked(e -> {
if (e.getButton() == MouseButton.PRIMARY) {
fillTheMap(e);
}
if (e.getButton() == MouseButton.SECONDARY) {
nowPropertyCols = (int) (e.getX() / (tileWidth * getScale()));
nowPropertyRows = (int) (e.getY() / (tileHeight * getScale()));
contextMenu.show(MapCanvas.this, e.getScreenX(), e.getScreenY());
}
});
setOnMouseDragged(e -> {
fillTheMap(e);
isDrawAltasList = false;
});
setOnMouseReleased(e -> {
isDrawAltasList = true;
});
setOnMouseMoved(e -> {
mouseCols = (int) (e.getX() / (tileWidth * getScale()));
mouseRows = (int) (e.getY() / (tileHeight * getScale()));
mouseX = e.getX();
mouseY = e.getY();
});
setOnMouseEntered(e -> {
isDrawAltasList = true;
});
setOnMouseExited(e -> {
isDrawAltasList = false;
});
setWidth(TiledMap.getInstance().getRealTileMapWidth());
setHeight(TiledMap.getInstance().getRealTileMapHeight());
}
private void fillTheMap(MouseEvent e) {
switch (getBrushType()) {
case 0:
if (getNowSelectLayer() >= 0) {
fillTheMap(e.getX(), e.getY());
}
break;
case 1:
brushAllMap();
break;
case 2:
if (getNowSelectLayer() >= 0) {
eraserTheMap(e.getX(), e.getY());
}
break;
case 3:
fillTheMap(e.getX(), e.getY(), rectIndex);
break;
}
}
private void brushAllMap() {
if (getNowSelectLayer() >= 0 && getNowSelectLayer() < mapLayerList.size()) {
TiledMapLayer layer = mapLayerList.get(getNowSelectLayer());
MapTile[][] tiles = layer.getMapTiles();
if (tiles != null) {
for (int y = 0; y < tiles.length; y++) {
for (int x = 0; x < tiles[0].length; x++) {
MapTile mapTile = new MapTile();
mapTile.setAltasIndex(nowChooseProperty.get(0));
mapTile.setAltasId(nowAltasResource.getAltasId());
layer.setMapTile(x, y, mapTile);
}
}
}
}
}
private void fillTheMap(double x, double y) {
int cols = (int) (x / (tileWidth * getScale()));
int rows = (int) (y / (tileHeight * getScale()));
if (getNowSelectLayer() >= 0 && getNowSelectLayer() < mapLayerList.size()) {
TiledMapLayer layer = mapLayerList.get(getNowSelectLayer());
for (int i = 0; i < nowChooseProperty.getSize(); i++) {
int index = nowChooseProperty.get(i);
Image image = nowAltasResource.getImage();
if (index != -1) {
int cellX = (int) (image.getWidth() / tileWidth);
int col = index % cellX;
int row = index / cellX;
int startCol = nowChooseProperty.get(0) % cellX;
int startRow = nowChooseProperty.get(0) / cellX;
MapTile mapTile = new MapTile();
mapTile.setAltasIndex(index);
mapTile.setAltasId(nowAltasResource.getAltasId());
layer.setMapTile(cols + col - startCol, rows + row - startRow, mapTile);
}
}
}
}
private void fillTheMap(double x, double y, int index) {
int cols = (int) (x / (tileWidth * getScale()));
int rows = (int) (y / (tileHeight * getScale()));
if (getNowSelectLayer() >= 0 && getNowSelectLayer() < mapLayerList.size()) {
TiledMapLayer layer = mapLayerList.get(getNowSelectLayer());
if (index != -1) {
MapTile mapTile = new MapTile();
mapTile.setAltasIndex(index);
mapTile.setAltasId("");
layer.setMapTile(cols, rows, mapTile);
}
}
}
private void eraserTheMap(double x, double y) {
int cols = (int) (x / (tileWidth * getScale()));
int rows = (int) (y / (tileHeight * getScale()));
if (getNowSelectLayer() >= 0 && getNowSelectLayer() < mapLayerList.size()) {
TiledMapLayer layer = mapLayerList.get(getNowSelectLayer());
MapTile mapTile = new MapTile();
mapTile.setAltasIndex(-1);
mapTile.setAltasId(null);
layer.setMapTile(cols, rows, mapTile);
System.out.println(cols + "," + rows + "," + mapTile.getAltasIndex());
}
}
public void draw() {
gContext2D.save();
gContext2D.setFill(Color.WHITE);
gContext2D.clearRect(0, 0, getWidth(), getHeight());
gContext2D.setStroke(Color.BLACK);
TiledMap tiledMap = TiledMap.getInstance();
tileWidth = tiledMap.getTileWidth();
tileHeight = tiledMap.getTileHeight();
// 绘制多图层地图
int length = mapLayerList.size();
if (length > 0) {
for (int i = length - 1; i >= 0; i--) {
TiledMapLayer mapLayer = mapLayerList.get(i);
if (mapLayer.isVisible()) {
MapTile[][] tiles = mapLayer.getMapTiles();
gContext2D.setGlobalAlpha(mapLayer.getAlpha());
if (tiles != null) {
for (int y = 0; y < tiles.length; y++) {
for (int x = 0; x < tiles[0].length; x++) {
if (tiles[y][x] != null) {
AltasResource resource = AltasResourceManager.getInstance().getResourceById(
tiles[y][x].getAltasId());
if (resource != null) {
Image image = resource.getImage();
int index = tiles[y][x].getAltasIndex();
if (index != -1) {
int cellX = (int) (image.getWidth() / tileWidth);
int col = index % cellX;
int row = index / cellX;
gContext2D.drawImage(image, col * tileWidth, row * tileHeight, tileWidth,
tileHeight, x * tileWidth * getScale(),
y * tileHeight * getScale(), tileWidth * getScale(), tileHeight
* getScale());
}
} else {
int index = tiles[y][x].getAltasIndex();
if (index == rectIndex) {
gContext2D.save();
gContext2D.setGlobalAlpha(0.6f);
gContext2D.setFill(Color.RED);
gContext2D.fillRect(x * tileWidth * getScale(),
y * tileHeight * getScale(), tileWidth * getScale(), tileHeight
* getScale());
gContext2D.restore();
}
}
}
}
}
}
}
}
if (isShowGrid()) {
// 绘制网格
gContext2D.setGlobalAlpha(1.0f);
gContext2D.setLineWidth(0.5f);
for (int i = 0; i < tiledMap.getMapWidth(); i++) {
for (int j = 0; j < tiledMap.getMapHeight(); j++) {
gContext2D.strokeRect(i * tileWidth * getScale(), j * tileHeight * getScale(), tileWidth
* getScale(), tileHeight * getScale());
}
}
}
if (isDrawAltasList) {
int cols = (int) (mouseX / (tileWidth * getScale()));
int rows = (int) (mouseY / (tileHeight * getScale()));
// 绘制受影响的网格
gContext2D.setGlobalAlpha(0.6f);
if (nowChooseProperty.getSize() != 0) {
for (int i = 0; i < nowChooseProperty.getSize(); i++) {
int index = nowChooseProperty.get(i);
Image image = nowAltasResource.getImage();
if (index != -1) {
int cellX = (int) (image.getWidth() / tileWidth);
int col = index % cellX;
int row = index / cellX;
int startCol = nowChooseProperty.get(0) % cellX;
int startRow = nowChooseProperty.get(0) / cellX;
gContext2D.fillRect((cols + col - startCol) * tileWidth * getScale(),
(rows + row - startRow) * tileHeight * getScale(), tileWidth * getScale(),
tileHeight * getScale());
}
}
} else {
if (brushTypeProperty.get() == 3) {
gContext2D.fillRect(cols * tileWidth * getScale(), rows * tileHeight * getScale(), tileWidth
* getScale(), tileHeight * getScale());
}
}
// 绘制要填充的贴图
gContext2D.setGlobalAlpha(0.8f);
for (int i = 0; i < nowChooseProperty.getSize(); i++) {
int index = nowChooseProperty.get(i);
Image image = nowAltasResource.getImage();
if (index != -1) {
int cellX = (int) (image.getWidth() / tileWidth);
int col = index % cellX;
int row = index / cellX;
int startCol = nowChooseProperty.get(0) % cellX;
int startRow = nowChooseProperty.get(0) / cellX;
gContext2D.drawImage(image, col * tileWidth, row * tileHeight, tileWidth, tileHeight, (cols
+ col - startCol)
* tileWidth * getScale(), (rows + row - startRow) * tileHeight * getScale(), tileWidth
* getScale(), tileHeight * getScale());
}
}
}
// 绘制属性网格
ArrayList<TileProperty> propertyList = tiledMap.getPropertyList();
if (propertyList.size() > 0) {
gContext2D.setFill(Color.PURPLE);
gContext2D.setGlobalAlpha(0.5f);
for (TileProperty tileProperty : propertyList) {
int rows = tileProperty.getRow();
int cols = tileProperty.getCol();
gContext2D.fillRect(cols * tileWidth * getScale(), rows * tileHeight * getScale(), tileWidth
* getScale(), tileHeight * getScale());
}
}
}
gContext2D.restore();
}
public ObservableList<Integer> getNowChoose() {
return nowChooseProperty.get();
}
public void setNowChoose(ObservableList<Integer> nowChoose) {
this.nowChooseProperty.set(nowChoose);
}
public SimpleListProperty<Integer> NowChooseProperty() {
return nowChooseProperty;
}
public List<TiledMapLayer> getMapLayerList() {
return mapLayerList;
}
public void setMapLayerList(List<TiledMapLayer> mapLayerList) {
this.mapLayerList = mapLayerList;
}
public AltasResource getNowAltasResource() {
return nowAltasResource;
}
public void setNowAltasResource(AltasResource nowAltasResource) {
this.nowAltasResource = nowAltasResource;
}
public SimpleIntegerProperty NowSelectLayerProperty() {
return nowSelectLayerProperty;
}
public void setNowSelectLayer(int nowSelect) {
nowSelectLayerProperty.set(nowSelect);
}
public int getNowSelectLayer() {
return nowSelectLayerProperty.get();
}
public SimpleIntegerProperty BrushTypeProperty() {
return brushTypeProperty;
}
public SimpleBooleanProperty ShowGridProperty() {
return showGridProperty;
}
public SimpleDoubleProperty ScaleProperty() {
return scaleProperty;
}
public void setScale(double scale) {
scaleProperty.set(scale);
}
public double getScale() {
return scaleProperty.get();
}
public boolean isShowGrid() {
return showGridProperty.get();
}
public void setShowGrid(boolean isShowGrid) {
this.showGridProperty.set(isShowGrid);
}
public int getBrushType() {
return brushTypeProperty.get();
}
public int getMouseCols() {
return mouseCols;
}
public int getMouseRows() {
return mouseRows;
}
}