2
0
Эх сурвалжийг харах

Level: Support model drag n drop

trethaller 7 жил өмнө
parent
commit
b15b99549e

+ 5 - 0
hide/prefab/Model.hx

@@ -5,6 +5,11 @@ class Model extends Object3D {
 	var animation : Null<String>;
 	var lockAnimation : Bool = false;
 
+	public function new(?parent) {
+		super(parent);
+		type = "model";
+	}
+
 	override function save() {
 		var obj : Dynamic = super.save();
 		if( animation != null ) obj.animation = animation;

+ 42 - 10
hide/ui/Ide.hx

@@ -89,24 +89,34 @@ class Ide {
 		var body = window.window.document.body;
 		body.onfocus = function(_) haxe.Timer.delay(function() new Element(body).find("input[type=file]").change().remove(), 200);
 		body.ondragover = function(e:js.html.DragEvent) {
-			e.preventDefault();
+			syncMousePosition(e);
+			var view = getViewAt(mouseX, mouseY);
+			if(view != null && view.onDrop(true, e)) {
+				e.preventDefault();
+				e.stopPropagation();
+			}
 			return false;
 		};
 		body.ondrop = function(e:js.html.DragEvent) {
-			for( f in e.dataTransfer.files )
-				openFile(Reflect.field(f,"path"));
-			e.preventDefault();
+			syncMousePosition(e);
+			var view = getViewAt(mouseX, mouseY);
+			if(view != null && view.onDrop(false, e)) {
+				e.preventDefault();
+				e.stopPropagation();
+			}
+			else {
+				for( f in e.dataTransfer.files )
+					openFile(Reflect.field(f,"path"));
+				e.preventDefault();
+			}
 			return false;
 		}
 
 		// dispatch global keys based on mouse position
 		new Element(body).keydown(function(e) {
-			for( v in views ) {
-				var c = v.root.offset();
-				if( mouseX >= c.left && mouseY >= c.top && mouseX <= c.left + v.root.outerWidth() && mouseY <= c.top + v.root.outerHeight() ) {
-					v.keys.processEvent(e);
-					break;
-				}
+			var view = getViewAt(mouseX, mouseY);
+			if(view != null) {
+				view.keys.processEvent(e);
 			}
 		});
 
@@ -115,6 +125,28 @@ class Ide {
 		hxd.Key.initialize();
 	}
 
+	function getViewAt(x : Float, y : Float) {
+		for( v in views ) {
+			var c = v.root.offset();
+			if( x >= c.left && y >= c.top && x <= c.left + v.root.outerWidth() && y <= c.top + v.root.outerHeight() ) {
+				return v;
+			}
+		}
+		return null;
+	}
+
+	function syncMousePosition(e:js.html.MouseEvent) {
+		mouseX = e.clientX;
+		mouseY = e.clientY;
+		for( c in new Element("canvas") ) {
+			var s : hide.comp.Scene = (c:Dynamic).__scene;
+			if( s != null ) @:privateAccess {
+				s.stage.curMouseX = mouseX;
+				s.stage.curMouseY = mouseY;
+			}
+		}
+	}
+
 	function get_isWindows() {
 		return true;
 	}

+ 4 - 0
hide/ui/View.hx

@@ -136,6 +136,10 @@ class View<T> extends hide.comp.Component {
 	public function onResize() {
 	}
 
+	public function onDrop(over : Bool, e:js.html.DragEvent) {
+		return false;
+	}
+
 	/**
 		Gives focus if part of a tab group
 	**/

+ 72 - 10
hide/view/l3d/Level3D.hx

@@ -776,6 +776,50 @@ class Level3D extends FileView {
 		}
 	}
 
+	override function onDrop(over: Bool, e:js.html.DragEvent) {
+		var supported = ["fbx"];
+		var models = [];
+		for(f in e.dataTransfer.files) {
+			var path = Reflect.field(f, "path");
+			var ext = haxe.io.Path.extension(path);
+			if(supported.indexOf(ext) >= 0) {
+				models.push(path);
+			}
+		}
+		if(models.length > 0) {
+			if(!over) {
+				dropModels(models);
+			}
+			return true;
+		}
+		return false;
+	}
+
+	function dropModels(paths: Array<String>) {
+		var proj = screenToWorld(scene.s2d.mouseX, scene.s2d.mouseY);
+		if(proj == null) return;
+
+		var parent = curEdit != null && curEdit.elements.length > 0 ? curEdit.elements[0] : data;
+		var parentMat = worldMat(getObject(parent));
+		parentMat.invert();
+
+		var localMat = new h3d.Matrix();
+		localMat.initTranslate(proj.x, proj.y, proj.z);
+		localMat.multiply(localMat, parentMat);
+
+		var models: Array<PrefabElement> = [];
+		for(path in paths) {
+			var model = new hide.prefab.Model(parent);
+			model.setTransform(localMat);
+			var relative = ide.makeRelative(path);
+			model.source = relative;
+			autoName(model);
+			models.push(model);
+		}
+
+		refresh();
+	}
+
 	function canGroupSelection() {
 		var elts = curEdit.rootElements;
 		if(elts.length == 0)
@@ -1041,28 +1085,46 @@ class Level3D extends FileView {
 		updateTreeStyle(p, el);
 	}
 
-	function getZ(x: Float, y: Float) {
+	function getGroundPolys() {
 		var gname = props.get("l3d.groundLayer");
 		var groundLayer = data.get(Layer, gname);
 		var polygons = groundLayer.getAll(hide.prefab.l3d.Polygon);
-		var offset = 1000;
-		var ray = h3d.col.Ray.fromValues(x, y, offset, 0, 0, -1);
-		var topPoly = null;
-		var topDist = 1e10;
+		return polygons;		
+	}
+
+	function projectToGround(ray: h3d.col.Ray) {
+		var polygons = getGroundPolys();
+		var minDist = -1.;
 		for(polygon in polygons) {
 			var collider = polygon.mesh.getGlobalCollider();
 			var d = collider.rayIntersection(ray, true);
-			if(d > 0 && d < topDist) {
-				topDist = d;
-				topPoly = polygon;
+			if(d > 0 && (d < minDist || minDist < 0)) {
+				minDist = d;
 			}
 		}
-		if(topPoly != null) {
-			return offset - topDist;
+		return minDist;
+	}
+
+	function getZ(x: Float, y: Float) {
+		var offset = 1000;
+		var ray = h3d.col.Ray.fromValues(x, y, offset, 0, 0, -1);
+		var dist = projectToGround(ray);
+		if(dist >= 0) {
+			return offset - dist;
 		}
 		return 0.;
 	}
 
+	function screenToWorld(sx: Float, sy: Float) {
+		var camera = scene.s3d.camera;
+		var ray = camera.rayFromScreen(sx, sy);
+		var dist = projectToGround(ray);
+		if(dist >= 0) {
+			return ray.getPoint(dist);
+		}
+		return null;
+	}
+
 	static function worldMat(obj: Object) {
 		if(obj.defaultTransform != null) {
 			var m = obj.defaultTransform.clone();