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
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 }