package gui.simulator; import gui.simulator.Images.ImageType; import gui.simulator.facilities.RestRoom; import gui.simulator.facilities.SimulatorStage; import gui.simulator.facilities.SnackBar; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.TexturePaint; import java.awt.Toolkit; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.SwingUtilities; import agenda.Agenda; public class Terrain extends JPanel { private List entities; private Point2D oldPosition; private double oldRotation, oldScale; private DrawEngine dragObject, selectedObject; private ImageType background; private Sidebar sidebar; private int festivalheight, festivalwidth; private int sideBarWidth = 200; private int pathgenerate = 1; private WalkingPath currentpath; private SimulatorPane.Terrains terrain; Point2D cameraPoint = new Point2D.Double(festivalwidth/2,festivalheight/2); float cameraScale = 1; private boolean grid; private ArrayList visitors; private ArrayList paths; Cursor rotate, pathpoint; Point2D lastClickPosition; Point lastMousePosition; Point2D lastMovedMousePosition; private Agenda agenda; public Terrain(int length, int width, SimulatorPane.Terrains terrain, Agenda agenda){ //get values setFestivalHeight(length); setFestivalWidth(width); grid = true; this.terrain = terrain; visitors = new ArrayList(); paths = new ArrayList(); createCustomCursors(); //initialize sidebar sidebar = new Sidebar(sideBarWidth, 3000, this); //set terrainbackground switch(terrain){ case BEACH: background = Images.ImageType.Sand; break; case GRASS: background = Images.ImageType.Grass; break; case URBAN: background = Images.ImageType.Street; break; } this.dragObject = null; this.entities = new LinkedList(); this.initEntities(); this.listeners(); //agenda this.agenda = agenda; } private void getFacility(MouseEvent e){ Point2D clickPoint = getClickPoint(e.getPoint()); DrawEngine dragObject = null; if(e.getX() < sideBarWidth) { if(e.getY() > 100 && e.getY() < 260){ dragObject = new SimulatorStage((int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); setDragObject(dragObject); }else if(e.getY() >= 260 && e.getY() < 425){ dragObject = new RestRoom((int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); setDragObject(dragObject); }else if(e.getY() >= 430 && e.getY() < 510){ dragObject = new AccessPoint(this, (int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); setDragObject(dragObject); } else if(e.getY() >= 510 && e.getY() < 610){ dragObject = new ExitPoint(this, (int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); setDragObject(dragObject); } else if(e.getY() > 610 && e.getY() < getFestivalHeight()){ dragObject = new SnackBar((int)clickPoint.getX(),(int)clickPoint.getY(), 0.3, 10); setDragObject(dragObject); } entities.add(dragObject); } } private void listeners(){ addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); lastClickPosition = clickPoint; lastMousePosition = e.getPoint(); //if selected in sidebar getFacility(e); //else selected in terrain if(e.getX() > sideBarWidth){ for(DrawEngine drawObject: entities){ if(drawObject.contains(clickPoint)){ if(pathgenerate == 1){ currentpath = new WalkingPath(); currentpath.addPoint(new Point((int)drawObject.getCenter().getX(), (int)drawObject.getCenter().getY())); currentpath.setObject1(drawObject); pathgenerate = 2; return; }else if(pathgenerate > 1){ currentpath.addPoint(new Point((int)drawObject.getCenter().getX(), (int)drawObject.getCenter().getY())); currentpath.setObject2(drawObject); paths.add(currentpath); for(int i=0; i< 200; i++){ visitors.add(new Visitor(new Point(100+(i*15),100))); visitors.get(i).walkRoute(paths.get(0)); } pathgenerate = 0; return; }else{ setCursor(new Cursor(Cursor.MOVE_CURSOR)); dragObject = drawObject; selectedObject = dragObject; oldPosition = new Point2D.Double(selectedObject.getX(), selectedObject.getY()); oldRotation = selectedObject.getScale(); oldScale = selectedObject.getScale(); //double click if(e.getClickCount() == 2){ //TODO open dialog JDialog dialog = new StageDialog(drawObject, agenda); //position Toolkit toolkit = Toolkit.getDefaultToolkit(); Dimension screenSize = toolkit.getScreenSize(); int x = (int) ((screenSize.getWidth() - dialog.getWidth()) / 2); int y = (int) ((screenSize.getHeight() - dialog.getHeight()) / 2); Point center = new Point(x, y); dialog.setLocation(center); dialog.pack(); dialog.setVisible(true); } return; } } } if(pathgenerate > 1){ currentpath.addPoint(new Point((int)getClickPoint(e.getPoint()).getX(), (int)getClickPoint(e.getPoint()).getY())); } } repaint(); } @Override public void mouseReleased(MouseEvent e) { if(selectedObject != null){ for(DrawEngine drawObject: entities){ if(drawObject == selectedObject){ continue; } if(intersection(selectedObject, drawObject)){ //move back selectedObject.setX(oldPosition.getX()); selectedObject.setY(oldPosition.getY()); selectedObject.setRotation(oldRotation); selectedObject.setScale(oldScale); } } } setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); selectedObject = null; dragObject = null; repaint(); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent e){ lastMovedMousePosition = getClickPoint(e.getPoint()); if(pathgenerate >0){ setCursor(pathpoint); }else{ for(DrawEngine drawObject: entities){ if(drawObject.contains(lastMovedMousePosition)){ setCursor(new Cursor(Cursor.HAND_CURSOR)); return; } } setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } @Override public void mouseDragged(MouseEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); if(dragObject != null){ if(SwingUtilities.isLeftMouseButton(e) && dragObject instanceof AccessPoint){ dragObject.setX(-25); dragObject.setRotation(90); if(dragObject.getY()<80){ dragObject.setY(80); } else if(dragObject.getY()>getFestivalHeight()-150){ dragObject.setY(getFestivalHeight()-150); } else { dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY())); } }else if(SwingUtilities.isLeftMouseButton(e) && dragObject instanceof ExitPoint){ dragObject.setX(getFestivalWidth()-200); dragObject.setRotation(90); if(dragObject.getY()<80){ dragObject.setY(80); } else if(dragObject.getY()>getFestivalHeight()-150){ dragObject.setY(getFestivalHeight()-150); } else { dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY())); } }else if(SwingUtilities.isLeftMouseButton(e)){ setCursor(new Cursor(Cursor.MOVE_CURSOR)); dragObject.setX(dragObject.getX() - (lastClickPosition.getX() - clickPoint.getX())); dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY())); }else if(SwingUtilities.isRightMouseButton(e)){ setCursor(rotate); dragObject.setRotation(dragObject.getRotation() + (lastClickPosition.getX() - clickPoint.getX() + lastClickPosition.getY() - clickPoint.getY())); } } else { setCursor(new Cursor(Cursor.MOVE_CURSOR)); cameraPoint = new Point2D.Double( cameraPoint.getX() + (lastMousePosition.getX() - e.getX()), cameraPoint.getY() + (lastMousePosition.getY() - e.getY()) ); } repaint(); lastMousePosition = e.getPoint(); lastClickPosition = clickPoint; } }); addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); for(DrawEngine object: entities){ //if object selected, scale object if(object.contains(clickPoint)){ double oldscale = object.getScale(); if(oldscale < 0.3){ if((e.getPreciseWheelRotation()/10.0) > 0){ object.setScale(object.getScale() * 1 + (e.getPreciseWheelRotation()/10.0)); } } else { object.setScale(object.getScale() * 1 + (e.getPreciseWheelRotation()/10.0)); } //intersect for(DrawEngine draw: entities){ if(draw != object){ if(intersection(draw, object)){ object.setScale(oldscale); } } } repaint(); return; } } //scale camera cameraScale *= 1 - (e.getPreciseWheelRotation()/10.0); repaint(); } }); } /* * Add facilities on initializing */ private void initEntities(){ //this.entities.add(new Stage(300, 10, 0.5, 10)); //this.entities.add(new Stage(400, 40, 2, 10)); } @Override public void paint(Graphics g) { super.paint(g); Graphics2D g2 = (Graphics2D) g; sidebar.draw(g2); //draw simulation field g2.setClip(new Rectangle2D.Double(sideBarWidth, 0, getWidth()-sideBarWidth, getHeight())); AffineTransform oldTransform = g2.getTransform(); g2.translate(sideBarWidth,0); g2.setTransform(getCamera()); TexturePaint p = new TexturePaint(Images.getImage(background), new Rectangle2D.Double(0, 0, 200, 200)); g2.setPaint(p); g2.fill(new Rectangle2D.Double(0,0,festivalwidth,festivalheight)); if(grid){ g2.setColor(new Color(160,160,160,120)); g2.setStroke(new BasicStroke(1)); for(int i = 0; i < (getFestivalWidth()/10)+1; i++){ g2.drawLine(i*10, 0, i*10, getFestivalHeight()); }; for(int i = 0; i < (getFestivalHeight()/10)+1; i++){ g2.drawLine(0, i*10, getFestivalWidth(), i*10); }; } if(pathgenerate > 1){ g2.setStroke(new BasicStroke(10)); currentpath.paint(g2); g2.drawLine((int)currentpath.get(currentpath.getPath().size()-1).getX(),(int)currentpath.get(currentpath.getPath().size()-1).getY(), (int)lastMovedMousePosition.getX(), (int)lastMovedMousePosition.getY()); }else{ for(WalkingPath path:paths){ path.paint(g2); } } for(Visitor v:visitors){ v.paint(g2); } for(DrawEngine drawObject: entities){ drawObject.draw(g2); if(pathgenerate > 0){ g2.fill(drawObject.getAffineTransform().createTransformedShape(new Rectangle((int)(drawObject.getX()-(drawObject.getWidth()/2)-10),(int)(drawObject.getY()-(drawObject.getHeight()/2)-10), 20, 20))); } } //draw collide boxes if(this.selectedObject != null){ Shape shape = this.selectedObject.getRect(); g2.setColor(Color.RED); g2.draw(this.selectedObject.getAffineTransform().createTransformedShape(shape)); boolean collide = false; for(DrawEngine drawEngine : entities){ if(!drawEngine.equals(this.selectedObject)){ if(intersection(this.selectedObject, drawEngine)){ collide = true; } } } if(collide){ g2.setColor(new Color(254, 0, 0, 128)); }else{ g2.setColor(new Color(0, 254, 0, 128)); } g2.fill(this.selectedObject.getAffineTransform().createTransformedShape(this.selectedObject.getRect())); g2.setClip(null); g2.setTransform(oldTransform); } } private Rectangle drawDragRectangle(DrawEngine shape){ Rectangle rectangle = null; rectangle = new Rectangle((int) (shape.getX() - shape.getDistanceToOtherObjects()), (int) (shape.getY() - shape.getDistanceToOtherObjects()), (int) (shape.getWidth() * shape.getScale() + (2 * shape.getDistanceToOtherObjects())), (int) (shape.getHeight() * shape.getScale() + (2 * shape.getDistanceToOtherObjects()))); return rectangle; } private boolean intersection(DrawEngine d1, DrawEngine d2){ Area area = new Area(d1.getAffineTransform().createTransformedShape(d1.getRect())); Area area2 = new Area(d2.getAffineTransform().createTransformedShape(d2.getRect())); area.intersect(area2); return !area.isEmpty(); } public Point2D getClickPoint(Point point) { try { return getCamera().inverseTransform(point, null); } catch (NoninvertibleTransformException e1) { e1.printStackTrace(); } return null; } private AffineTransform getCamera() { AffineTransform tx = new AffineTransform(); //start field in top left corner, next to sidebar tx.translate(-cameraPoint.getX() + sideBarWidth, -cameraPoint.getY()); //start field in middle of screen //tx.translate(-cameraPoint.getX() + getWidth()/2, -cameraPoint.getY() + getHeight()/2); tx.scale(cameraScale, cameraScale); return tx; } public void calculate(){ for(Visitor v:visitors){ v.update(visitors, entities); } for(WalkingPath p:paths){ p.reCalculate(); } } public void setFestivalHeight(int height){ this.festivalheight = height; } public void setFestivalWidth(int width){ this.festivalwidth = width; } public int getFestivalHeight(){ return festivalheight; } public int getFestivalWidth(){ return festivalwidth; } //getters and setters for sidebar public void setDragObject(DrawEngine dragObject){ this.dragObject = dragObject; } public DrawEngine getDragObject(){ return dragObject; } public void addEntity(DrawEngine dragObject){ entities.add(dragObject); } public void createCustomCursors(){ Toolkit toolkit = Toolkit.getDefaultToolkit(); Images.ImageType image; image = Images.ImageType.RotateCursor; rotate = toolkit.createCustomCursor(Images.getImage(image), new Point(14,14), "Rotate"); image = Images.ImageType.PathCursor; pathpoint = toolkit.createCustomCursor(Images.getImage(image), new Point(14,14), "Pathpoint"); } }