VisClient/org/hfbk/vis/visnode/VisNodeMousable.java

Go to the documentation of this file.
00001 /*
00002  * Created on 16.04.2008
00003  */
00004 package org.hfbk.vis.visnode;
00005 
00006 import java.awt.AWTEvent;
00007 import java.awt.event.MouseEvent;
00008 import java.util.List;
00009 
00010 import org.dronus.gl.GLUtil;
00011 import org.dronus.graph.Node;
00012 import org.hfbk.vis.VisClient;
00013 import org.hfbk.vis.VisEvent;
00014 import org.lwjgl.util.vector.Matrix4f;
00015 import org.lwjgl.util.vector.Vector3f;
00016 import org.lwjgl.util.vector.Vector4f;
00017 
00040 public abstract class VisNodeMousable extends VisNode {
00041 
00047         final float MINDEPTH=12;  
00048         
00049         protected boolean isHoovered = false, isDragged = false;
00050 
00051         public float w = 12, h = 4; // default keyword panel
00052 
00053         VisNodeMousable(Node node, Vector3f position) {
00054                 super(node, position);
00055         }
00056 
00057         
00058 
00063         abstract void handleEvent(VisMouseEvent evt);
00064 
00069         class Ray {
00070                 Vector3f start, dir;
00071 
00072                 public Ray(Vector3f start, Vector3f dir) {
00073                         this.start = start;
00074                         this.dir = dir;
00075                 }
00076         }
00077 
00092         boolean hit(Ray mouseray, Vector3f hit) {
00093                 // calculate a flat plane intersection.
00094 
00095                 float distance = mouseray.start.z;
00096 
00097                 Vector3f normal = new Vector3f(0, 0, -1);
00098                 float projectiveLength=distance/Vector3f.dot(mouseray.dir, normal);
00099                 
00100                 if (projectiveLength<0) //ray and ray target are on same side of the plane  
00101                         return false;
00102                 
00103                 Vector3f projector = (Vector3f) new Vector3f(mouseray.dir).scale(projectiveLength);
00104                 Vector3f.add(mouseray.start, projector, hit);
00105                 
00106                 return hit.x > -w / 2 && hit.y > -h / 2 && hit.x < w / 2 && hit.y < h / 2;                      
00107         }
00108 
00109         
00110         
00118         Ray buildRay(Vector4f raystart, Vector4f rayend){
00119 //               get the current node's transform
00120                 Matrix4f transform= new Matrix4f();
00121                 transform.load(currentTransform);
00122                 
00123                 // we now transform the viewpoint (as start) and a point 1 unit
00124                 // deeper at the mouse position (as some point on the ray)
00125                 transform = (Matrix4f) transform.invert();
00126 
00127                 Matrix4f.transform(transform, raystart, raystart);
00128                 Matrix4f.transform(transform, rayend, rayend);
00129 
00130                 // now compute the line from start to the other point
00131                 Vector3f raydir = Vector3f.sub(new Vector3f(rayend), new Vector3f(raystart), null);
00132                 raydir.normalise(); // normalise the direction to the length of 1.
00133 
00134                 return new Ray(new Vector3f(raystart), raydir);
00135 
00136         }
00145         Ray buildRay(float x, float y) {
00146                 // map mouse coords to normalised -1,1 coords.
00147                 VisClient vc = getRoot().client;
00148                 x = 2 * x / vc.panel.getWidth() - 1f;
00149                 y = 2 * y / vc.panel.getHeight() - 1f;
00150 
00151                 // 0,0,0: the camera origin.
00152                 Vector4f raystart = new Vector4f(0, 0, 0, 1);
00153 
00154                 // the mouse pos
00155                 Vector4f rayend = new Vector4f(x * GLUtil.aspect, -y, -1 / GLUtil.fov, 1);
00156 
00157                 //we now got a ray from the viewer to infinity in the direction of the
00158                 // mouse pointer. transform it to local space.          
00159                 return buildRay(raystart,rayend);
00160         }
00161 
00173         void handleEvents(List<AWTEvent> events) {
00174                 // operate on a clone of the event list so we can remove an event
00175                 // from the original list if consumed
00176                 for (Object e : events.toArray())
00177                         if (e instanceof MouseEvent) { //an original 2d mouse event
00178                                 MouseEvent me = (MouseEvent) e;
00179                                 
00180                                 //dirty: make shure we don't dismissed ourselves by an event
00181                                 //thus having no parent to build projection
00182                                 //if (parent==null) return; 
00183                                 //parent won't get null anymore i think
00184                                 
00185                                 Ray ray = buildRay(me.getX(), me.getY());
00186                                                                 
00187                                 float depth = -GLUtil.getPosition().z;
00188                                 
00189                                 Vector3f hit = new Vector3f();
00190                                 
00191                                 boolean weWon = false;
00192                                 if (depth > MINDEPTH && hit(ray,hit)) {
00193                                         
00194                                         //get exact hit depth
00195                                         VisRoot r=getRoot();
00196                                         if(! (r instanceof VisHUD)) depth=Vector3f.sub(traverse(r, hit), r.client.mouseViewpoint, null).length();
00197                                         
00198                                         // we are hit, now challenge last hit for the foremost position
00199                                         weWon = true; //'til we stand our mach 
00200                                         AWTEvent looser = null;
00201                                         for (AWTEvent e2 : events)
00202                                                 if (e2 instanceof VisMouseEvent && e2.getID() == me.getID()) { 
00203                                                         VisMouseEvent candidate=(VisMouseEvent)e2;
00204                                                         
00205                                                         // should be only one event of any type (click, move, drag)
00206                                                         // but not sure.
00207                                                         if (candidate.getSource()==this) continue;
00208                                                         
00209                                                         if (depth < candidate.depth) { // we take the lead,
00210                                                                 // kill him
00211                                                                 weWon = true;
00212                                                                 looser = e2;
00213                                                         } else
00214                                                                 weWon = false;
00215                                                 }
00216                                         if (looser != null)
00217                                                 events.remove(looser);
00218                                         if (weWon) // either we beat him or we where all alone.
00219                                                 events.add(new VisMouseEvent(me.getID(), this, me, hit, depth));
00220                                 } 
00221                                 if (!weWon && isHoovered){
00222                                         isHoovered = false;
00223                                         handleEvent(new VisMouseEvent(MouseEvent.MOUSE_EXITED, this, me, hit, 0));                      
00224                                         getRoot().client.hoovered=null;
00225                                 }
00226                                 
00227                                 if(me.getID()==MouseEvent.MOUSE_RELEASED){
00228                                         isDragged=false;
00229                                 }
00230                                 
00231                                 if (isDragged){ //handle now, there can be no other ones.
00232                                         events.clear();
00233                                         handleEvent(new VisMouseEvent(me.getID(), this, me, hit, 0));
00234                                 }
00235                         } else if (e instanceof VisMouseEvent) {
00236                                 VisMouseEvent vme = (VisMouseEvent) e;
00237                                 if (vme.getSource() == this) {
00238                                         if (!isHoovered){
00239                                                 vme=new VisMouseEvent(MouseEvent.MOUSE_ENTERED, this, vme.awtEvent, vme.hit, 0);
00240                                                 getRoot().client.hoovered=this;
00241                                                 isHoovered=true;
00242                                         }
00243                                         
00244                                         if (vme.getID()==MouseEvent.MOUSE_PRESSED)
00245                                                 isDragged=true;
00246                                         
00247                                         handleEvent(vme);
00248                                         
00249                                         events.remove(e);
00250                                 }
00251                         }
00252         }
00253 
00254         
00255         float getExtends() {
00256                 if (isDragged) return Float.MAX_VALUE;
00257                 else return super.getExtends();
00258         }
00259         
00267         public static class VisMouseEvent extends VisEvent {
00268                 Vector3f hit;
00269                 float depth;
00270 
00279                 public VisMouseEvent(int id, Object source, AWTEvent ae, Vector3f hit, float depth) {
00280                         super(source, id, ae);
00281                         this.hit = hit;
00282                         this.depth = depth;
00283                 }
00284                 int getButton(){
00285                         if (awtEvent!=null)
00286                                 return ((MouseEvent)awtEvent).getButton();
00287                         else
00288                                 return MouseEvent.BUTTON1;
00289                 }
00290         }
00291 }

Generated on Tue Apr 7 17:57:21 2009 for visclient by  doxygen 1.5.1