View Javadoc

1   package erland.game.tileadventure;
2   
3   import erland.game.GamePanelInterface;
4   import erland.game.GameEnvironmentInterface;
5   import erland.game.component.EPanel;
6   import erland.game.component.EButton;
7   
8   import javax.swing.*;
9   import java.awt.event.*;
10  import java.awt.*;
11  
12  /*
13   * Copyright (C) 2004 Erland Isaksson (erland_i@hotmail.com)
14   *
15   * This program is free software; you can redistribute it and/or
16   * modify it under the terms of the GNU General Public License
17   * as published by the Free Software Foundation; either version 2
18   * of the License, or (at your option) any later version.
19   *
20   * This program is distributed in the hope that it will be useful,
21   * but WITHOUT ANY WARRANTY; without even the implied warranty of
22   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   * GNU General Public License for more details.
24   *
25   * You should have received a copy of the GNU General Public License
26   * along with this program; if not, write to the Free Software
27   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28   * 
29   */
30  
31  /***
32   * Abstract class that implement basic behaviour in a map editor
33   * @author Erland Isaksson
34   */
35  public abstract class MapEditor implements GamePanelInterface {
36      /*** Indicates the the map editor should be closed */
37      private boolean bQuit;
38      /*** MouseListener object */
39      private MouseListener mouseListener;
40      /*** Block container for blocks in the map */
41      private IrregularBlockContainerInterface cont;
42      /*** Block container for blocks in the block selection area */
43      private IrregularBlockContainerInterface contPalette;
44      /*** Matrix with all selection blocks */
45      private MapObjectContainerInterface paletteBlocks;
46      /*** Matrix with all blocks in the map */
47      private MapObjectContainerInterface mapBlocks;
48      /*** Currently selected block in the block selection area */
49      private MapObjectInterface selectedBlock;
50      /*** The x position of the block which the pointer is hovering over in the block map area */
51      private int hoveringBlockPosX=-1;
52      /*** The x position of the block which the pointer is hovering over in the block map area */
53      private int hoveringBlockPosY=-1;
54      /*** EPanel containing all the main buttons */
55      private EPanel buttonPanel;
56      /*** MouseMotion listener */
57      private MouseMotionListener mouseMotionListener;
58      /*** Game environment object */
59      private GameEnvironmentInterface environment;
60  
61      public boolean isExit() {
62          return bQuit;
63      }
64  
65      public void exit() {
66          environment.getScreenHandler().getContainer().removeMouseListener(mouseListener);
67          environment.getScreenHandler().getContainer().removeMouseMotionListener(mouseMotionListener);
68          if(buttonPanel!=null) {
69              environment.getScreenHandler().remove(buttonPanel.getComponent());
70          }
71          exitFinish();
72      }
73  
74      /***
75       * Get block container for the map area
76       * @return The block container
77       */
78      protected abstract IrregularBlockContainerInterface getMapContainer();
79  
80      /***
81       * Get block container for the block selection area
82       * @return The block container
83       */
84      protected abstract IrregularBlockContainerInterface getPaletteContainer();
85  
86      /***
87       * Get matrix with all blocks in the block selection area
88       * @return Matrix with the blocks
89       */
90      protected abstract MapObjectContainerInterface getPaletteBlocks();
91  
92      /***
93       * Get matrix with all blocks in the map
94       * @return Matrix with the blocks
95       */
96      protected abstract MapObjectContainerInterface getMapBlocks();
97  
98  
99      /***
100      * Prepare a new block so it can be inserted in the map
101      * @param oldBlock Old block at the same position
102      * @param newBlock New block that should be inserted
103      * @return Prepared block that should be inserted, may be same as newBlock
104      * but may also be a completely new block based on newBlock and oldBlock
105      */
106     protected MapObjectInterface prepareNewBlock(MapObjectInterface oldBlock,MapObjectInterface newBlock)
107     {
108         return newBlock;
109     }
110 
111     public void init(GameEnvironmentInterface environ) {
112         bQuit = false;
113         this.environment = environ;
114 
115         mouseListener = new MouseAdapter() {
116             public void mousePressed(MouseEvent e) {
117                 if (e.getButton() == 1) {
118                     leftMousePressed(environment.getScreenHandler().getScreenX(e.getX()),environment.getScreenHandler().getScreenY(e.getY()));
119                 }
120             }
121         };
122         mouseMotionListener = new MouseMotionAdapter() {
123             public void mouseMoved(MouseEvent e) {
124                 mouseHovering(environment.getScreenHandler().getScreenX(e.getX()),environment.getScreenHandler().getScreenY(e.getY()));
125             }
126 
127             public void mouseDragged(MouseEvent e) {
128                 if ((e.getModifiers() & e.BUTTON1_MASK)!=0) {
129                     leftMouseDragged(environment.getScreenHandler().getScreenX(e.getX()),environment.getScreenHandler().getScreenY(e.getY()));
130                 }
131             }
132         };
133         environment.getScreenHandler().getContainer().addMouseListener(mouseListener);
134         environment.getScreenHandler().getContainer().addMouseMotionListener(mouseMotionListener);
135         buttonPanel = initButtonPanel();
136         if(buttonPanel!=null) {
137             initDefaultButtons(buttonPanel);
138             initButtons(buttonPanel);
139             environment.getScreenHandler().add(buttonPanel.getComponent());
140         }
141 
142         contPalette = getPaletteContainer();
143         cont = getMapContainer();
144         initFinish();
145         updateBlocks();
146 
147         environment.getScreenHandler().getContainer().setBackground(Color.black);
148     }
149 
150     /***
151      * Called when a block on the map is clicked, this method will either insert the
152      * selected block in the clicked map position or remove the current block at the
153      * map position
154      * @param posX X position of the block in the map that was clicked
155      * @param posY Y position of the block in the map that was clicked
156      */
157     protected void clickedMapBlock(int posX, int posY)
158     {
159         if(selectedBlock!=null) {
160             setMapBlock(prepareNewBlock(mapBlocks.getBlock(posX,posY,getMapPosZ()),cloneBlock(selectedBlock,cont,posX,posY,getMapPosZ())),posX,posY,getMapPosZ());
161         }else {
162             if(isEmptyAllowed()) {
163                 setMapBlock(null,posX,posY,getMapPosZ());
164             }
165         }
166     }
167 
168     /***
169      * Uppdates the map with a new block
170      * @param block The new block to insert in map
171      * @param posX The x position of the new block
172      * @param posY The y position of the new block
173      * @param posZ The z position of the new block
174      */
175     protected void setMapBlock(MapObjectInterface block, int posX, int posY, int posZ) {
176         mapBlocks.setBlock(block,posX,posY,posZ);
177     }
178 
179     /***
180      * Called when the mouse pointer is hovering over a block on the map , this method will
181      * just be called to make it possible to show which block the mouse is hovering over
182      * The method is called with -1 in both parameters if the mouse is not hovering over any block
183      * @param posX X position of the block in the map that was hovered over
184      * @param posY Y position of the block in the map that was hovered over
185      */
186     protected void hoverMapBlock(int posX, int posY)
187     {
188         hoveringBlockPosX = posX;
189         hoveringBlockPosY = posY;
190     }
191 
192     /***
193      * Called when a block in the selection area is clicked, this method will make
194      * the clicked block the currently selected block or if there were no block
195      * at the clicked make no block selected
196      * @param posX X position of the block in the selection area that was clicked
197      * @param posY Y position of the block in the selection area that was clicked
198      */
199     protected void clickedSelectBlock(int posX,int posY)
200     {
201         if(paletteBlocks.getBlock(posX,posY,getPalettePosZ())!=null) {
202             selectedBlock = paletteBlocks.getBlock(posX,posY,getPalettePosZ());
203         }else {
204             selectedBlock = null;
205         }
206     }
207     protected void leftMouseDragged(int x, int y)
208     {
209         Rectangle rc = new Rectangle(cont.getOffsetX(),cont.getOffsetY(),cont.getDrawingSizeX(),cont.getDrawingSizeY());
210         if(rc.contains(x,y)) {
211 
212             int posX = cont.getBlockPositionX(x,y,getMapPosZ()*cont.getSquareSizeZ());
213             int posY = cont.getBlockPositionY(x,y,getMapPosZ()*cont.getSquareSizeZ());
214             if(posX>=0 && posX<mapBlocks.getSizeX() && posY>=0 && posY<mapBlocks.getSizeY()) {
215                 clickedMapBlock(posX,posY);
216                 hoverMapBlock(posX,posY);
217             }else {
218                 hoverMapBlock(-1,-1);
219             }
220         }
221     }
222     protected void mouseHovering(int x, int y)
223     {
224         Rectangle rc = new Rectangle(cont.getOffsetX(),cont.getOffsetY(),cont.getDrawingSizeX(),cont.getDrawingSizeY());
225         if(rc.contains(x,y)) {
226             int posX = cont.getBlockPositionX(x,y,getMapPosZ()*cont.getSquareSizeZ());
227             int posY = cont.getBlockPositionY(x,y,getMapPosZ()*cont.getSquareSizeZ());
228             if(posX>=0 && posX<mapBlocks.getSizeX() && posY>=0 && posY<mapBlocks.getSizeY()) {
229                 hoverMapBlock(posX,posY);
230             }else {
231                 hoverMapBlock(-1,-1);
232             }
233         }else {
234             hoverMapBlock(-1,-1);
235         }
236     }
237     protected void leftMousePressed(int x, int y)
238     {
239         Rectangle rc = new Rectangle(cont.getOffsetX(),cont.getOffsetY(),cont.getDrawingSizeX(),cont.getDrawingSizeY());
240         Rectangle rcSelect = new Rectangle(contPalette.getOffsetX(),contPalette.getOffsetY(),contPalette.getDrawingSizeX(),contPalette.getDrawingSizeY());
241         if(rc.contains(x,y)) {
242             leftMouseDragged(x,y);
243         }else if(rcSelect.contains(x,y)) {
244             int posX = contPalette.getBlockPositionX(x,y,getMapPosZ()*cont.getSquareSizeZ());
245             int posY = contPalette.getBlockPositionY(x,y,getMapPosZ()*cont.getSquareSizeZ());
246             if(posX>=0 && posX<paletteBlocks.getSizeX() && posY>=0 && posY<paletteBlocks.getSizeY()) {
247                 clickedSelectBlock(posX,posY);
248             }
249         }
250     }
251 
252     /***
253      * Update all blocks
254      */
255     protected void updateBlocks()
256     {
257         paletteBlocks = getPaletteBlocks();
258         mapBlocks = getMapBlocks();
259     }
260     public void update() {
261     }
262 
263     /***
264      * Draw the specified block
265      * @param g Graphics object to draw on
266      * @param block Block to draw
267      */
268     protected void drawBlock(Graphics g, MapObjectInterface block) {
269         block.draw(g);
270     }
271 
272     /***
273      * Clone specified block
274      * @param block Block to clone
275      * @param cont Block container to put new block in
276      * @param x X position to put new block at
277      * @param y Y position to put new block at
278      * @param z Z position to put new block at
279      * @return Newly cloned block
280      */
281     protected abstract MapObjectInterface cloneBlock(MapObjectInterface block,IrregularBlockContainerInterface cont, int x, int y, int z);
282 
283     /***
284      * Checks if it is allowed to have positions in the map without any block
285      * @return true/false (Empty positions allowed/No empty positions allowed)
286      */
287     protected abstract boolean isEmptyAllowed();
288 
289     /***
290      * Create and initialize all buttons
291      * @param panel EPanel to put buttons on
292      */
293     protected void initButtons(EPanel panel)
294     {
295     }
296     /***
297      * Called once when the initialization of the map editor is finished
298      */
299     protected void initFinish()
300     {
301     }
302 
303     /***
304      * Called once when exit of the map editor is finished
305      */
306     protected void exitFinish()
307     {
308     }
309 
310     /***
311      * Called when the standard save button is pressed, the current blocks in
312      * the map area should be saved to the map
313      * @param blocks The blocks in the map area
314      */
315     protected void saveButton(MapObjectContainerInterface blocks)
316     {
317     }
318     /***
319      * Called when the standard load button is pressed, a new map should be
320      * loaded
321      */
322     protected void loadButton()
323     {
324     }
325     /***
326      * Called when the standard exit button is pressed, the map editor should
327      * exit
328      */
329     protected void exitButton()
330     {
331         bQuit = true;
332     }
333     /*** Standard Exit button, used in {@link #getDefaultButtons} */
334     protected final static int BUTTON_EXIT=1;
335     /*** Standard Save button, used in {@link #getDefaultButtons} */
336     protected final static int BUTTON_SAVE=2;
337     /*** Standard Load button, used in {@link #getDefaultButtons} */
338     protected final static int BUTTON_LOAD=3;
339     /***
340      * Called to get which default buttons that should be available, the return value
341      * is a bitmask composed by {@link #BUTTON_EXIT}, {@link #BUTTON_LOAD}, {@link #BUTTON_SAVE}
342      * @return Bitmask that indicates which default buttons that should be used
343      */
344     protected int getDefaultButtons()
345     {
346         return BUTTON_EXIT|BUTTON_SAVE|BUTTON_LOAD;
347     }
348 
349     /***
350      * Create and initialize default butons
351      * @param panel EPanel which the buttons should be added to
352      */
353     protected void initDefaultButtons(EPanel panel)
354     {
355         int defaultbuttons = getDefaultButtons();
356         if((defaultbuttons & BUTTON_EXIT)!=0) {
357             EButton b = EButton.create("Exit");
358             panel.getContainer().add(b.getComponent());
359             b.addActionListener(new  ActionListener() {
360                 public void actionPerformed(ActionEvent e) {
361                     exitButton();
362                 }
363             });
364         }
365         if((defaultbuttons & BUTTON_SAVE)!=0) {
366             EButton b = EButton.create("Save");
367             panel.getContainer().add(b.getComponent());
368             b.addActionListener(new  ActionListener() {
369                 public void actionPerformed(ActionEvent e) {
370                     saveButton(mapBlocks);
371                 }
372             });
373         }
374         if((defaultbuttons & BUTTON_LOAD)!=0) {
375             EButton b = EButton.create("Load");
376             panel.getContainer().add(b.getComponent());
377             b.addActionListener(new  ActionListener() {
378                 public void actionPerformed(ActionEvent e) {
379                     loadButton();
380                 }
381             });
382         }
383     }
384     /***
385      * Create and initialize button panel
386      * @return The newly created EPanel for the buttons
387      */
388     protected EPanel initButtonPanel()
389     {
390         EPanel panel = EPanel.create();
391         panel.getContainer().setSize(environment.getScreenHandler().getWidth()/5, environment.getScreenHandler().getHeight());
392         panel.getContainer().setLocation(environment.getScreenHandler().getWidth()*4/5,0);
393 
394         panel.getContainer().setLayout(new BoxLayout(panel.getContainer(), BoxLayout.Y_AXIS));
395         return panel;
396     }
397 
398     /***
399      * Called everything normal has been drawed, can be used to do extra drawing on top of
400      * the other graphics
401      * @param g The Graphics object to draw on
402      */
403     protected void drawFinish(Graphics g)
404     {
405     }
406 
407     public abstract void drawMapBlocks(Graphics g, MapObjectContainerInterface blocks);
408 
409     public abstract void drawSelectedFrame(Graphics g, MapObjectInterface selectedBlock);
410 
411     public abstract void drawHoveringFrame(Graphics g, int posX, int posY);
412 
413     public void drawPaletteBlocks(Graphics g, MapObjectContainerInterface paletteBlocks) {
414         for(int x=0;x<paletteBlocks.getSizeX();x++) {
415             for(int y=0;y<paletteBlocks.getSizeY();y++) {
416                 for (int z = 0; z < paletteBlocks.getSizeZ(); z++) {
417                     if(contPalette.getVisible(x,y,z)) {
418                         if(paletteBlocks.getBlock(x,y,z)!=null) {
419                             drawBlock(g,paletteBlocks.getBlock(x,y,z));
420                         }
421                     }
422                 }
423             }
424         }
425     }
426     public void draw() {
427         Graphics g = environment.getScreenHandler().getCurrentGraphics();
428         g.clearRect(0,0,environment.getScreenHandler().getWidth(),environment.getScreenHandler().getHeight());
429         g.setColor(Color.red);
430         g.drawRect(cont.getOffsetX()-1,cont.getOffsetY()-1,cont.getDrawingSizeX()+1,cont.getDrawingSizeY()+1);
431         g.drawRect(contPalette.getOffsetX()-1,contPalette.getOffsetY()-1,contPalette.getDrawingSizeX()+1,contPalette.getDrawingSizeY()+1);
432         g.setClip(cont.getOffsetX(),cont.getOffsetY(),cont.getDrawingSizeX(),cont.getDrawingSizeY());
433         drawMapBlocks(g,mapBlocks);
434         g.setClip(contPalette.getOffsetX(),contPalette.getOffsetY(),contPalette.getDrawingSizeX(),contPalette.getDrawingSizeY());
435         drawPaletteBlocks(g, paletteBlocks);
436         g.setClip(null);
437 
438         if(selectedBlock!=null) {
439             g.setColor(Color.white);
440             drawSelectedFrame(g,selectedBlock);
441         }
442         if(hoveringBlockPosX>=0 && hoveringBlockPosY>=0) {
443             drawHoveringFrame(g,hoveringBlockPosX,hoveringBlockPosY);
444         }
445         drawFinish(g);
446 
447         environment.getScreenHandler().paintComponents(g);
448     }
449 
450     public void setCheatmode(boolean enable) {
451     }
452 
453     public GameEnvironmentInterface getEnvironment() {
454         return environment;
455     }
456 
457     protected int getMapPosZ() {
458         return 0;
459     }
460     protected int getPalettePosZ() {
461         return 0;
462     }
463 }