Mercurial > hg > accesspd
view java/src/uk/ac/qmul/eecs/ccmi/haptics/FalconHaptics.java @ 1:e3935c01cde2 tip
moved license of PdPersistenceManager to the beginning of the file
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Tue, 08 Jul 2014 19:52:03 +0100 |
parents | 78b7fc5391a2 |
children |
line wrap: on
line source
/* CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.qmul.eecs.ccmi.haptics; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.geom.Line2D; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.BitSet; import java.util.HashMap; import java.util.ListIterator; import uk.ac.qmul.eecs.ccmi.utils.OsDetector; import uk.ac.qmul.eecs.ccmi.utils.PreferencesService; import uk.ac.qmul.eecs.ccmi.utils.ResourceFileWriter; class FalconHaptics extends Thread implements Haptics { static Haptics createInstance(HapticListenerThread listener) { if(OsDetector.has64BitJVM()){// no 64 native library supported yet return null; } if(OsDetector.isWindows()){ /* create a directory for the dll distributed with HAPI library */ String libDir = PreferencesService.getInstance().get("dir.libs", System.getProperty("java.io.tmpdir")); File hapiDir = new File(libDir,"HAPI"); hapiDir.mkdir(); /* try to load .dll's. First copy it in the home/ccmi_editor_data/lib directory */ String[] dlls = {"HAPI/pthreadVC2.dll","HAPI/FreeImage.dll","HAPI/freeglut.dll", "HAPI/H3DUtil_vc9.dll","HAPI/HAPI_vc9.dll","FalconHaptics.dll"}; ResourceFileWriter fileWriter = new ResourceFileWriter(); for(String dll : dlls){ URL url = OmniHaptics.class.getResource(dll); fileWriter.setResource(url); fileWriter.writeOnDisk(libDir, dll); String path = fileWriter.getFilePath(); try{ if(path == null) throw new UnsatisfiedLinkError(dll+" missing"); System.load( path ); }catch(UnsatisfiedLinkError e){ System.err.println(e.getMessage()); e.printStackTrace(); return null; } } }else{ return null; } FalconHaptics falcon = new FalconHaptics("FalconHaptics"); falcon.hapticListener = listener; /* start up the listener which immediately stops, waiting for commands */ if(!falcon.hapticListener.isAlive()) falcon.hapticListener.start(); /* start up the haptics thread which issues commands from the java to the c++ thread */ falcon.start(); synchronized(falcon){ try { falcon.wait(); }catch (InterruptedException ie) { throw new RuntimeException(ie); // must never happen } } if(falcon.initFailed) return null; else return falcon; } private FalconHaptics(String threadName){ super(threadName); nodes = new HashMap<String,ArrayList<Node>>(); edges = new HashMap<String,ArrayList<Edge>>(); currentNodes = Empties.EMPTY_NODE_LIST; currentEdges = Empties.EMPTY_EDGE_LIST; attractTo = 0; } private native int initFalcon(int width, int height) throws IOException ; @Override public void addNewDiagram(String diagramName) { ArrayList<Node> cNodes = new ArrayList<Node>(30); ArrayList<Edge> cEdges = new ArrayList<Edge>(30); nodes.put(diagramName, cNodes); edges.put(diagramName, cEdges); synchronized(this){ currentNodes = cNodes; currentEdges = cEdges; collectionsChanged = true; } } @Override public synchronized void switchDiagram(String diagramName) { if(!nodes.containsKey(diagramName)) throw new IllegalArgumentException("Diagram not found among added diagrams:" + diagramName); currentNodes = nodes.get(diagramName); currentEdges = edges.get(diagramName); collectionsChanged = true; } @Override public synchronized void removeDiagram(String diagramNameToRemove, String diagramNameOfNext) { if(!nodes.containsKey(diagramNameToRemove)) throw new IllegalArgumentException("Diagram not found among added diagrams:" + diagramNameToRemove); nodes.remove(diagramNameToRemove); edges.remove(diagramNameToRemove); if(diagramNameOfNext == null){ currentNodes = Empties.EMPTY_NODE_LIST; currentEdges = Empties.EMPTY_EDGE_LIST; }else { if(!nodes.containsKey(diagramNameOfNext)) throw new IllegalArgumentException("Diagram not found among added diagrams:" + diagramNameOfNext); currentNodes = nodes.get(diagramNameOfNext); currentEdges = edges.get(diagramNameOfNext); } collectionsChanged = true; } @Override public synchronized void addNode(double x, double y, int nodeHashCode, String diagramName) { Node n = new Node(x,y,nodeHashCode, nodeHashCode); if(diagramName == null){ currentNodes.add(n); }else{ nodes.get(diagramName).add(n); } collectionsChanged = true; } @Override public synchronized void removeNode(int nodeHashCode, String diagramName) { ListIterator<Node> itr = (diagramName == null) ? currentNodes.listIterator() : nodes.get(diagramName).listIterator(); while(itr.hasNext()){ Node n = itr.next(); if(n.diagramId == nodeHashCode){ itr.remove(); collectionsChanged = true; break; } } } @Override public synchronized void moveNode(double x, double y, int nodeHashCode, String diagramName) { ArrayList<Node> iterationList = (diagramName == null) ? currentNodes : nodes.get(diagramName); for(Node n : iterationList){ if(n.diagramId == nodeHashCode){ n.x = x; n.y = y; collectionsChanged = true; break; } } } @Override public synchronized void addEdge(int edgeHashCode, double[] xs, double[] ys, BitSet[] adjMatrix, int nodeStart, int stipplePattern, Line2D attractLine, String diagramName) { /* find the mid point of the line of attraction */ double pX = Math.min(attractLine.getX1(), attractLine.getX2()); double pY = Math.min(attractLine.getY1(), attractLine.getY2()); pX += Math.abs(attractLine.getX1() - attractLine.getX2())/2; pY += Math.abs(attractLine.getY1() - attractLine.getY2())/2; Edge e = new Edge(edgeHashCode,edgeHashCode, xs, ys, adjMatrix, nodeStart, stipplePattern, pX, pY); /* add the edge reference to the edges list */ if(diagramName == null){ currentEdges.add(e); }else{ edges.get(diagramName).add(e); } collectionsChanged = true; } @Override public synchronized void updateEdge(int edgeHashCode, double[] xs, double[] ys, BitSet[] adjMatrix, int nodeStart, Line2D attractLine, String diagramName) { for(Edge e : currentEdges){ if(e.diagramId == edgeHashCode){ e.xs = xs; e.ys = ys; e.size = xs.length; e.adjMatrix = adjMatrix; e.nodeStart = nodeStart; // find the mid point of the line of attraction double pX = Math.min(attractLine.getX1(), attractLine.getX2()); double pY = Math.min(attractLine.getY1(), attractLine.getY2()); pX += Math.abs(attractLine.getX1() - attractLine.getX2())/2; pY += Math.abs(attractLine.getY1() - attractLine.getY2())/2; e.attractPointX = pX; e.attractPointY = pY; } } collectionsChanged = true; } @Override public synchronized void removeEdge(int edgeHashCode, String diagramName) { ListIterator<Edge> itr = (diagramName == null) ? currentEdges.listIterator() : edges.get(diagramName).listIterator(); while(itr.hasNext()){ Edge e = itr.next(); if(e.diagramId == edgeHashCode){ itr.remove(); collectionsChanged = true; break; } } collectionsChanged = true; } @Override public synchronized void attractTo(int elementHashCode) { attractTo = elementHashCode; } @Override public synchronized void pickUp(int elementHashCode) { pickUp = true; } @Override public void setVisible(boolean visible) { // falcon haptics window cannot be made invisible } @Override public synchronized void dispose(){ shutdown = true; /* wait for the haptic thread to shut down */ try { wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } @Override public void run() { /* get the screen size which will be passed to init methos in order to set up a window * for the haptic with the same size as the swing one */ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int screenWidth = (int)screenSize.getWidth(); int screenHeight = (int)screenSize.getHeight(); currentNodes.size(); try { initFalcon(screenWidth * 5 / 8,screenHeight * 5 / 8); } catch (IOException e) { throw new RuntimeException();// OMNI haptic device doesn't cause any exception } } /* the diagram currently selected */ private ArrayList<Node> currentNodes; private ArrayList<Edge> currentEdges; /* maps with all the diagrams in the editor */ private HashMap<String,ArrayList<Node>> nodes; private HashMap<String,ArrayList<Edge>> edges; private HapticListenerThread hapticListener; private boolean initFailed; private boolean collectionsChanged; private boolean pickUp; private int attractTo; private boolean shutdown; }