00001
00002
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;
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
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)
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
00120 Matrix4f transform= new Matrix4f();
00121 transform.load(currentTransform);
00122
00123
00124
00125 transform = (Matrix4f) transform.invert();
00126
00127 Matrix4f.transform(transform, raystart, raystart);
00128 Matrix4f.transform(transform, rayend, rayend);
00129
00130
00131 Vector3f raydir = Vector3f.sub(new Vector3f(rayend), new Vector3f(raystart), null);
00132 raydir.normalise();
00133
00134 return new Ray(new Vector3f(raystart), raydir);
00135
00136 }
00145 Ray buildRay(float x, float y) {
00146
00147 VisClient vc = getRoot().client;
00148 x = 2 * x / vc.panel.getWidth() - 1f;
00149 y = 2 * y / vc.panel.getHeight() - 1f;
00150
00151
00152 Vector4f raystart = new Vector4f(0, 0, 0, 1);
00153
00154
00155 Vector4f rayend = new Vector4f(x * GLUtil.aspect, -y, -1 / GLUtil.fov, 1);
00156
00157
00158
00159 return buildRay(raystart,rayend);
00160 }
00161
00173 void handleEvents(List<AWTEvent> events) {
00174
00175
00176 for (Object e : events.toArray())
00177 if (e instanceof MouseEvent) {
00178 MouseEvent me = (MouseEvent) e;
00179
00180
00181
00182
00183
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
00195 VisRoot r=getRoot();
00196 if(! (r instanceof VisHUD)) depth=Vector3f.sub(traverse(r, hit), r.client.mouseViewpoint, null).length();
00197
00198
00199 weWon = true;
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
00206
00207 if (candidate.getSource()==this) continue;
00208
00209 if (depth < candidate.depth) {
00210
00211 weWon = true;
00212 looser = e2;
00213 } else
00214 weWon = false;
00215 }
00216 if (looser != null)
00217 events.remove(looser);
00218 if (weWon)
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){
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 }