/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package automenta.vivisect.swing; import automenta.vivisect.Vis; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; 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.event.MouseEvent; /** * * @author me */ public class PCanvas extends PApplet implements HierarchyListener { int mouseScroll = 0; Hnav hnav = new Hnav(); float zoom = 0.1f; float scale = 1f; float selection_distance = 10; float FrameRate = 25f; boolean drawn = false; float motionBlur = 0.0f; private final Vis vis; float camspeed = 20.0f; float scrollcammult = 0.92f; boolean keyToo = true; float savepx = 0; float savepy = 0; int selID = 0; float difx = 0; float dify = 0; int lastscr = 0; boolean EnableZooming = true; float scrollcamspeed = 1.1f; public PCanvas() { this(null); } public PCanvas(Vis vis) { this(vis, 26); } public PCanvas(Vis vis, int frameRate) { super(); this.FrameRate = frameRate; init(); if ((vis == null) && (this instanceof Vis)) { //for subclasses: vis = (Vis)this; } this.vis = vis; vis.init(this); } float MouseToWorldCoordX(final int x) { return 1 / zoom * (x - difx - width / 2); } float MouseToWorldCoordY(final int y) { return 1 / zoom * (y - dify - height / 2); } public float getPanX() { return difx; } public float getPanY() { return dify; } public void setPanX(float px) { difx = -px; } public void setPanY(float py) { dify = -py; } public float getCursorX() { return MouseToWorldCoordX(mouseX); } public float getCursorY() { return MouseToWorldCoordY(mouseY); } @Override protected void resizeRenderer(int newWidth, int newHeight) { if ((newWidth > 0) && (newHeight > 0)) { super.resizeRenderer(newWidth, newHeight); drawn = false; } } public void mouseScrolled() { hnav.mouseScrolled(); } @Override public void keyPressed() { hnav.keyPressed(); } @Override public void mouseMoved() { } @Override public void mouseReleased() { hnav.mouseReleased(); super.mouseReleased(); } @Override public void mouseDragged() { hnav.mouseDragged(); super.mouseDragged(); } @Override public void mousePressed() { hnav.mousePressed(); super.mousePressed(); } @Override public void draw() { if (drawn) { return; } drawn = false; if (motionBlur > 0) { fill(0, 0, 0, 255f * (1.0f - motionBlur)); rect(0, 0, getWidth(), getHeight()); } else { background(0, 0, 0);//, 0.001f); } hnav.applyTransform(); vis.draw(g); } public void setMotionBlur(float motionBlur) { this.motionBlur = motionBlur; } public float getMotionBlur() { return motionBlur; } @Override public void mouseWheel(MouseEvent event) { super.mouseWheel(event); mouseScroll = -event.getCount(); mouseScrolled(); } @Override public void setup() { //size(500,500,P3D); frameRate(FrameRate); if (isGL()) { textFont(createDefaultFont(16)); smooth(); System.out.println("Processing.org enabled OpenGL"); } } @Override public void addNotify() { super.addNotify(); addHierarchyListener(this); } @Override public void removeNotify() { removeHierarchyListener(this); super.removeNotify(); } @Override public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { boolean showing = isShowing(); onShowing(showing); } } protected void onShowing(boolean showing) { vis.onVisible(showing); if (showing) { //restart loop? can this even happen //throw new RuntimeException("if this happens, looping state should be restored here"); } else { noLoop(); } } public PCanvas setFrameRate(float frameRate) { this.FrameRate = frameRate; frameRate(FrameRate); return this; } public float getFrameRate() { return frameRate; } public PCanvas setZoom(float x, float y, float z) { setPanX(x); setPanY(y); setZoom(z); return this; } public PCanvas setZoom(float f) { zoom = f; return this; } public float getZoom() { return zoom; } /** zoom to a rectangular region */ public void setZoom(float cx, float cy, float width, float height) { //TODO add margin, right-click zoom out //System.out.println("auto-zoom: " + cx + " " + cy + " " + width + " " + height); //https://github.com/automenta/automenta.spacegraphj/blob/master/spacegraph/automenta/spacegraph/control/FractalControl.java#L128 // float targetZ = getTargetDepth(width, height); //TODO calculate correct height float targetZ = this.width / Math.max(width,height); //System.out.print(getPanX() + " " + getPanY() + " " + getZoom() + " --> "); float tx = (cx) * targetZ; float ty = (cy) * targetZ; //System.out.println(tx + " " + ty + " " + targetZ); setZoom(tx, ty, targetZ); } /*static float getTargetDepth(float width, float height) { float zoomDilation = 1.0f; float r = Math.max(width, height) / 2.0f * zoomDilation; final float focus = (float)Math.PI/4f; return (float) (r * Math.sin(Math.PI / 2.0 - focus / 2.0) / Math.sin(focus / 2.0)); }*/ class Hnav { private boolean md = false; void mousePressed() { md = true; if (mouseButton == RIGHT) { savepx = mouseX; savepy = mouseY; redraw(); } } void mouseReleased() { md = false; } void mouseDragged() { if (mouseButton == RIGHT) { difx += (mouseX - savepx); dify += (mouseY - savepy); savepx = mouseX; savepy = mouseY; redraw(); } } 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); } redraw(); 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); redraw(); drawn = false; } void applyTransform() { 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(); // } // } // boolean dragged = false; // // void mouseDragged() { // if (mouseButton == LEFT) { // dragged = true; // dragElems(); // } // } // // 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; // } // } // } // */ // } // } }