Files
ATCS/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java

2239 lines
84 KiB
Java

package com.gpl.rpg.atcontentstudio.ui.map;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolTip;
import javax.swing.JTree;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.ToolTipManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import tiled.view.MapRenderer;
import tiled.view.OrthogonalRenderer;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea;
import com.gpl.rpg.atcontentstudio.model.maps.KeyArea;
import com.gpl.rpg.atcontentstudio.model.maps.MapChange;
import com.gpl.rpg.atcontentstudio.model.maps.MapObject;
import com.gpl.rpg.atcontentstudio.model.maps.MapObjectGroup;
import com.gpl.rpg.atcontentstudio.model.maps.ReplaceArea;
import com.gpl.rpg.atcontentstudio.model.maps.RestArea;
import com.gpl.rpg.atcontentstudio.model.maps.ScriptArea;
import com.gpl.rpg.atcontentstudio.model.maps.SignArea;
import com.gpl.rpg.atcontentstudio.model.maps.SpawnArea;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.BooleanBasedCheckBox;
import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.Editor;
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox;
import com.gpl.rpg.atcontentstudio.ui.ScrollablePanel;
import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideTabbedPane;
public class TMXMapEditor extends Editor {
private static final long serialVersionUID = -3079451876618342442L;
Map<String, JPanel> editorTabs = new HashMap<String, JPanel>();
JideTabbedPane editorTabsHolder;
private RSyntaxTextArea editorPane;
private IntegerBasedCheckBox outsideBox;
private LayerListModel layerListModel;
private JList layerList;
private tiled.core.MapLayer selectedLayer;
private JButton addTileLayer;
private JButton addObjectGroup;
private JButton deleteLayer;
private JPanel layerDetailsPane;
private BooleanBasedCheckBox layerVisibleBox;
private BooleanBasedCheckBox activeLayerBox;
private JTextField layerNameField;
private MapObjectsListModel groupObjectsListModel;
private JList groupObjectsList;
private MapObject selectedMapObject;
private JButton addMapchange;
private JButton addSpawn;
private JButton addRest;
private JButton addKey;
private JButton addReplace;
private JButton addScript;
private JButton addContainer;
private JButton addSign;
private JButton deleteObject;
private JPanel mapObjectSettingsPane;
private JComboBox droplistBox;
private JComboBox dialogueBox;
private JComboBox mapBox;
private JTextField areaField;
private JComboBox targetAreaCombo;
private JComboBox evaluateTriggerBox;
private JSpinner quantityField;
private JCheckBox activeForNewGame;
private JTextField spawngroupField;
private JList npcList;
private SpawnGroupNpcListModel npcListModel;
private JComboBox requirementTypeCombo;
private JPanel requirementParamsPane;
private JComboBox requirementObj;
private JTextField requirementObjId;
private JSpinner requirementValue;
private BooleanBasedCheckBox requirementNegated;
private JList replacementsList;
private ReplacementsListModel replacementsListModel;
private ReplaceArea.Replacement selectedReplacement;
private JButton addReplacement;
private JButton deleteReplacement;
private JPanel replacementEditPane;
private JComboBox sourceLayer;
private JComboBox targetLayer;
private TMXViewer tmxViewer;
public TMXMapEditor(TMXMap map) {
this.target = map;
this.name = map.getDesc();
this.icon = new ImageIcon(DefaultIcons.getTiledIconIcon());
setLayout(new BorderLayout());
editorTabsHolder = new JideTabbedPane(JideTabbedPane.BOTTOM);
editorTabsHolder.setTabShape(JideTabbedPane.SHAPE_FLAT);
editorTabsHolder.setUseDefaultShowCloseButtonOnTab(false);
editorTabsHolder.setShowCloseButtonOnTab(false);
add(editorTabsHolder, BorderLayout.CENTER);
JScrollPane tmxScroller = new JScrollPane(getTmxEditorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane xmlScroller = new JScrollPane(getXmlEditorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane replScroller = new JScrollPane(getReplacementSimulatorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
xmlScroller.getVerticalScrollBar().setUnitIncrement(16);
editorTabsHolder.add("TMX", tmxScroller);
editorTabsHolder.add("XML", xmlScroller);
editorTabsHolder.add("Replacements", replScroller);
}
public JPanel getTmxEditorPane() {
final TMXMap map = (TMXMap) target;
final FieldUpdateListener listener = new MapFieldUpdater();
ScrollablePanel pane = new ScrollablePanel();
pane.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
addLabelField(pane, "TMX File: ", ((TMXMap)target).tmxFile.getAbsolutePath());
createButtonPane(pane, map.getProject(), map, listener);
outsideBox = addIntegerBasedCheckBox(pane, "Map is outdoors", map.outside, map.writable, listener);
JSplitPane layersViewSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
layerListModel = new LayerListModel(map);
layerList = new JList(layerListModel);
layerList.setCellRenderer(new LayerListRenderer());
layerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane layerListScroller = new JScrollPane(layerList);
layerListScroller.getVerticalScrollBar().setUnitIncrement(16);
layerList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedLayer = (tiled.core.MapLayer) layerList.getSelectedValue();
selectedMapObject = null;
if (selectedLayer != null && map.writable) {
deleteLayer.setEnabled(true);
} else {
deleteLayer.setEnabled(false);
}
updateLayerDetailsPane(layerDetailsPane, selectedLayer, listener);
listener.valueChanged(layerList, selectedLayer);
}
});
JPanel layersListPane = new JPanel();
layersListPane.setLayout(new JideBoxLayout(layersListPane, JideBoxLayout.PAGE_AXIS, 6));
layersListPane.add(layerListScroller, JideBoxLayout.VARY);
addTileLayer = new JButton(new ImageIcon(DefaultIcons.getCreateTileLayerIcon()));
addTileLayer.setToolTipText("Create new tile layer (graphics layer).");
addTileLayer.setEnabled(map.writable);
addTileLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.addObject(new tiled.core.TileLayer());
}
});
addObjectGroup = new JButton(new ImageIcon(DefaultIcons.getCreateObjectGroupIcon()));
addObjectGroup.setToolTipText("Create new object group.");
addObjectGroup.setEnabled(map.writable);
addObjectGroup.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.addObject(new tiled.core.ObjectGroup());
}
});
deleteLayer = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
deleteLayer.setToolTipText("Delete selected layer/group.");
deleteLayer.setEnabled(false);
deleteLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.removeObject(selectedLayer);
}
});
JPanel layersButtonsPane = new JPanel();
layersButtonsPane.setLayout(new JideBoxLayout(layersButtonsPane, JideBoxLayout.LINE_AXIS, 6));
layersButtonsPane.add(addTileLayer, JideBoxLayout.FIX);
layersButtonsPane.add(addObjectGroup, JideBoxLayout.FIX);
layersButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
layersButtonsPane.add(deleteLayer, JideBoxLayout.FIX);
layersListPane.add(layersButtonsPane, JideBoxLayout.FIX);
layersViewSplitPane.setLeftComponent(layersListPane);
layerDetailsPane = new JPanel();
layerDetailsPane.setLayout(new JideBoxLayout(layerDetailsPane, JideBoxLayout.PAGE_AXIS, 6));
layersViewSplitPane.setRightComponent(layerDetailsPane);
pane.add(layersViewSplitPane, JideBoxLayout.FIX);
tmxViewer = new TMXViewer(((TMXMap)target), listener);
JScrollPane tmxScroller = new JScrollPane(tmxViewer);
tmxScroller.getVerticalScrollBar().setUnitIncrement(16);
tmxScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
tmxScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
pane.add(tmxScroller, JideBoxLayout.FIX);
addTMXMapSpritesheetsList(pane, ((TMXMap)target));
addBacklinksList(pane, map);
pane.add(new JPanel(), JideBoxLayout.VARY);
return pane;
}
public void updateLayerDetailsPane(JPanel pane, tiled.core.MapLayer selected, final FieldUpdateListener listener) {
final TMXMap map = (TMXMap)target;
pane.removeAll();
if (selected == null) {
return;
} else if (selected instanceof tiled.core.TileLayer) {
layerNameField = addTextField(pane, "Layer name: ", selected.getName(), map.writable, listener);
layerVisibleBox = addBooleanBasedCheckBox(pane, "Visible", selected.isVisible(), true, listener);
pane.add(new JPanel(), JideBoxLayout.VARY);
} else if (selected instanceof tiled.core.ObjectGroup) {
JSplitPane objectGroupDetailsSplitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JPanel groupDetailPane = new JPanel();
groupDetailPane.setLayout(new JideBoxLayout(groupDetailPane, JideBoxLayout.PAGE_AXIS, 6));
objectGroupDetailsSplitter.setLeftComponent(groupDetailPane);
layerNameField = addTextField(groupDetailPane, "Group name: ", selected.getName(), map.writable, listener);
layerVisibleBox = addBooleanBasedCheckBox(groupDetailPane, "Visible", selected.isVisible(), true, listener);
MapObjectGroup objGroup = null;
for (MapObjectGroup group : map.groups) {
if (group.tmxGroup == selected) {
objGroup = group;
break;
}
}
activeForNewGame = addBooleanBasedCheckBox(groupDetailPane, "Active for new game", objGroup.active, map.writable, listener);
groupObjectsListModel = new MapObjectsListModel(objGroup);
groupObjectsList = new JList(groupObjectsListModel);
groupObjectsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
groupObjectsList.setCellRenderer(new GroupObjectsRenderer());
JScrollPane groupObjectsScroller = new JScrollPane(groupObjectsList);
groupObjectsScroller.getVerticalScrollBar().setUnitIncrement(16);
groupDetailPane.add(groupObjectsScroller, JideBoxLayout.VARY);
groupObjectsList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedMapObject = (MapObject) groupObjectsList.getSelectedValue();
updateMapObjectSettingsPane(mapObjectSettingsPane, selectedMapObject, listener);
listener.valueChanged(groupObjectsList, selectedMapObject);
if (selectedMapObject != null && map.writable) {
deleteObject.setEnabled(true);
} else {
deleteObject.setEnabled(false);
}
}
});
addMapchange = new JButton(new ImageIcon(DefaultIcons.getCreateMapchangeIcon()));
addMapchange.setToolTipText("Create new mapchange area.");
addMapchange.setEnabled(map.writable);
addMapchange.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newMapchange(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addSpawn = new JButton(new ImageIcon(DefaultIcons.getCreateSpawnareaIcon()));
addSpawn.setToolTipText("Create new spawn area.");
addSpawn.setEnabled(map.writable);
addSpawn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newSpawnArea(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addRest = new JButton(new ImageIcon(DefaultIcons.getCreateRestIcon()));
addRest.setToolTipText("Create new rest area.");
addRest.setEnabled(map.writable);
addRest.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newRest(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addKey = new JButton(new ImageIcon(DefaultIcons.getCreateKeyIcon()));
addKey.setToolTipText("Create new key area.");
addKey.setEnabled(map.writable);
addKey.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newKey(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addReplace = new JButton(new ImageIcon(DefaultIcons.getCreateReplaceIcon()));
addReplace.setToolTipText("Create new replace area.");
addReplace.setEnabled(map.writable);
addReplace.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newReplace(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addScript = new JButton(new ImageIcon(DefaultIcons.getCreateScriptIcon()));
addScript.setToolTipText("Create new script area.");
addScript.setEnabled(map.writable);
addScript.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newScript(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addContainer = new JButton(new ImageIcon(DefaultIcons.getCreateContainerIcon()));
addContainer.setToolTipText("Create new container.");
addContainer.setEnabled(map.writable);
addContainer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newContainer(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
addSign = new JButton(new ImageIcon(DefaultIcons.getCreateSignIcon()));
addSign.setToolTipText("Create new sign post.");
addSign.setEnabled(map.writable);
addSign.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newSign(new tiled.core.MapObject(0, 0, 32, 32), map));
}
});
deleteObject = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
deleteObject.setToolTipText("Delete selected map object.");
deleteObject.setEnabled(false);
deleteObject.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.removeObject(selectedMapObject);
}
});
JPanel groupButtonsPane1 = new JPanel();
groupButtonsPane1.setLayout(new JideBoxLayout(groupButtonsPane1, JideBoxLayout.LINE_AXIS, 6));
groupButtonsPane1.add(addMapchange, JideBoxLayout.FIX);
groupButtonsPane1.add(addSpawn, JideBoxLayout.FIX);
groupButtonsPane1.add(addRest, JideBoxLayout.FIX);
groupButtonsPane1.add(addKey, JideBoxLayout.FIX);
groupButtonsPane1.add(new JPanel(), JideBoxLayout.VARY);
JPanel groupButtonsPane2 = new JPanel();
groupButtonsPane2.setLayout(new JideBoxLayout(groupButtonsPane2, JideBoxLayout.LINE_AXIS, 6));
groupButtonsPane2.add(addReplace, JideBoxLayout.FIX);
groupButtonsPane2.add(addScript, JideBoxLayout.FIX);
groupButtonsPane2.add(addContainer, JideBoxLayout.FIX);
groupButtonsPane2.add(addSign, JideBoxLayout.FIX);
groupButtonsPane2.add(new JPanel(), JideBoxLayout.VARY);
groupButtonsPane2.add(deleteObject, JideBoxLayout.FIX);
groupDetailPane.add(groupButtonsPane1, JideBoxLayout.FIX);
groupDetailPane.add(groupButtonsPane2, JideBoxLayout.FIX);
mapObjectSettingsPane = new JPanel();
mapObjectSettingsPane.setLayout(new JideBoxLayout(mapObjectSettingsPane, JideBoxLayout.PAGE_AXIS, 6));
JScrollPane mapObjectSettingsScroller = new JScrollPane(mapObjectSettingsPane);
mapObjectSettingsScroller.getVerticalScrollBar().setUnitIncrement(16);
objectGroupDetailsSplitter.setRightComponent(mapObjectSettingsScroller);
pane.add(objectGroupDetailsSplitter, JideBoxLayout.VARY);
}
pane.revalidate();
pane.repaint();
}
public void updateMapObjectSettingsPane(JPanel pane, final MapObject selected, final FieldUpdateListener listener) {
pane.removeAll();
boolean needVary = true;
if (selected instanceof ContainerArea) {
droplistBox = addDroplistBox(pane, ((TMXMap)target).getProject(), "Droplist: ", ((ContainerArea)selected).droplist, ((TMXMap)target).writable, listener);
} else if (selected instanceof KeyArea) {
dialogueBox = addDialogueBox(pane, ((TMXMap)target).getProject(), "Message when locked: ", ((KeyArea)selected).dialogue, ((TMXMap)target).writable, listener);
requirementTypeCombo = addEnumValueBox(pane, "Requirement type: ", Requirement.RequirementType.values(), ((KeyArea)selected).requirement.type, ((TMXMap)target).writable, listener);
requirementParamsPane = new JPanel();
requirementParamsPane.setLayout(new JideBoxLayout(requirementParamsPane, JideBoxLayout.PAGE_AXIS, 6));
pane.add(requirementParamsPane, JideBoxLayout.FIX);
updateRequirementParamsPane(requirementParamsPane, ((KeyArea)selected).requirement, listener);
} else if (selected instanceof MapChange) {
areaField = addTextField(pane, "Area ID: ", ((MapChange)selected).name, ((TMXMap)target).writable, listener);
mapBox = addMapBox(pane, ((TMXMap)target).getProject(), "Target map: ", ((MapChange)selected).map, ((TMXMap)target).writable, listener);
targetAreaCombo = new JComboBox();
if (((MapChange)selected).map != null) {
((MapChange)selected).map.link();
targetAreaCombo.setModel(new DefaultComboBoxModel((((MapChange)selected).map.getMapchangesNames().toArray())));
}
targetAreaCombo.setEditable(false);
targetAreaCombo.setEnabled(((TMXMap)target).writable);
targetAreaCombo.setSelectedItem(((MapChange)selected).place_id);
JPanel tACPane = new JPanel();
tACPane.setLayout(new JideBoxLayout(tACPane, JideBoxLayout.LINE_AXIS, 6));
tACPane.add(new JLabel("Target mapchange area ID: "), JideBoxLayout.FIX);
tACPane.add(targetAreaCombo, JideBoxLayout.VARY);
JButton nullifyTargetArea = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
tACPane.add(nullifyTargetArea, JideBoxLayout.FIX);
nullifyTargetArea.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
targetAreaCombo.setSelectedItem(null);
listener.valueChanged(targetAreaCombo, null);
}
});
targetAreaCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
listener.valueChanged(targetAreaCombo, targetAreaCombo.getSelectedItem());
}
});
pane.add(tACPane, JideBoxLayout.FIX);
} else if (selected instanceof ReplaceArea) {
//Replace areas only use questProgress requirements ATM
//requirementTypeCombo = addEnumValueBox(pane, "Requirement type: ", Requirement.RequirementType.values(), ((ReplaceArea)selected).requirement.type, ((TMXMap)target).writable, listener);
requirementParamsPane = new JPanel();
requirementParamsPane.setLayout(new JideBoxLayout(requirementParamsPane, JideBoxLayout.PAGE_AXIS, 6));
pane.add(requirementParamsPane, JideBoxLayout.FIX);
updateRequirementParamsPane(requirementParamsPane, ((ReplaceArea)selected).requirement, listener);
CollapsiblePanel replacementListPane = new CollapsiblePanel("Replacements");
replacementListPane.setLayout(new JideBoxLayout(replacementListPane, JideBoxLayout.PAGE_AXIS));
replacementsListModel = new ReplacementsListModel((ReplaceArea) selected);
replacementsList = new JList(replacementsListModel);
replacementsList.setCellRenderer(new ReplacementsListRenderer((ReplaceArea) selected));
replacementListPane.add(new JScrollPane(replacementsList), JideBoxLayout.VARY);
JPanel replacementListButtonsPane = new JPanel();
replacementListButtonsPane.setLayout(new JideBoxLayout(replacementListButtonsPane, JideBoxLayout.LINE_AXIS));
addReplacement = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
replacementListButtonsPane.add(addReplacement, JideBoxLayout.FIX);
addReplacement.setEnabled(((TMXMap)target).writable);
addReplacement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
replacementsListModel.addObject(null, null);
}
});
deleteReplacement = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
replacementListButtonsPane.add(deleteReplacement, JideBoxLayout.FIX);
deleteReplacement.setEnabled(false);
deleteReplacement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
replacementsListModel.removeObject(selectedReplacement);
}
});
replacementListButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
replacementListPane.add(replacementListButtonsPane, JideBoxLayout.FIX);
replacementEditPane = new JPanel();
replacementListPane.add(replacementEditPane, JideBoxLayout.FIX);
pane.add(new JScrollPane(replacementListPane), JideBoxLayout.VARY);
replacementsList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedReplacement = (ReplaceArea.Replacement)replacementsList.getSelectedValue();
updateReplacementsEditPane(replacementEditPane, (ReplaceArea)selected, selectedReplacement, listener);
deleteReplacement.setEnabled(((TMXMap)target).writable);
}
});
} else if (selected instanceof RestArea) {
areaField = addTextField(pane, "Area ID: ", ((RestArea)selected).name, ((TMXMap)target).writable, listener);
} else if (selected instanceof ScriptArea) {
evaluateTriggerBox = addEnumValueBox(pane, "Evaluate on every: ", ScriptArea.EvaluationTrigger.values(), ((ScriptArea)selected).trigger_type, ((TMXMap)target).writable, listener);
dialogueBox = addDialogueBox(pane, ((TMXMap)target).getProject(), "Script: ", ((ScriptArea)selected).dialogue, ((TMXMap)target).writable, listener);
} else if (selected instanceof SignArea) {
dialogueBox = addDialogueBox(pane, ((TMXMap)target).getProject(), "Message: ", ((SignArea)selected).dialogue, ((TMXMap)target).writable, listener);
} else if (selected instanceof SpawnArea) {
areaField = addTextField(pane, "Spawn area ID: ", ((SpawnArea)selected).name, ((TMXMap)target).writable, listener);
spawngroupField = addTextField(pane, "Spawn group ID: ", ((SpawnArea)selected).spawngroup_id, ((TMXMap)target).writable, listener);
quantityField = addIntegerField(pane, "Number of spawned NPCs: ", ((SpawnArea)selected).quantity, false, ((TMXMap)target).writable, listener);
activeForNewGame = addBooleanBasedCheckBox(pane, "Active in a new game: ", ((SpawnArea)selected).active, ((TMXMap)target).writable, listener);
npcListModel = new SpawnGroupNpcListModel((SpawnArea) selected);
npcList = new JList(npcListModel);
npcList.setCellRenderer(new GDERenderer(true, ((TMXMap)target).writable));
npcList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
npcList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
ATContentStudio.frame.openEditor((JSONElement)npcList.getSelectedValue());
ATContentStudio.frame.selectInTree((JSONElement)npcList.getSelectedValue());
}
}
});
npcList.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
ATContentStudio.frame.openEditor((JSONElement)npcList.getSelectedValue());
ATContentStudio.frame.selectInTree((JSONElement)npcList.getSelectedValue());
}
}
});
JScrollPane npcListScroller = new JScrollPane(npcList);
npcListScroller.getVerticalScrollBar().setUnitIncrement(16);
pane.add(npcListScroller, JideBoxLayout.VARY);
needVary = false;
}
if (needVary) pane.add(new JPanel(), JideBoxLayout.VARY);
pane.revalidate();
pane.repaint();
}
public void updateRequirementParamsPane(JPanel pane, Requirement requirement, FieldUpdateListener listener) {
boolean writable = ((TMXMap)target).writable;
Project project = ((TMXMap)target).getProject();
pane.removeAll();
if (requirement.type != null) {
switch (requirement.type) {
case consumedBonemeals:
case spentGold:
requirementObj = null;
requirementObjId = null;
requirementValue = addIntegerField(pane, "Quantity: ", requirement.required_value, false, writable, listener);
break;
case hasActorCondition:
requirementObj = addActorConditionBox(pane, project, "Actor Condition: ", (ActorCondition) requirement.required_obj, writable, listener);
requirementObjId = null;
requirementValue = null;
break;
case inventoryKeep:
case inventoryRemove:
case usedItem:
requirementObj = addItemBox(pane, project, "Item: ", (Item) requirement.required_obj, writable, listener);
requirementObjId = null;
requirementValue = addIntegerField(pane, "Quantity: ", requirement.required_value, false, writable, listener);
break;
case killedMonster:
requirementObj = addNPCBox(pane, project, "Monster: ", (NPC) requirement.required_obj, writable, listener);
requirementObjId = null;
requirementValue = addIntegerField(pane, "Quantity: ", requirement.required_value, false, writable, listener);
break;
case questLatestProgress:
case questProgress:
requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener);
requirementObjId = null;
requirementValue = addIntegerField(pane, "Quest stage: ", requirement.required_value, false, writable, listener);
break;
case skillLevel:
requirementObj = null;
requirementObjId = addTextField(pane, "Skill ID:", requirement.required_obj_id, writable, listener);
requirementValue = addIntegerField(pane, "Level: ", requirement.required_value, false, writable, listener);
break;
case timerElapsed:
requirementObj = null;
requirementObjId = addTextField(pane, "Timer ID:", requirement.required_obj_id, writable, listener);
requirementValue = addIntegerField(pane, "Timer value: ", requirement.required_value, false, writable, listener);
break;
case wear:
requirementObj = addItemBox(pane, project, "Item: ", (Item) requirement.required_obj, writable, listener);
requirementObjId = null;
requirementValue = null;
break;
}
}
requirementNegated = addBooleanBasedCheckBox(pane, "Negate this requirement.", requirement.negated, writable, listener);
pane.revalidate();
pane.repaint();
}
public void updateReplacementsEditPane(JPanel pane, ReplaceArea area, ReplaceArea.Replacement replacement, final FieldUpdateListener listener) {
boolean writable = ((TMXMap)target).writable;
pane.removeAll();
sourceLayer = new JComboBox<String>(new ReplacementsLayersComboModel(area, true, replacement.sourceLayer));
targetLayer = new JComboBox<String>(new ReplacementsLayersComboModel(area, false, replacement.targetLayer));
sourceLayer.setEnabled(writable);
targetLayer.setEnabled(writable);
sourceLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
listener.valueChanged(sourceLayer, sourceLayer.getModel().getSelectedItem());
}
});
targetLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
listener.valueChanged(targetLayer, targetLayer.getModel().getSelectedItem());
}
});
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.LINE_AXIS));
pane.add(new JLabel("Replace "), JideBoxLayout.FIX);
pane.add(sourceLayer, JideBoxLayout.FIX);
pane.add(new JLabel(" by "), JideBoxLayout.FIX);
pane.add(targetLayer, JideBoxLayout.FIX);
pane.add(new JPanel(), JideBoxLayout.VARY);
}
public JPanel getXmlEditorPane() {
JPanel pane = new JPanel();
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
editorPane = new RSyntaxTextArea();
editorPane.setText(((TMXMap)target).toXml());
editorPane.setEditable(false);
editorPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
pane.add(editorPane, JideBoxLayout.VARY);
return pane;
}
public void updateXmlViewText(String text) {
editorPane.setText(text);
}
public JPanel getReplacementSimulatorPane() {
JPanel replacementSimulator = new JPanel();
replacementSimulator.setLayout(new JideBoxLayout(replacementSimulator, JideBoxLayout.PAGE_AXIS));
final JCheckBox walkableVisibleBox = new JCheckBox("Show \""+TMXMap.WALKABLE_LAYER_NAME+"\" layer.");
JPanel areasActivationPane = new JPanel();
areasActivationPane.setLayout(new JideBoxLayout(areasActivationPane, JideBoxLayout.PAGE_AXIS));
TreeModel areasTreeModel = new ReplaceAreasActivationTreeModel();
final JTree areasTree = new JTree(areasTreeModel);
areasTree.setEditable(false);
areasTree.setRootVisible(false);
areasTree.setCellRenderer(new ReplaceAreasActivationTreeCellRenderer());
areasActivationPane.add(new JScrollPane(areasTree), JideBoxLayout.FIX);
final JToggleButton activate = new JToggleButton("Activate ReplaceArea(s)");
areasActivationPane.add(activate, JideBoxLayout.VARY);
final TMXReplacementViewer viewer = new TMXReplacementViewer((TMXMap)target);
JPanel activateAndViewPane = new JPanel();
activateAndViewPane.setLayout(new JideBoxLayout(activateAndViewPane, JideBoxLayout.LINE_AXIS));
activateAndViewPane.add(areasActivationPane, JideBoxLayout.FIX);
activateAndViewPane.add(viewer, JideBoxLayout.VARY);
replacementSimulator.add(walkableVisibleBox, JideBoxLayout.FIX);
replacementSimulator.add(activateAndViewPane, JideBoxLayout.VARY);
walkableVisibleBox.setSelected(true);
walkableVisibleBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
viewer.showWalkable = walkableVisibleBox.isSelected();
viewer.revalidate();
viewer.repaint();
}
});
activate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (areasTree.getSelectionPaths() == null) return;
for (TreePath paths : areasTree.getSelectionPaths()) {
Object target = paths.getLastPathComponent();
if (target instanceof ReplaceArea) {
viewer.activeReplacements.put((ReplaceArea) target, activate.isSelected());
viewer.updateLayers();
viewer.revalidate();
viewer.repaint();
} else if (target instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)target).mapObjects) {
if (obj instanceof ReplaceArea) {
viewer.activeReplacements.put((ReplaceArea) obj, activate.isSelected());
}
viewer.updateLayers();
viewer.revalidate();
viewer.repaint();
}
}
}
}
});
areasTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
ReplaceArea oldHighlight = viewer.highlighted;
viewer.highlighted = null;
if (areasTree.getSelectionPaths() == null) return;
for (TreePath paths : areasTree.getSelectionPaths()) {
Object target = paths.getLastPathComponent();
if (target instanceof ReplaceArea) {
activate.setSelected(viewer.activeReplacements.get((ReplaceArea) target));
viewer.highlighted = (ReplaceArea)target;
} else if (target instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)target).mapObjects) {
activate.setSelected(true);
if (obj instanceof ReplaceArea) {
if (!viewer.activeReplacements.get((ReplaceArea) obj)) {
activate.setSelected(false);
}
}
}
}
}
if (oldHighlight != viewer.highlighted) {
viewer.revalidate();
viewer.repaint();
}
}
});
return replacementSimulator;
}
public class ReplaceAreasActivationTreeModel implements TreeModel {
@Override
public Object getRoot() {
return target;
}
@Override
public Object getChild(Object parent, int index) {
int i = index;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
if (i == 0) return group;
i--;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj instanceof ReplaceArea) {
if (i == 0) return obj;
i--;
}
}
}
return null;
}
@Override
public int getChildCount(Object parent) {
int count = 0;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
count++;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj instanceof ReplaceArea) {
count++;
}
}
}
return count;
}
@Override
public boolean isLeaf(Object node) {
return node instanceof ReplaceArea;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
// TODO Auto-generated method stub
}
@Override
public int getIndexOfChild(Object parent, Object child) {
int index = 0;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
if (group == child) return index;
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
index++;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj == child) return index;
if (obj instanceof ReplaceArea) {
index++;
}
}
}
return index;
}
List<TreeModelListener> listeners = new LinkedList<TreeModelListener>();
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
}
public class ReplaceAreasActivationTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 3988638353699460533L;
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (c instanceof JLabel) {
JLabel label = (JLabel)c;
if (value instanceof MapObjectGroup) {
label.setText(((MapObjectGroup)value).name);
label.setIcon(new ImageIcon(DefaultIcons.getObjectLayerIcon()));
} else if (value instanceof ReplaceArea) {
label.setText(((ReplaceArea)value).name);
label.setIcon(new ImageIcon(DefaultIcons.getReplaceIcon()));
}
}
return c;
}
}
public static JList addTMXMapSpritesheetsList(JPanel pane, TMXMap tmxMap) {
final JList list = new JList(new TMXMapSpritesheetsListModel(tmxMap));
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
ATContentStudio.frame.openEditor((Spritesheet)list.getSelectedValue());
ATContentStudio.frame.selectInTree((Spritesheet)list.getSelectedValue());
}
}
});
list.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
ATContentStudio.frame.openEditor((Spritesheet)list.getSelectedValue());
ATContentStudio.frame.selectInTree((Spritesheet)list.getSelectedValue());
}
}
});
list.setCellRenderer(new SpritesheetCellRenderer(true));
JScrollPane scroller = new JScrollPane(list);
scroller.setBorder(BorderFactory.createTitledBorder("Spritesheets used in this map."));
pane.add(scroller, JideBoxLayout.FIX);
return list;
}
public class LayerListModel implements ListModel {
public TMXMap map;
public LayerListModel(TMXMap map) {
this.map = map;
}
@Override
public int getSize() {
return map.tmxMap.getLayerCount();
}
@Override
public Object getElementAt(int index) {
return map.tmxMap.getLayer(index);
}
public void objectChanged(tiled.core.MapLayer layer) {
int index = map.tmxMap.getLayerIndex(layer);
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
}
}
public void addObject(tiled.core.MapLayer layer) {
map.addLayer(layer);
int index = map.tmxMap.getLayerIndex(layer);
for (ListDataListener l : listeners) {
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
}
}
public void removeObject(tiled.core.MapLayer layer) {
int index = map.tmxMap.getLayerIndex(layer);
map.removeLayer(layer);
for (ListDataListener l : listeners) {
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
}
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}
public class LayerListRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = -6182599528961565957L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (c instanceof JLabel) {
JLabel label = (JLabel)c;
tiled.core.MapLayer layer = (tiled.core.MapLayer)value;
label.setText(layer.getName());
if (layer instanceof tiled.core.TileLayer) {
label.setIcon(new ImageIcon(DefaultIcons.getTileLayerIcon()));
} else if (layer instanceof tiled.core.ObjectGroup) {
label.setIcon(new ImageIcon(DefaultIcons.getObjectLayerIcon()));
}
}
return c;
}
}
public class ReplacementsListModel implements ListModel {
public ReplaceArea area;
public ReplacementsListModel(ReplaceArea area) {
this.area = area;
}
@Override
public int getSize() {
if (area.replacements == null) return 0;
return area.replacements.size();
}
@Override
public Object getElementAt(int index) {
if (index < 0 || index > getSize()) return null;
if (area.replacements == null) return null;
return area.replacements.get(index);
}
public void objectChanged(ReplaceArea.Replacement repl) {
int index = area.replacements.indexOf(repl);
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
}
}
public void addObject(String source, String target) {
ReplaceArea.Replacement repl = area.addReplacement(source, target);
int index = area.replacements.indexOf(repl);
for (ListDataListener l : listeners) {
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
}
}
public void removeObject(ReplaceArea.Replacement repl) {
int index = area.replacements.indexOf(repl);
area.removeReplacement(repl);
for (ListDataListener l : listeners) {
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
}
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}
public class ReplacementsListRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = -6182599528961565957L;
public ReplaceArea area;
public ReplacementsListRenderer(ReplaceArea area) {
super();
this.area = area;
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (c instanceof JLabel) {
JLabel label = (JLabel)c;
ReplaceArea.Replacement repl = (ReplaceArea.Replacement)value;
label.setText(repl.sourceLayer+" -> "+repl.targetLayer);
}
return c;
}
}
public class ReplacementsLayersComboModel implements ComboBoxModel<String> {
ReplaceArea area;
boolean modelForSource = false;
public List<String> availableLayers = new LinkedList<String>();
public String selected;
public ReplacementsLayersComboModel(ReplaceArea area, boolean modelForSource, String selected) {
this.area = area;
this.modelForSource = modelForSource;
this.selected = selected;
availableLayers.add(null);
for (tiled.core.MapLayer layer : ((TMXMap)target).tmxMap.getLayers()) {
if (layer instanceof tiled.core.TileLayer) {
if (modelForSource && !TMXMap.isPaintedLayerName(layer.getName())) {
continue;
}
if (modelForSource && area.hasReplacementFor(layer.getName()) && !layer.getName().equals(selected)) {
continue;
}
availableLayers.add(layer.getName());
}
}
}
@Override
public String getElementAt(int index) {
return availableLayers.get(index);
}
@Override
public Object getSelectedItem() {
return selected;
}
@Override
public int getSize() {
return availableLayers.size();
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
@Override
public void setSelectedItem(Object anItem) {
selected = (String)anItem;
}
}
public class MapObjectsListModel implements ListModel {
public MapObjectGroup group;
public MapObjectsListModel(MapObjectGroup group) {
this.group = group;
}
@Override
public int getSize() {
return group.mapObjects.size();
}
@Override
public Object getElementAt(int index) {
return group.mapObjects.get(index);
}
public void objectChanged(MapObject area) {
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(groupObjectsList, ListDataEvent.CONTENTS_CHANGED, group.mapObjects.indexOf(area), group.mapObjects.indexOf(area)));
}
}
public void addObject(MapObject area) {
group.mapObjects.add(area);
int index = group.mapObjects.indexOf(area);
for (ListDataListener l : listeners) {
l.intervalAdded(new ListDataEvent(groupObjectsList, ListDataEvent.INTERVAL_ADDED, index, index));
}
}
public void removeObject(MapObject area) {
int index = group.mapObjects.indexOf(area);
group.mapObjects.remove(area);
for (ListDataListener l : listeners) {
l.intervalRemoved(new ListDataEvent(groupObjectsList, ListDataEvent.INTERVAL_REMOVED, index, index));
}
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}
public class GroupObjectsRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = -6182599528961565957L;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (c instanceof JLabel) {
((JLabel)c).setText(((MapObject)value).name);
((JLabel)c).setIcon(new ImageIcon(((MapObject)value).getIcon()));
}
return c;
}
}
public class SpawnGroupNpcListModel implements ListModel {
public SpawnArea area;
public SpawnGroupNpcListModel(SpawnArea area) {
this.area = area;
}
@Override
public int getSize() {
return area.spawnGroup.size();
}
@Override
public Object getElementAt(int index) {
return area.spawnGroup.get(index);
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}
public class TMXViewer extends JPanel implements Scrollable {
private static final long serialVersionUID = 2845032142029325865L;
public tiled.core.MapObject highlighted = null;
private MapRenderer renderer;
private FieldUpdateListener listener;
public boolean resizing = false;
public boolean moving = false;
public Rectangle getResizeHitArea() {
//16x16 px square in the lower right corner of area
return new Rectangle(selectedMapObject.x + selectedMapObject.w - 16, selectedMapObject.y + selectedMapObject.h - 16, 16, 16);
}
public Rectangle getMoveHitArea() {
//16x16 px square in the upper left corner of area
return new Rectangle(selectedMapObject.x, selectedMapObject.y, 16, 16);
}
public Rectangle getSelectHitArea(MapObject obj) {
//16x16 px square in the upper left corner of area
return new Rectangle(obj.x, obj.y, 16, 16);
}
public TMXViewer(final TMXMap map, FieldUpdateListener listener) {
this.listener = listener;
renderer = createRenderer(map.tmxMap);
setPreferredSize(renderer.getMapSize());
setOpaque(true);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (!moving && !resizing) {
select: for (MapObjectGroup group : map.groups) {
if (group.visible) {
for (MapObject obj : group.mapObjects) {
if (getSelectHitArea(obj).contains(e.getPoint())) {
TMXMapEditor.this.selectMapObject(obj);
break select;
}
}
}
}
}
}
}
});
if (((TMXMap)target).writable) {
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
resizing = false;
moving = false;
}
}
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (selectedMapObject != null && selectedLayer.isVisible()) {
if (getResizeHitArea().contains(e.getPoint())) {
resizing = true;
} else if (getMoveHitArea().contains(e.getPoint())) {
moving = true;
}
}
}
}
});
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseMoved(MouseEvent e) {
if (selectedMapObject == null) return;
if (!resizing && !moving) {
if (getResizeHitArea().contains(e.getPoint())) {
setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
} else if (getMoveHitArea().contains(e.getPoint())) {
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
} else {
setCursor(Cursor.getDefaultCursor());
}
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (selectedMapObject == null) return;
boolean valueChanged = false;
if (resizing) {
Point p = getClosestTileCorner(e.getPoint());
if (p.x > selectedMapObject.x) {
int oldW = selectedMapObject.w;
selectedMapObject.w = Math.min(p.x - selectedMapObject.x, map.tmxMap.getWidth() * map.tmxMap.getTileWidth());
if (selectedMapObject.w != oldW) valueChanged = true;
}
if (p.y > selectedMapObject.y) {
int oldH = selectedMapObject.h;
selectedMapObject.h = Math.min(p.y - selectedMapObject.y, map.tmxMap.getHeight() * map.tmxMap.getTileHeight());
if (selectedMapObject.h != oldH) valueChanged = true;
}
} else if (moving) {
Point p = getClosestTileCorner(e.getPoint());
if (p.x + selectedMapObject.w <= map.tmxMap.getWidth() * map.tmxMap.getTileWidth()) {
int oldX = selectedMapObject.x;
selectedMapObject.x = Math.max(p.x, 0);
if (selectedMapObject.x != oldX) valueChanged = true;
}
if (p.y + selectedMapObject.h <= map.tmxMap.getHeight() * map.tmxMap.getTileHeight()) {
int oldY = selectedMapObject.y;
selectedMapObject.y = Math.max(p.y, 0);
if (selectedMapObject.y != oldY) valueChanged = true;
}
}
if (valueChanged) {
TMXViewer.this.listener.valueChanged(TMXViewer.this, null);
TMXViewer.this.revalidate();
TMXViewer.this.repaint();
}
}
});
}
}
public void setHighlight(tiled.core.MapObject selected) {
highlighted = selected;
invalidate();
}
public void paintComponent(Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
final Rectangle clip = g2d.getClipBounds();
// Draw a gray background
g2d.setPaint(new Color(100, 100, 100));
g2d.fill(clip);
// Draw each tile map layer
boolean paintSelected = false;
for (tiled.core.MapLayer layer : ((TMXMap)target).tmxMap) {
if (layer instanceof tiled.core.TileLayer && layer.isVisible()) {
renderer.paintTileLayer(g2d, (tiled.core.TileLayer) layer);
} else if (layer instanceof tiled.core.ObjectGroup && layer.isVisible()) {
paintSelected |= paintObjectGroup(g2d, (tiled.core.ObjectGroup) layer);
}
}
if (paintSelected) {
//TODO make this less ugly..... visually speaking.
g2d.setColor(new Color(190, 20, 20));
g2d.drawRect(selectedMapObject.x + selectedMapObject.w - 16, selectedMapObject.y + selectedMapObject.h - 16, 15, 15);
g2d.drawRect(selectedMapObject.x + selectedMapObject.w - 12, selectedMapObject.y + selectedMapObject.h - 12, 11, 11);
drawObject(selectedMapObject, g2d, new Color(190, 20, 20));
}
g2d.dispose();
}
private boolean paintObjectGroup(Graphics2D g2d, tiled.core.ObjectGroup layer) {
boolean paintSelected = false;
for (MapObjectGroup group : ((TMXMap)target).groups) {
if (group.tmxGroup == layer) {
for (MapObject object : group.mapObjects) {
if (object == selectedMapObject) {
paintSelected = true;
continue;
} else {
drawObject(object, g2d, new Color(20, 20, 190));
}
}
break;
}
}
return paintSelected;
}
private MapRenderer createRenderer(tiled.core.Map map) {
switch (map.getOrientation()) {
case tiled.core.Map.ORIENTATION_ORTHOGONAL:
return new OrthogonalRenderer(map);
default:
return null;
}
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL)
return ((TMXMap)target).tmxMap.getTileWidth();
else
return ((TMXMap)target).tmxMap.getTileHeight();
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL) {
final int tileWidth = ((TMXMap)target).tmxMap.getTileWidth();
return (visibleRect.width / tileWidth - 1) * tileWidth;
} else {
final int tileHeight = ((TMXMap)target).tmxMap.getTileHeight();
return (visibleRect.height / tileHeight - 1) * tileHeight;
}
}
public boolean getScrollableTracksViewportWidth() {
return false;
}
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
public static class TMXMapSpritesheetsListModel implements ListModel {
TMXMap map;
public TMXMapSpritesheetsListModel(TMXMap map) {
this.map = map;
}
@Override
public int getSize() {
return map.usedSpritesheets.size();
}
@Override
public Object getElementAt(int index) {
for (Spritesheet sheet : map.usedSpritesheets) {
if (index == 0) return sheet;
index --;
}
return null;
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
public void fireListChanged() {
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, this.getSize()));
}
}
}
public static class SpritesheetCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 6819681566800482793L;
private boolean includeType = false;
public SpritesheetCellRenderer(boolean includeType) {
super();
this.includeType = includeType;
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
label.setText("none");
} else {
if (includeType && ((Spritesheet)value).getDataType() != null) {
label.setText(((Spritesheet)value).getDataType().toString()+"/"+((Spritesheet)value).getDesc());
} else {
label.setText(((Spritesheet)value).getDesc());
}
if (((Spritesheet)value).getIcon() == null) {
Notification.addError("Unable to find icon for "+((Spritesheet)value).getDesc());
} else {
label.setIcon(new ImageIcon(((Spritesheet)value).getIcon()));
}
}
return label;
}
}
@Override
public void targetUpdated() {
this.name = ((TMXMap)target).getDesc();
updateMessage();
}
protected void selectMapObject(MapObject obj) {
for (MapObjectGroup group : ((TMXMap)target).groups) {
if (group.mapObjects.contains(obj)) {
layerList.setSelectedValue(group.tmxGroup, true);
groupObjectsList.setSelectedValue(obj, true);
}
}
}
public JButton createButtonPane(JPanel pane, final Project proj, final TMXMap map, final FieldUpdateListener listener) {
final JButton gdeIcon = new JButton(new ImageIcon(DefaultIcons.getTiledIconImage()));
JPanel savePane = new JPanel();
savePane.add(gdeIcon, JideBoxLayout.FIX);
savePane.setLayout(new JideBoxLayout(savePane, JideBoxLayout.LINE_AXIS, 6));
if (map.writable) {
if (map.getDataType() == GameSource.Type.altered) {
savePane.add(message = new JLabel(ALTERED_MESSAGE), JideBoxLayout.FIX);
} else if (map.getDataType() == GameSource.Type.created) {
savePane.add(message = new JLabel(CREATED_MESSAGE), JideBoxLayout.FIX);
}
JButton save = new JButton(SAVE);
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (map.state != TMXMap.State.saved) {
map.save();
ATContentStudio.frame.nodeChanged(map);
}
}
});
savePane.add(save, JideBoxLayout.FIX);
JButton delete = new JButton(DELETE);
if (map.getDataType() == GameSource.Type.altered) {
delete.setText(REVERT);
}
delete.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ATContentStudio.frame.closeEditor(map);
map.childrenRemoved(new ArrayList<ProjectTreeNode>());
map.delete();
}
});
savePane.add(delete, JideBoxLayout.FIX);
} else {
if (proj.getMap(map.id) != map) {
savePane.add(message = new JLabel(ALTERED_EXISTS_MESSAGE), JideBoxLayout.FIX);
JButton makeWritable = new JButton(GO_TO_ALTERED);
makeWritable.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (map.getProject().getMap(map.id) != map) {
ATContentStudio.frame.openEditor(map.getProject().getMap(map.id));
ATContentStudio.frame.closeEditor(map);
ATContentStudio.frame.selectInTree(map.getProject().getMap(map.id));
}
}
});
savePane.add(makeWritable, JideBoxLayout.FIX);
} else {
savePane.add(message = new JLabel(READ_ONLY_MESSAGE), JideBoxLayout.FIX);
JButton makeWritable = new JButton(ALTER);
makeWritable.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (map.getProject().getMap(map.id) == map) {
map.getProject().makeWritable(map);
}
if (map.getProject().getMap(map.id) != map) {
ATContentStudio.frame.openEditor(map.getProject().getMap(map.id));
ATContentStudio.frame.closeEditor(map);
ATContentStudio.frame.selectInTree(map.getProject().getMap(map.id));
}
}
});
savePane.add(makeWritable, JideBoxLayout.FIX);
}
}
JButton prev = new JButton(new ImageIcon(DefaultIcons.getArrowLeftIcon()));
JButton next = new JButton(new ImageIcon(DefaultIcons.getArrowRightIcon()));
savePane.add(prev, JideBoxLayout.FIX);
savePane.add(next, JideBoxLayout.FIX);
if (map.getParent().getIndex(map) == 0) {
prev.setEnabled(false);
}
if (map.getParent().getIndex(map) == map.getParent().getChildCount() - 1) {
next.setEnabled(false);
}
prev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ProjectTreeNode prevNode = (ProjectTreeNode) map.getParent().getChildAt(map.getParent().getIndex(map) - 1);
if (prevNode != null && prevNode instanceof GameDataElement) {
ATContentStudio.frame.openEditor((GameDataElement) prevNode);
}
}
});
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ProjectTreeNode nextNode = (ProjectTreeNode) map.getParent().getChildAt(map.getParent().getIndex(map) + 1);
if (nextNode != null && nextNode instanceof GameDataElement) {
ATContentStudio.frame.openEditor((GameDataElement) nextNode);
}
}
});
//Placeholder. Fills the eventual remaining space.
savePane.add(new JPanel(), JideBoxLayout.VARY);
pane.add(savePane, JideBoxLayout.FIX);
return gdeIcon;
}
public class MapFieldUpdater implements FieldUpdateListener {
@Override
public void valueChanged(JComponent source, Object value) {
TMXMap map = (TMXMap) target;
boolean modified = true;
if (source == layerNameField) {
selectedLayer.setName((String) value);
if (selectedLayer instanceof tiled.core.ObjectGroup){
map.getGroup((tiled.core.ObjectGroup) selectedLayer).name = (String) value;
}
layerListModel.objectChanged(selectedLayer);
} else if (source == layerVisibleBox) {
selectedLayer.setVisible(layerVisibleBox.isSelected());
if (selectedLayer instanceof tiled.core.ObjectGroup) {
map.getGroup((tiled.core.ObjectGroup) selectedLayer).visible = layerVisibleBox.isSelected();
}
modified = false;
tmxViewer.revalidate();
tmxViewer.repaint();
} else if (source == activeForNewGame) {
if (selectedLayer instanceof tiled.core.ObjectGroup) {
map.getGroup((tiled.core.ObjectGroup) selectedLayer).active = activeForNewGame.isSelected();
}
modified = true;
} else if (source == layerList) {
modified = false;
tmxViewer.revalidate();
tmxViewer.repaint();
} else if (source == groupObjectsList) {
modified = false;
tmxViewer.revalidate();
tmxViewer.repaint();
} else if (source == areaField) {
selectedMapObject.name = (String) value;
groupObjectsListModel.objectChanged(selectedMapObject);
} else if (source == spawngroupField) {
if (selectedMapObject instanceof SpawnArea) {
SpawnArea area = (SpawnArea)selectedMapObject;
if (area.spawnGroup != null && !area.spawnGroup.isEmpty()) {
for (NPC npc : area.spawnGroup) {
npc.removeBacklink(map);
}
}
area.spawngroup_id = (String) value;
selectedMapObject.link();
npcList.setModel(new SpawnGroupNpcListModel(area));
groupObjectsListModel.objectChanged(area);
npcList.revalidate();
npcList.repaint();
tmxViewer.revalidate();
tmxViewer.repaint();
}
} else if (source == targetAreaCombo) {
if (selectedMapObject instanceof MapChange) {
MapChange area = (MapChange) selectedMapObject;
area.place_id = (String) value;
}
} else if (source == outsideBox) {
map.outside = (Integer)value;
} else if (source == droplistBox) {
if (selectedMapObject instanceof ContainerArea) {
ContainerArea area = (ContainerArea)selectedMapObject;
if (area.droplist != null) {
area.droplist.removeBacklink(map);
}
area.droplist = (Droplist) value;
if (area.droplist != null) {
area.name = area.droplist.id;
} else {
area.name = null;
}
groupObjectsListModel.objectChanged(area);
tmxViewer.revalidate();
tmxViewer.repaint();
}
} else if (source == dialogueBox) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
if (area.dialogue != null) {
area.dialogue.removeBacklink(map);
}
area.dialogue = (Dialogue) value;
if (area.dialogue != null) {
area.dialogue_id = area.dialogue.id;
} else {
area.dialogue_id = null;
}
tmxViewer.revalidate();
tmxViewer.repaint();
} else if (selectedMapObject instanceof ScriptArea) {
ScriptArea area = (ScriptArea) selectedMapObject;
if (area.dialogue != null) {
area.dialogue.removeBacklink(map);
}
area.dialogue = (Dialogue) value;
if (area.dialogue != null) {
area.name = area.dialogue.id;
} else {
area.name = null;
}
groupObjectsListModel.objectChanged(area);
tmxViewer.revalidate();
tmxViewer.repaint();
} else if (selectedMapObject instanceof SignArea) {
SignArea area = (SignArea) selectedMapObject;
if (area.dialogue != null) {
area.dialogue.removeBacklink(map);
}
area.dialogue = (Dialogue) value;
if (area.dialogue != null) {
area.name = area.dialogue.id;
} else {
area.name = null;
}
groupObjectsListModel.objectChanged(area);
tmxViewer.revalidate();
tmxViewer.repaint();
}
} else if (source == mapBox) {
if (selectedMapObject instanceof MapChange) {
MapChange area = (MapChange) selectedMapObject;
if (area.map != null) {
area.map.removeBacklink(map);
}
area.map = (TMXMap) value;
if (area.map != null) {
area.map_id = area.map.id;
targetAreaCombo.setModel(new DefaultComboBoxModel((area.map.getMapchangesNames().toArray())));
} else {
area.map_id = null;
}
tmxViewer.revalidate();
tmxViewer.repaint();
}
} else if (source == evaluateTriggerBox) {
if (selectedMapObject instanceof ScriptArea) {
ScriptArea area = (ScriptArea) selectedMapObject;
area.trigger_type = (ScriptArea.EvaluationTrigger) value;
}
} else if (source == quantityField) {
if (selectedMapObject instanceof SpawnArea) {
SpawnArea area = (SpawnArea) selectedMapObject;
area.quantity = (Integer) value;
}
} else if (source == activeForNewGame) {
if (selectedMapObject instanceof SpawnArea) {
SpawnArea area = (SpawnArea) selectedMapObject;
area.active = (Boolean) value;
}
} else if (source == requirementTypeCombo) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.changeType((Requirement.RequirementType)requirementTypeCombo.getSelectedItem());
updateRequirementParamsPane(requirementParamsPane, area.requirement, this);
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementObj) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.required_obj = (GameDataElement) value;
if (area.requirement.required_obj != null) {
area.requirement.required_obj_id = area.requirement.required_obj.id;
} else {
area.requirement.required_obj_id = null;
}
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_obj = (GameDataElement) value;
if (area.requirement.required_obj != null) {
area.requirement.required_obj_id = area.requirement.required_obj.id;
} else {
area.requirement.required_obj_id = null;
}
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementObjId) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.required_obj_id = (String) value;
area.requirement.required_obj = null;
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_obj_id = (String) value;
area.requirement.required_obj = null;
}
} else if (source == requirementValue) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.required_value = (Integer) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_value = (Integer) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementNegated) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.negated = (Boolean) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.negated = (Boolean) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == sourceLayer) {
selectedReplacement.sourceLayer = (String)value;
replacementsListModel.objectChanged(selectedReplacement);
groupObjectsListModel.objectChanged(selectedMapObject);
} else if (source == targetLayer) {
selectedReplacement.targetLayer = (String)value;
replacementsListModel.objectChanged(selectedReplacement);
groupObjectsListModel.objectChanged(selectedMapObject);
}
if (modified) {
if (map.state != GameDataElement.State.modified) {
map.state = GameDataElement.State.modified;
TMXMapEditor.this.name = map.getDesc();
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
}
updateXmlViewText(map.toXml());
}
}
}
public void updateMessage() {
//TODO make this a full update of the button panel.
TMXMap node = (TMXMap) target;
if (node.writable) {
if (node.getDataType() == GameSource.Type.altered) {
message.setText(ALTERED_MESSAGE);
} else if (node.getDataType() == GameSource.Type.created) {
message.setText(CREATED_MESSAGE);
}
} else if (node.getProject().getMap(node.id) != node) {
message.setText(ALTERED_EXISTS_MESSAGE);
} else {
message.setText(READ_ONLY_MESSAGE);
}
message.revalidate();
message.repaint();
}
public class TMXReplacementViewer extends JPanel implements Scrollable {
private static final long serialVersionUID = 2845032142029325865L;
private TMXMap map;
public ReplaceArea highlighted = null;
public boolean showWalkable = true;
private OrthogonalRenderer renderer;
private String groundName, objectsName, aboveName, walkableName;
private Map<String, tiled.core.TileLayer> layersByName = new LinkedHashMap<String, tiled.core.TileLayer>();
private tiled.core.TileLayer ground, objects, above, walkable;
private Map<String, List<ReplaceArea>> replacementsForLayer = new LinkedHashMap<String, List<ReplaceArea>>();
public Map<ReplaceArea, Boolean> activeReplacements = new LinkedHashMap<ReplaceArea, Boolean>();
private boolean tooltipActivated = true;
public TMXReplacementViewer(final TMXMap map) {
this.map = map;
renderer = createRenderer(map.tmxMap);
init();
setPreferredSize(renderer.getMapSize());
setOpaque(true);
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
tooltippedTile.setLocation(e.getX() / 32, e.getY() / 32);
if (!((TMXMap)target).tmxMap.contains(tooltippedTile.x, tooltippedTile.y)) {
if (tooltipActivated) {
//Hides the tooltip...
ToolTipManager.sharedInstance().setEnabled(false);
ToolTipManager.sharedInstance().unregisterComponent(TMXReplacementViewer.this);
tooltipActivated = false;
}
} else {
if (!tooltipActivated) {
ToolTipManager.sharedInstance().registerComponent(TMXReplacementViewer.this);
ToolTipManager.sharedInstance().setEnabled(true);
tooltipActivated = true;
}
}
}
});
ToolTipManager.sharedInstance().registerComponent(this);
setToolTipText("");
}
public void init() {
groundName = objectsName = aboveName = walkableName = null;
layersByName.clear();
ground = objects = above = walkable = null;
replacementsForLayer.clear();
for (tiled.core.MapLayer layer : map.tmxMap.getLayers()) {
if (layer instanceof tiled.core.TileLayer) {
layersByName.put(layer.getName(), (tiled.core.TileLayer)layer);
if (TMXMap.GROUND_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
groundName = layer.getName();
} else if (TMXMap.OBJECTS_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
objectsName = layer.getName();
} else if (TMXMap.ABOVE_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
aboveName = layer.getName();
} else if (TMXMap.WALKABLE_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
walkableName = layer.getName();
}
}
}
for (MapObjectGroup group : map.groups) {
for (MapObject object : group.mapObjects) {
if (object instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea)object;
if (!activeReplacements.containsKey(area)) {
activeReplacements.put(area, true);
}
for (ReplaceArea.Replacement repl : area.replacements) {
if (replacementsForLayer.get(repl.sourceLayer) == null) {
replacementsForLayer.put(repl.sourceLayer, new LinkedList<ReplaceArea>());
}
replacementsForLayer.get(repl.sourceLayer).add(area);
}
}
}
}
updateLayers();
}
public void updateLayers() {
ground = mergeReplacements(groundName);
objects = mergeReplacements(objectsName);
above = mergeReplacements(aboveName);
walkable = mergeReplacements(walkableName);
}
private tiled.core.TileLayer mergeReplacements(String layerName) {
tiled.core.TileLayer merged = null;
if (layerName != null && layersByName.get(layerName) != null) {
tiled.core.TileLayer original = layersByName.get(layerName);
merged = new tiled.core.TileLayer(original.getBounds());
merged.copyFrom(original);
if (replacementsForLayer.containsKey(layerName)) {
for (ReplaceArea area : replacementsForLayer.get(layerName)) {
if (activeReplacements.get(area)) {
String targetName = null;
for (ReplaceArea.Replacement repl : area.replacements) {
if (layerName.equals(repl.sourceLayer)) {
targetName = repl.targetLayer;
}
}
if (targetName != null) {
for (int x = area.x / 32; x < (area.x + area.w) / 32; x++) {
for (int y = area.y / 32; y < (area.y + area.h) / 32; y++) {
merged.setTileAt(x, y, layersByName.get(targetName).getTileAt(x, y));
}
}
}
}
}
}
}
return merged;
}
public void setHighlight(ReplaceArea selected) {
highlighted = selected;
invalidate();
}
public void paintComponent(Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
final Rectangle clip = g2d.getClipBounds();
// Draw a gray background
g2d.setPaint(new Color(100, 100, 100));
g2d.fill(clip);
// Draw each tile map layer
if (ground != null) {
renderer.paintTileLayer(g2d, ground);
}
if (objects != null) {
renderer.paintTileLayer(g2d, objects);
}
if (above != null) {
renderer.paintTileLayer(g2d, above);
}
if (walkable != null && showWalkable) {
renderer.paintTileLayer(g2d, walkable);
}
if (highlighted != null) {
drawObject(highlighted, g2d, new Color(190, 20, 20));
}
g2d.dispose();
}
private OrthogonalRenderer createRenderer(tiled.core.Map map) {
return new OrthogonalRenderer(map);
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL)
return ((TMXMap)target).tmxMap.getTileWidth();
else
return ((TMXMap)target).tmxMap.getTileHeight();
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL) {
final int tileWidth = ((TMXMap)target).tmxMap.getTileWidth();
return (visibleRect.width / tileWidth - 1) * tileWidth;
} else {
final int tileHeight = ((TMXMap)target).tmxMap.getTileHeight();
return (visibleRect.height / tileHeight - 1) * tileHeight;
}
}
public boolean getScrollableTracksViewportWidth() {
return false;
}
public boolean getScrollableTracksViewportHeight() {
return false;
}
JLabel noTileGround = new JLabel(new ImageIcon(DefaultIcons.getNullifyImage().getScaledInstance(32, 32, Image.SCALE_DEFAULT)));
JLabel noTileObjects = new JLabel(new ImageIcon(DefaultIcons.getNullifyImage().getScaledInstance(32, 32, Image.SCALE_DEFAULT)));
JLabel noTileAbove = new JLabel(new ImageIcon(DefaultIcons.getNullifyImage().getScaledInstance(32, 32, Image.SCALE_DEFAULT)));
{
noTileGround.setPreferredSize(new Dimension(32, 32));
noTileObjects.setPreferredSize(new Dimension(32, 32));
noTileAbove.setPreferredSize(new Dimension(32, 32));
}
Point tooltippedTile = new Point();
JToolTip tt = null;
Point lastTTTile = null;
@Override
public JToolTip createToolTip() {
if (tooltippedTile.equals(lastTTTile)) {
return tt;
}
if (!((TMXMap)target).tmxMap.contains(tooltippedTile.x, tooltippedTile.y)) {
return super.createToolTip();
}
tt = super.createToolTip();
lastTTTile = new Point(tooltippedTile);
tt.setLayout(new BorderLayout());
JPanel content = new JPanel();
content.setLayout(new JideBoxLayout(content, JideBoxLayout.PAGE_AXIS));
if (tooltippedTile != null) {
Image tile;
JLabel label;
if (above != null && above.getTileAt(tooltippedTile.x, tooltippedTile.y) != null) {
tile = above.getTileAt(tooltippedTile.x, tooltippedTile.y).getImage();
} else {
tile = null;
}
if (tile != null) {
label = new JLabel(new ImageIcon(tile));
label.setPreferredSize(new Dimension(32,32));
content.add(label, JideBoxLayout.FIX);
} else {
content.add(noTileAbove, JideBoxLayout.FIX);
}
if (objects != null && objects.getTileAt(tooltippedTile.x, tooltippedTile.y) != null) {
tile = objects.getTileAt(tooltippedTile.x, tooltippedTile.y).getImage();
} else {
tile = null;
}
if (tile != null) {
label = new JLabel(new ImageIcon(tile));
label.setPreferredSize(new Dimension(32,32));
content.add(label, JideBoxLayout.FIX);
} else {
content.add(noTileObjects, JideBoxLayout.FIX);
}
if (ground != null && ground.getTileAt(tooltippedTile.x, tooltippedTile.y) != null) {
tile = ground.getTileAt(tooltippedTile.x, tooltippedTile.y).getImage();
} else {
tile = null;
}
if (tile != null) {
label = new JLabel(new ImageIcon(tile));
label.setPreferredSize(new Dimension(32,32));
content.add(label, JideBoxLayout.FIX);
} else {
content.add(noTileGround, JideBoxLayout.FIX);
}
content.add(new JLabel(tooltippedTile.x+", "+tooltippedTile.y), JideBoxLayout.FIX);
}
tt.add(content, BorderLayout.CENTER);
tt.setPreferredSize(tt.getLayout().preferredLayoutSize(tt));
return tt;
}
@Override
public Point getToolTipLocation(MouseEvent event) {
return event.getPoint();//new Point(event.getX() - (event.getX() % 32), event.getY() - (event.getY() % 32));
}
}
public Point getClosestTileCorner(Point p) {
return new Point(getClosestMultiple(p.x, 32), getClosestMultiple(p.y, 32));
}
public int getClosestMultiple(int num, int ref) {
int rest = num % ref;
int result = num - rest;
if (rest >= ref / 2) {
result += ref;
}
return result;
}
private void drawObject(MapObject object, Graphics2D g2d, Color color) {
g2d.setPaint(color);
g2d.drawRect(object.x+1, object.y+1, object.w-3, object.h-3);
g2d.drawRect(object.x+2, object.y+2, object.w-5, object.h-5);
g2d.setPaint(color.darker().darker());
g2d.drawLine(object.x, object.y + object.h - 1, object.x + object.w - 1, object.y + object.h - 1);
g2d.drawLine(object.x + object.w - 1, object.y, object.x + object.w - 1, object.y + object.h - 1);
g2d.drawLine(object.x + 3, object.y + 3, object.x + object.w - 4, object.y + 3);
g2d.drawLine(object.x + 3, object.y + 3, object.x + 3, object.y + object.h - 4);
g2d.setPaint(color.brighter().brighter().brighter());
g2d.drawLine(object.x, object.y, object.x + object.w - 1, object.y);
g2d.drawLine(object.x, object.y, object.x, object.y + object.h - 1);
g2d.drawLine(object.x + 3, object.y + object.h - 4, object.x + object.w - 4, object.y + object.h - 4);
g2d.drawLine(object.x + object.w - 4, object.y + 3, object.x + object.w - 4, object.y + object.h - 4);
Image img = object.getIcon();
g2d.setColor(new Color(255, 255, 255, 120));
g2d.fillRect(object.x + 2, object.y + 2, img.getWidth(null), img.getHeight(null));
g2d.drawImage(object.getIcon(), object.x + 2, object.y + 2, null);
}
}