/* * JavaXYQ Source Code * by kylixs * at 2009-12-5 * please visit http://javaxyq.googlecode.com * or mail to kylixs@qq.com */ package com.javaxyq.tools.maker; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.SQLException; import java.util.List; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.border.Border; import javax.swing.text.BadLocationException; import org.jdesktop.application.Action; import org.jdesktop.application.Application; import org.jdesktop.application.ApplicationContext; import org.jdesktop.application.SingleFrameApplication; import com.javaxyq.core.SpriteFactory; import com.javaxyq.data.PreexistingEntityException; import com.javaxyq.data.SceneNpc; import com.javaxyq.tools.JMap; import com.javaxyq.ui.Label; import com.javaxyq.util.UIUtils; import com.javaxyq.widget.Animation; import com.jidesoft.dialog.ButtonPanel; import com.jidesoft.dialog.StandardDialog; import com.jidesoft.document.DocumentComponent; import com.jidesoft.document.DocumentPane; import com.jidesoft.editor.CodeEditor; import com.jidesoft.editor.SyntaxDocument; import com.jidesoft.editor.tokenmarker.JavaTokenMarker; import com.jidesoft.swing.JideTabbedPane; /** * �����༭�� * * @author dewitt * @date 2009-12-5 create */ public class SceneEditor extends JPanel implements MouseListener { private static final long serialVersionUID = 1L; private JMap map; private CellPanel cellPanel; private boolean gridShowing = true; private SceneLayer eventLayer; private SceneLayer topLayer; private CharacterChooser spriteChooser; private int cellWidth = 20; private int cellHeight = 20; private String characterId = "1001"; private String sceneId; private String scriptTemplate; private Border spriteHoverBorder = BorderFactory.createLineBorder(Color.RED); private Border spriteBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); public SceneEditor() { initGUI(); } /** * ��ʼ��GUI * * @return */ private void initGUI() { setLayout(null); this.map = new JMap(); cellPanel = new CellPanel(); eventLayer = new SceneLayer(); //eventLayer.setComponentPopupMenu(createEventLayerMenu()); add(eventLayer); add(cellPanel); add(this.map); setTopLayer(eventLayer); addMouseListener(this); spriteChooser = new CharacterChooser(((SingleFrameApplication)Application.getInstance()).getMainFrame()); } /** * ��ȡActionʵ�� * * @param name * @return */ private javax.swing.Action getAction(String name) { ApplicationContext context = Application.getInstance().getContext(); return context.getActionMap(this).get(name); } /** * @return */ private JPopupMenu createEventLayerMenu() { JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(getAction("placeNpc")); return popupMenu; } public CellPanel getCellPanel() { return cellPanel; } public int getCellHeight() { return cellPanel.getCellHeight(); } public int getCellWidth() { return cellPanel.getCellWidth(); } public void setCellHeight(int cellHeight) { cellPanel.setCellHeight(cellHeight); } public void setCellWidth(int cellWidth) { cellPanel.setCellWidth(cellWidth); } /** * ��ʾ���������� */ public void toggleGrid() { gridShowing = !gridShowing; cellPanel.setVisible(gridShowing); } /** * ��ǰ�Ƿ���ʾ���� * * @return the gridShowing */ public boolean isGridShowing() { return gridShowing; } /** * ��������ͼ�㣨�ö���ɽ�����ꡢ���̲����� * * @param layer */ private void setTopLayer(SceneLayer layer) { if (this.topLayer != null) { removeListeners(); } this.topLayer = layer; installListeners(); } public String getCharacterId() { return characterId; } public void setCharacterId(String characterId) { this.characterId = characterId; } /** * ɾ��topLayer������¼������� */ private void removeListeners() { MouseListener[] listeners1 = getListeners(MouseListener.class); MouseMotionListener[] listeners2 = getListeners(MouseMotionListener.class); for (int i = 0; i < listeners1.length; i++) { topLayer.removeMouseListener(listeners1[i]); } for (int i = 0; i < listeners2.length; i++) { topLayer.removeMouseMotionListener(listeners2[i]); } } /** * ��topLayer��Ӽ����� */ private void installListeners() { MouseListener[] listeners1 = getListeners(MouseListener.class); MouseMotionListener[] listeners2 = getListeners(MouseMotionListener.class); for (int i = 0; i < listeners1.length; i++) { topLayer.addMouseListener(listeners1[i]); } for (int i = 0; i < listeners2.length; i++) { topLayer.addMouseMotionListener(listeners2[i]); } } public void addMouseListener(MouseListener l) { super.addMouseListener(l); topLayer.addMouseListener(l); } public void addMouseMotionListener(MouseMotionListener l) { super.addMouseMotionListener(l); topLayer.addMouseMotionListener(l); } public void removeMouseListener(MouseListener l) { super.removeMouseListener(l); topLayer.removeMouseListener(l); } public void removeMouseMotionListener(MouseMotionListener l) { super.removeMouseMotionListener(l); topLayer.removeMouseMotionListener(l); } public Point getSelectedCell() { return eventLayer.getSelectedCell(); } public Point getSelectingCell() { return eventLayer.getSelectingCell(); } // ------------------------- Actions --------------------------------// /** * ����npc���������� */ @Action public void createNewNpc() { try { Point cell = eventLayer.getSelectedCell(); if(cell == null) { cell = new Point(10, 10); } SceneNpc npc = createNpc(characterId,sceneId, cell.x,cell.y, "NPC"); replaceNpc(npc); } catch (Exception e) { e.printStackTrace(); UIUtils.showError("����NPCʧ�ܣ�",e); } } public void replaceNpc(SceneNpc npc) { try { int npcId = npc.getId(); String characterId = npc.getCharacterId(); int sceneX = npc.getSceneX(); int sceneY = npc.getSceneY(); System.out.println("replace "+characterId+" at (" + sceneX + "," + sceneY + ")"); String filename = "shape/char/"+characterId+"/stand.tcp"; Animation anim = SpriteFactory.loadAnimation(filename); Label label = new Label(anim); label.setHorizontalTextPosition(Label.CENTER); label.setVerticalTextPosition(Label.BOTTOM); label.setFont(UIUtils.TEXT_NAME_FONT); //label.setForeground(GameMain.COLOR_NAME); label.setForeground(UIUtils.COLOR_NAME); label.setBorder(spriteBorder); label.setName(String.valueOf(npcId)); label.setText(npc.getName()); Dimension prefSize = label.getPreferredSize(); label.setSize(prefSize); Point pos = sceneToLocal(sceneX,sceneY); pos.translate(-anim.getRefPixelX(), -anim.getRefPixelY()); label.setLocation(pos); draggable(label); eventLayer.add(label); } catch (Exception e) { e.printStackTrace(); UIUtils.showError("��ԭNPCʧ�ܣ�"+npc,e); } } /** * ���õ�ǰ���� * * @param filename * @return */ public void setScene(String sceneId) { this.sceneId = sceneId; File file = new File("scene/"+sceneId+".map"); this.map.loadMap(file); this.cellPanel.setSize(this.map.getWidth(), this.map.getHeight()); this.eventLayer.setSize(this.map.getWidth(), this.map.getHeight()); this.eventLayer.clearStatus(); this.setPreferredSize(this.cellPanel.getSize()); this.setSize(this.cellPanel.getSize()); reloadSceneNpcs(sceneId); } /** * @param sceneId2 */ private void reloadSceneNpcs(String sceneId) { List<SceneNpc> npcs; try { npcs = getDataFacade().findNpcsBySceneId(Integer.valueOf(sceneId)); for (SceneNpc _npc : npcs) { replaceNpc(_npc); } } catch (Exception e) { e.printStackTrace(); } } /** * @param characterId * @param sceneId * @param name TODO * @param x * @param y * @return * @throws Exception * @throws PreexistingEntityException */ private SceneNpc createNpc(String characterId, String sceneId, int sceneX, int sceneY, String name) throws PreexistingEntityException, Exception { SceneNpc npcVO = new SceneNpc(0, Integer.parseInt(sceneId), characterId, name, sceneX, sceneY, "state=stand;"); int npcId = getDataFacade().createSceneNpc(npcVO); return npcVO; } private void moveNpc(int npcId,int x,int y) { try { System.out.println("moveNpc: "+npcId+", "+x+", "+y); DataFacade dataFacade = getDataFacade(); SceneNpc npcVO = dataFacade.findSceneNpc(npcId); npcVO.setSceneX(x); npcVO.setSceneY(y); dataFacade.updateSceneNpc(npcVO); } catch (Exception e) { e.printStackTrace(); UIUtils.showError("�ƶ�npcʧ�ܣ�npcId="+npcId+", x="+x+", y="+y, e); } } private DataFacade getDataFacade() { return Application.getInstance(GameMaker.class).getDataFacade(); } private JFrame getMainFrame() { return Application.getInstance(GameMaker.class).getMainFrame(); } /** * @param label */ protected void draggable(Label label) { MouseAdapter handler = new MouseAdapter() { private Point orginLocation; @Override public void mousePressed(MouseEvent e) { if(e.getButton()==MouseEvent.BUTTON1) { orginLocation = e.getPoint(); } } @Override public void mouseReleased(MouseEvent e) { if(e.getButton()==MouseEvent.BUTTON1 && orginLocation!=null) { Label label = (Label) e.getSource(); Point location = label.getLocation(); location.translate(e.getX() - orginLocation.x, e.getY() - orginLocation.y); label.setLocation(location); Animation anim = label.getAnim(); Point scenePos = localToScene(location.x+anim.getRefPixelX(),location.y+anim.getRefPixelY()); moveNpc(Integer.valueOf(label.getName()),scenePos.x,scenePos.y); } orginLocation = null; } @Override public void mouseDragged(MouseEvent e) { if(orginLocation!=null) { Label label = (Label) e.getSource(); Point location = label.getLocation(); location.translate(e.getX() - orginLocation.x, e.getY() - orginLocation.y); label.setLocation(location); } } @Override public void mouseClicked(MouseEvent evt) { if(evt.getButton()==MouseEvent.BUTTON3) { Label label = (Label) evt.getSource(); String npcId = label.getName(); try { getDataFacade().deleteSceneNpc(Integer.valueOf(npcId)); label.getParent().remove(label); } catch (Exception ex) { ex.printStackTrace(); UIUtils.showError("�Ƴ�NPCʧ�ܣ�npcId="+npcId, ex); } evt.consume(); return; } if(evt.getButton()==MouseEvent.BUTTON1) { //����npc if (evt.getSource() instanceof Label) { Label label = (Label) evt.getSource(); String npcId = label.getName(); if(evt.getClickCount()==2) {//˫��npc showScriptDialog(npcId); return; } } } } @Override public void mouseEntered(MouseEvent e) { Label label = (Label) e.getComponent(); label.setBorder(spriteHoverBorder); //tooltip Point location = label.getLocation(); Animation anim = label.getAnim(); Point scenePos = localToScene(location.x+anim.getRefPixelX(),location.y+anim.getRefPixelY()); label.setToolTipText(label.getName()+" ("+scenePos.x+","+scenePos.y+")"); } @Override public void mouseExited(MouseEvent e) { Label label = (Label) e.getComponent(); label.setBorder(spriteBorder); } }; label.addMouseListener(handler); label.addMouseMotionListener(handler); } /** * �༭npc�ű� * @param npcId */ protected void showScriptDialog(final String npcId) { JFrame frame = getMainFrame(); final DocumentPane documentPane = createSourceCodePanel(npcId); StandardDialog dialog = new StandardDialog(frame, "�༭NPC�ű�", false) { @Override public JComponent createBannerPanel() { return null; } @Override public JComponent createContentPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); panel.add(documentPane); panel.setPreferredSize(new Dimension(600, 500)); return panel; } @Override public ButtonPanel createButtonPanel() { JButton okButton = new JButton(); okButton.setName(OK); okButton.setAction(new AbstractAction("OK") { @Override public void actionPerformed(ActionEvent e) { DocumentComponent comp = documentPane.getDocumentAt(0); CodeEditor editor = (CodeEditor) comp.getComponent(); storeScript(npcId,editor.getText()); setVisible(false); dispose(); } }); JButton closeButton = new JButton(); closeButton.setName(CLOSE); closeButton.setAction(new AbstractAction("Cancel") { public void actionPerformed(ActionEvent e) { setDialogResult(RESULT_AFFIRMED); setVisible(false); dispose(); } }); setDefaultCancelAction(closeButton.getAction()); ButtonPanel panel = new ButtonPanel(); panel.addButton(okButton); panel.addButton(closeButton); return panel; } }; dialog.pack(); dialog.setLocationRelativeTo(frame); dialog.setVisible(true); } public DocumentPane createSourceCodePanel(String npcId) { String filename = "scripts/npc/n"+npcId+".java"; DocumentPane pane = new DocumentPane(); pane.openDocument(new DocumentComponent(createTextComponent(npcId,filename), filename)); pane.setTabbedPaneCustomizer(new DocumentPane.TabbedPaneCustomizer() { public void customize(JideTabbedPane tabbedPane) { tabbedPane.setTabPlacement(JideTabbedPane.BOTTOM); } }); return pane; } public JComponent createTextComponent(String npcId,String filename) { CodeEditor area = new CodeEditor(); // area.setFont(new Font("Monospaced", Font.PLAIN, 12)); SyntaxDocument doc = new SyntaxDocument(); try { // try to start reading InputStream in = new FileInputStream(filename); if (in != null) { byte[] buff = new byte[4096]; int nch; while ((nch = in.read(buff, 0, buff.length)) != -1) { doc.insertString(doc.getLength(), new String(buff, 0, nch), null); } area.setDocument(doc); } } catch (FileNotFoundException ex) { //�����ű� area.setText(createScript(npcId)); } catch (IOException ex) { ex.printStackTrace(); UIUtils.showError("��ȡ�ű�ʧ�ܣ�", ex); } catch (BadLocationException ex) { ex.printStackTrace(); UIUtils.showError("��Ⱦ�ű�ʧ�ܣ�", ex); } area.setTokenMarker(new JavaTokenMarker()); //area.setTokenMarker(new GroovyTokenMarker()); return area; } /** * @param npcId * @return */ private String createScript(String npcId) { try { if(scriptTemplate == null) { loadScriptTemplate(); } return String.format(scriptTemplate,npcId,new java.util.Date()); } catch (IOException e) { e.printStackTrace(); UIUtils.showError("����NPC�ű�ģ��ʧ�ܣ�", e); } return null; } /** * ����npc�ű� * @param npcId * @param content */ private void storeScript(String npcId, String content) { try { if(content!=null) { String filename = "scripts/npc/n"+npcId+".java"; FileOutputStream fos = new FileOutputStream(filename); fos.write(content.getBytes()); fos.flush(); System.out.println("����NPC�ű���"+filename); } } catch (Exception e) { e.printStackTrace(); UIUtils.showError("����npc�ű�ʧ�ܣ�"+e.getMessage(), e); } } /** * @throws IOException * */ private void loadScriptTemplate() throws IOException { StringBuilder sb =new StringBuilder(1024); BufferedReader br = new BufferedReader(new InputStreamReader(GameMaker.class.getResourceAsStream("resources/npcscript.txt"))); String tmp = null; while((tmp=br.readLine())!=null) { sb.append(tmp); sb.append("\r\n"); } scriptTemplate = sb.toString(); } private Point sceneToLocal(int x,int y) { return new Point(x*cellWidth, getHeight()-y*cellHeight); } private Point localToScene(int x,int y) { return new Point(x/cellWidth, (getHeight()-y)/cellHeight); } // --------------------- Listeners -----------------------------// public void mouseClicked(MouseEvent e) { if(e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2) { createNewNpc(); } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }