package gui.simulator; import gui.simulator.Images.ImageType; import gui.simulator.SimulatorPane.Objects; 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.RenderingHints; 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 com.sun.xml.internal.stream.Entity; 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 Topbar topbar; private int festivalheight, festivalwidth; private int sideBarWidth = 200; private int pathgenerate, maxvisitors; private WalkingPath currentpath; Point2D cameraPoint = new Point2D.Double(festivalwidth/2,festivalheight/2); float cameraScale = 1; private boolean grid; private ArrayList visitors; private WalkingPathArrayList paths; Cursor rotate, pathpoint; Point2D lastClickPosition; Point lastMousePosition; Point2D lastMovedMousePosition; TexturePaint p; private Agenda agenda; public Terrain(int length, int width, SimulatorPane.Terrains terrain, Agenda agenda, SimulatorPane simulator){ //get values maxvisitors = 30; setFestivalHeight(length); setFestivalWidth(width); visitors = new ArrayList(); paths = new WalkingPathArrayList(); createCustomCursors(); //initialize sidebar & topbar sidebar = new Sidebar(sideBarWidth, 3000, this); topbar = new Topbar(this, simulator); addMouseListener(topbar); //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; } p = new TexturePaint(Images.getImage(background), new Rectangle2D.Double(0, 0, 200, 200)); this.entities = new LinkedList(); this.initEntities(); this.listeners(); this.agenda = agenda; } 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 sidebar.getFacility(e); //else selected in terrain if(e.getX() > sideBarWidth){ for(DrawEngine drawObject: entities){ if(drawObject.contains(clickPoint)){ if(pathgenerate == 1){ 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); 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){ if(SwingUtilities.isRightMouseButton(e)){ pathgenerate = 0; } }else if(pathgenerate > 1){ if(SwingUtilities.isRightMouseButton(e)){ currentpath.removeLastPoint(); if(currentpath.getPath().size() == 0){ pathgenerate = 0; } }else{ 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); } } for(WalkingPath p:paths){ p.reCalculate(); } } setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); selectedObject = null; dragObject = null; repaint(); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent e){ lastMovedMousePosition = getClickPoint(e.getPoint()); if(e.getX() < sidebar.getSideBarWidth()){ setCursor(new Cursor(Cursor.HAND_CURSOR)); }else if(pathgenerate >0){ setCursor(pathpoint); }else if(topbar.containsMouse(e.getPoint())){ setCursor(new Cursor(Cursor.HAND_CURSOR)); }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())); } for(WalkingPath p:paths){ p.reCalculate(); } } 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)); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); topbar.draw(g2, getWidth()); sidebar.draw(g2); //draw simulation field Area a1 = new Area(new Rectangle2D.Double(sideBarWidth, 0, getWidth()-sideBarWidth, getHeight())); Area a2 = new Area(topbar.getBackground()); a2.transform(new AffineTransform().getTranslateInstance(1, 1.2)); a1.subtract(a2); g2.setClip(a1); AffineTransform oldTransform = g2.getTransform(); g2.translate(sideBarWidth,0); g2.setTransform(getCamera()); 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){ 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()); } for(WalkingPath path:paths){ path.paint(g2); } for(Visitor v:visitors){ v.paint(g2); } g2.setStroke(new BasicStroke(4)); for(DrawEngine drawObject: entities){ drawObject.draw(g2); if(pathgenerate > 0){ g2.setColor(new Color(180,100,100,120)); g2.fill(new Rectangle((int)drawObject.getCenter().getX()-20, (int)drawObject.getCenter().getY()-20, 40,40)); } } //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.setTransform(oldTransform); } g2.setClip(null); } 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,paths); } if(Math.random()*500 <200){ Point2D startpoint = null; for(DrawEngine e:entities){ if(e.type == Objects.ENTRANCE){ startpoint = e.getCenter(); } } if(startpoint == null || visitors.size() >= maxvisitors) return; //No entrance found OR to many visitors, stop adding people. visitors.add(new Visitor(new Point2D.Double(-100-Math.random()*200, getFestivalHeight()-Math.random()*getFestivalHeight()), startpoint)); } topbar.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"); } public void toggleGrid(){ grid = !grid; } public void newWalkingPath(Images.ImageType imagetype){ if(pathgenerate == 0){ currentpath = new WalkingPath(imagetype); pathgenerate = 1; } } public List getEntities() { return entities; } public void clearVisitors(){ visitors.clear(); } public void setMaxVisitors(int v){ this.maxvisitors = v; } public int getMaxVisitors(){ return maxvisitors; } }