package nars.lab.grid2d.main; import automenta.vivisect.swing.NWindow; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.swing.JPanel; import nars.NAR; import nars.lab.grid2d.main.Cell.Logic; import nars.lab.grid2d.main.Cell.Material; import nars.lab.grid2d.gui.EditorPanel; //import nars.lab.grid2d.particle.ParticleSystem; import processing.core.PApplet; import static processing.core.PConstants.DOWN; import static processing.core.PConstants.LEFT; import static processing.core.PConstants.RIGHT; import static processing.core.PConstants.UP; import processing.core.PVector; public class Grid2DSpace extends PApplet { public static boolean world_used=false; public PVector target = new PVector(25, 25); //need to be init equal else feedback will public PVector current=new PVector(0, 0); ///////////////HAMLIB //processingjs compatibility layer int mouseScroll = 0; public final Hauto cells; public List<GridObject> objects = new ArrayList(); ProcessingJs processingjs = new ProcessingJs(); //Hnav 2D navigation system Hnav hnav = new Hnav(); //Object float selection_distance = 10; public float maxNodeSize = 40f; /** timing */ float FrameRate = 50f; int automataPeriod = 1; //how many cycles between each automata update int agentPeriod = 1; //how many cycles between each agent update boolean drawn = false; Hsim hsim = new Hsim(); Hamlib hamlib = new Hamlib(); public Button getBack; public Button conceptsView; public Button memoryView; public Button fetchMemory; float sx = 800; float sy = 800; long lasttime = -1; double realtime; //public ParticleSystem particles; public NAR nar; public Grid2DSpace(Hauto cells, NAR nar) { super(); this.cells = cells; world_used=true; this.nar=nar; init(); } public void add(GridObject g) { objects.add(g); g.init(this); } public NWindow newWindow(int width, int height, final boolean exitOnClose) { NWindow j = new NWindow("") { @Override protected void close() { stop(); destroy(); getContentPane().removeAll(); if (exitOnClose) System.exit(0); } }; Container content = j.getContentPane(); content.setLayout(new BorderLayout()); JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT)); /*final JCheckBox syntaxEnable = new JCheckBox("Syntax"); syntaxEnable.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { } }); menu.add(syntaxEnable); */ EditorPanel editor = new EditorPanel(this); NWindow editorWindow = new NWindow("Edit", editor); editorWindow.setSize(200, 400); editorWindow.setVisible(true); content.add(menu, BorderLayout.NORTH); content.add(this, BorderLayout.CENTER); j.setSize(width, height);//initial size of the window j.setVisible(true); return j; } @Override protected void resizeRenderer(int newWidth, int newHeight) { super.resizeRenderer(newWidth, newHeight); //To change body of generated methods, choose Tools | Templates. drawn = false; } public void mouseScrolled() { hamlib.mouseScrolled(); } @Override public void keyPressed() { hamlib.keyPressed(); } @Override public void mouseMoved() { hamlib.mouseMoved(); } @Override public void mouseReleased() { hamlib.mouseReleased(); } @Override public void mouseDragged() { hamlib.mouseDragged(); } @Override public void mousePressed() { hamlib.mousePressed(); } public void automataclicked(float x, float y) { if (x < 0 || y < 0) { return; } float realx = x / rendersize; float realy = y / rendersize; if (realx >= cells.w || realy >= cells.h) { return; } cells.clicked((int)realx,(int)realy,this); } public void updateAutomata() { cells.Exec(); } public void update(TestChamber s) { realtime = System.nanoTime() / 1.0e9; if (time % automataPeriod == 0 || s.executed) { updateAutomata(); } if (time % agentPeriod == 0 || s.executed) { try { for (GridObject g : objects) { Effect e = (g instanceof GridAgent) ? ((GridAgent)g).perceiveNext() : null; g.update(e); if (g instanceof GridAgent) { GridAgent b = (GridAgent)g; if (b.actions.size() > 0) { Action a = b.actions.pop(); if (a!=null) { process(b, a); } } } } } catch(Exception ex) {} } s.executed=false; } @Override public void draw() { background(0, 0, 0/*, 0.001f*/); pushMatrix(); hnav.Transform(); hrend_DrawBegin(); drawGround(); drawObjects(); drawParticles(); hrend_DrawEnd(); //popMatrix(); popMatrix(); hrend_DrawGUI(); } public void process(GridAgent agent, Action action) { Effect e = action.process(this, agent); if (e!=null) { agent.perceive(e); } } void hrend_DrawBegin() { } void hrend_DrawEnd() { //fill(0); //text("Hamlib simulation system demonstration", 0, -5); //stroke(255, 255, 255); //noStroke(); /*if (lastclicked != null) { fill(255, 0, 0); ellipse(lastclicked.x, lastclicked.y, 10, 10); }*/ } public void hrend_DrawGUI() { fill(255); // rect(10,10,10,10); } @Override public void setup() { if (FrameRate == 0) noLoop(); else frameRate(FrameRate); //particles = new ParticleSystem(this); } int time = 0; float rendersize = 1; public int getTime() { return time; } public double getRealtime() { return realtime; } // enum MotionEffect { // Moved, PainfullyMoved, TooHigh, TooSolid /* collision, impenetrable, bump */, Stuck /* flypaper, quicksand */, TooFar // } public String whyNonTraversible(GridAgent agent, int x, int y, int tx, int ty) { int dx = Math.abs(tx-x); int dy = Math.abs(ty-y); if (!((dx <= 1) && (dy <= 1))) return "Too far"; if ((tx < 0) || (ty < 0) || (tx >= cells.w) || (ty >= cells.h)) return "Out of bounds: " + tx + " " + ty; Cell from = cells.at(x, y); Cell to = cells.at(tx, ty); //System.out.println(to + " " + to.material); if ((to.material == Material.StoneWall) || to.is_solid || to.material==Material.Water || to.logic==Logic.BRIDGE || to.logic==Logic.UNCERTAINBRIDGE) return "Too solid"; final float maxTraversableHeight = 8; float dHeight = to.height - from.height; //if (dHeight > maxTraversableHeight) // return "Too high"; return null; } public Effect getMotionEffect(GridAgent agent, Action a, int x, int y, int tx, int ty) { String reason = whyNonTraversible(agent, x, y, tx, ty); if (reason == null) { return new Effect(a, true, getTime(), "Moved"); } else { return new Effect(a, false, getTime(), reason); } } public void drawObjects() { pushMatrix(); //shift half a cell down and right so that when an object draws, it's centerd in the middle of a cell. translate(rendersize/4f, rendersize/4f); for (int i = 0; i < objects.size(); i++) objects.get(i).draw(); popMatrix(); } public void drawParticles() { //PImage b = particles.particleImage; //this.blend(b, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight(), PImage.ADD); /* particles.tick(); //crashes for (Particle p : particles.p) { fill(p.rgba); rect(p.xPos, p.yPos, 0.1f,0.1f); }*/ } public void drawGround() { time++; //for speed: //strokeCap(SQUARE); //strokeJoin(PROJECT); noStroke(); //Hauto h=cells; for (int i = 0; i < cells.w; i++) { for (int j = 0; j < cells.h; j++) { Cell c = cells.readCells[i][j]; float x = i*rendersize; float y = j*rendersize; pushMatrix(); translate(x, y); c.draw(this,j==0 || i==0 || i==cells.w-1 || j==cells.w-1,hnav.MouseToWorldCoordX(width/2),hnav.MouseToWorldCoordY(height/2),x,y,hnav.zoom); popMatrix(); } } } class ProcessingJs { ProcessingJs() { addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent evt) { mouseScroll = -evt.getWheelRotation(); mouseScrolled(); } }); } } class Hnav { private float savepx = 0; private float savepy = 0; private int selID = 0; private float zoom = 43.0f; private float difx = -750; private float dify = -1300; private int lastscr = 0; private boolean EnableZooming = true; private float scrollcamspeed = 1.1f; float MouseToWorldCoordX(int x) { return 1 / zoom * (x - difx - width / 2); } float MouseToWorldCoordY(int y) { return 1 / zoom * (y - dify - height / 2); } private boolean md = false; void mousePressed() { md = true; if (mouseButton == RIGHT) { savepx = mouseX; savepy = mouseY; } drawn = false; } void mouseReleased() { md = false; } void mouseDragged() { if (mouseButton == RIGHT) { difx += (mouseX - savepx); dify += (mouseY - savepy); savepx = mouseX; savepy = mouseY; } drawn = false; } private float camspeed = 1.0f; private float scrollcammult = 0.92f; boolean keyToo = true; void keyPressed() { if ((keyToo && key == 'w') || keyCode == UP) { dify += (camspeed); } if ((keyToo && key == 's') || keyCode == DOWN) { dify += (-camspeed); } if ((keyToo && key == 'a') || keyCode == LEFT) { difx += (camspeed); } if ((keyToo && key == 'd') || keyCode == RIGHT) { difx += (-camspeed); } if (!EnableZooming) { return; } if (key == '-' || key == '#') { float zoomBefore = zoom; zoom *= scrollcammult; difx = (difx) * (zoom / zoomBefore); dify = (dify) * (zoom / zoomBefore); } if (key == '+') { float zoomBefore = zoom; zoom /= scrollcammult; difx = (difx) * (zoom / zoomBefore); dify = (dify) * (zoom / zoomBefore); } drawn = false; } void Init() { difx = -width / 2; dify = -height / 2; } void mouseScrolled() { if (!EnableZooming) { return; } float zoomBefore = zoom; if (mouseScroll > 0) { zoom *= scrollcamspeed; } else { zoom /= scrollcamspeed; } difx = (difx) * (zoom / zoomBefore); dify = (dify) * (zoom / zoomBefore); drawn = false; } void Transform() { translate(difx + 0.5f * width, dify + 0.5f * height); scale(zoom, zoom); } } ////Object management - dragging etc. class Hsim { ArrayList obj = new ArrayList(); void Init() { smooth(); } void mousePressed() { if (mouseButton == LEFT) { checkSelect(); float x = hnav.MouseToWorldCoordX(mouseX); float y = hnav.MouseToWorldCoordY(mouseY); automataclicked(x, y); } } boolean dragged = false; void mouseDragged() { if (mouseButton == LEFT) { dragged = true; dragElems(); } mousePressed(); } void mouseReleased() { dragged = false; //selected = null; } void dragElems() { /* if (dragged && selected != null) { selected.x = hnav.MouseToWorldCoordX(mouseX); selected.y = hnav.MouseToWorldCoordY(mouseY); hsim_ElemDragged(selected); } */ } void checkSelect() { /* double selection_distanceSq = selection_distance*selection_distance; if (selected == null) { for (int i = 0; i < obj.size(); i++) { Vertex oi = (Vertex) obj.get(i); float dx = oi.x - hnav.MouseToWorldCoordX(mouseX); float dy = oi.y - hnav.MouseToWorldCoordY(mouseY); float distanceSq = (dx * dx + dy * dy); if (distanceSq < (selection_distanceSq)) { selected = oi; hsim_ElemClicked(oi); return; } } } */ } } //Hamlib handlers class Hamlib { void Init() { noStroke(); hnav.Init(); hsim.Init(); } void mousePressed() { hnav.mousePressed(); hsim.mousePressed(); } void mouseDragged() { hnav.mouseDragged(); hsim.mouseDragged(); } void mouseReleased() { hnav.mouseReleased(); hsim.mouseReleased(); } public void mouseMoved() { } void keyPressed() { hnav.keyPressed(); } void mouseScrolled() { hnav.mouseScrolled(); } void Camera() { } } static List<PVector> Reconstruct_Taken_Path(Map<PVector, PVector> parent, PVector start, PVector target) { List<PVector> path = new ArrayList<>(); path.add( target ); while (!path.get(path.size()-1).equals(start)) { //since bfs found a solution, start is included for sure and thus this loop terminates for sure path.add(parent.get(path.get(path.size()-1))); } Collections.reverse(path); return path; } static List<PVector> Shortest_Path(Grid2DSpace s, GridAgent a, PVector start, PVector target) { Set<PVector> avoid = new HashSet<>(); Map<PVector, PVector> parent = new HashMap<>(); ArrayDeque<PVector> queue = new ArrayDeque<>(); queue.add(start); while (!queue.isEmpty()) { PVector active = queue.removeFirst(); if (avoid.contains(active)) continue; avoid.add(active); if (active.equals(target)) { return Reconstruct_Taken_Path(parent, start, target); } for (int i = 0; i < 4; i++) { PVector x = new PVector(); switch (i) { case 0: x.set(active.x+1, active.y); break; case 1: x.set(active.x-1, active.y); break; case 2: x.set(active.x, active.y+1); break; case 3: x.set(active.x, active.y-1); break; } if (avoid.contains(x) || s.whyNonTraversible(a, (int)active.x, (int)active.y, (int)x.x, (int)x.y)!=null) continue; parent.put(x, active); queue.add(x); } } return null; } }