Ver código fonte

fbx exporter: many fixs

lviguier 1 ano atrás
pai
commit
ac40e36d08
1 arquivos alterados com 182 adições e 4 exclusões
  1. 182 4
      hide/comp/SceneEditor.hx

+ 182 - 4
hide/comp/SceneEditor.hx

@@ -1154,12 +1154,17 @@ class SceneEditor {
 					{ label : "Select all", click : selectAll, keys : view.config.get("key.selectAll") },
 					{ label : "Select children", enabled : current != null, click : function() selectElements(current.flatten()) },
 				]);
-				if( !isRef )
+				if( !isRef ) {
+					var exportMenu = new Array<hide.comp.ContextMenu.ContextMenuItem>();
+					exportMenu.push({ label : "Export (default)", enabled : curEdit != null && canExportSelection(), click : function() exportSelection({forward:"0", forwardSign:"1", up:"2", upSign:"1"}), keys : null });
+					exportMenu.push({ label : "Export (-X Forward, Z Up)", enabled : curEdit != null && canExportSelection(), click : function() exportSelection({forward:"0", forwardSign:"-1", up:"2", upSign:"1"}), keys : null });
+
 					actionItems = actionItems.concat([
 						{ label : "Isolate", click : function() isolate(curEdit.elements), keys : view.config.get("key.sceneeditor.isolate") },
 						{ label : "Group", enabled : curEdit != null && canGroupSelection(), click : groupSelection, keys : view.config.get("key.group") },
-						{ label : "Export", enabled : curEdit != null && canExportSelection(), click : exportSelection, keys : null },
+						{ label : "Export", enabled : curEdit != null && canExportSelection(), menu : exportMenu },
 					]);
+				}
 			}
 
 			if( current != null ) {
@@ -2759,6 +2764,7 @@ class SceneEditor {
 	}
 
 	function canExportSelection() {
+		return true;
 		var elts = curEdit.rootElements;
 		if(elts.length == 0)
 			return false;
@@ -2793,13 +2799,185 @@ class SceneEditor {
 		return true;
 	}
 
-	function exportSelection() {
+	function exportSelection(?params : Dynamic) {
+		function clone(obj : h3d.scene.Object, ?into : h3d.scene.Mesh) : h3d.scene.Mesh {
+			var o : h3d.scene.Mesh = null;
+			if (into != null) {
+				o = into;
+			}
+			else {
+				var m = Std.downcast(obj, h3d.scene.Mesh);
+				o = new h3d.scene.Mesh(m.primitive, m.material, null);
+			}
+
+			o.x = obj.x;
+			o.y = obj.y;
+			o.z = obj.z;
+			o.scaleX = obj.scaleX;
+			o.scaleY = obj.scaleY;
+			o.scaleZ = obj.scaleZ;
+			@:privateAccess o.qRot.load(obj.qRot);
+			o.name = obj.name;
+			o.follow = obj.follow;
+			o.followPositionOnly = obj.followPositionOnly;
+			o.visible = obj.visible;
+			if( obj.defaultTransform != null ) {
+				if (o.defaultTransform != null)
+					o.defaultTransform = o.defaultTransform.multiplied(obj.defaultTransform.clone());
+				else
+					o.defaultTransform = obj.defaultTransform.clone();
+			}
+			return o;
+		}
+
+		function deepClone(m : h3d.scene.Mesh, ?parent : h3d.scene.Mesh) {
+			var copy = clone(m);
+
+			if (parent != null)
+				parent.addChild(copy);
+
+			for (child in @:privateAccess m.children) {
+				var childMesh = Std.downcast(child, h3d.scene.Mesh);
+
+				if (childMesh != null)
+					deepClone(childMesh, copy);
+			}
+
+			return copy;
+		}
+
+		function applyInverseDefaultTransform(obj : h3d.scene.Object, defaultTransform : h3d.Matrix) {
+			if (defaultTransform != null) {
+				var t = obj.getTransform().multiplied(defaultTransform.getInverse());
+				obj.x = t.getPosition().x;
+				obj.y = t.getPosition().y;
+				obj.z = t.getPosition().z;
+
+				var q : h3d.Quat = new h3d.Quat();
+				q.initRotation(t.getEulerAngles().x, t.getEulerAngles().y, t.getEulerAngles().z);
+				@:privateAccess obj.qRot.w = q.w;
+				@:privateAccess obj.qRot.x = q.x;
+				@:privateAccess obj.qRot.y = q.y;
+				@:privateAccess obj.qRot.z = q.z;
+
+				obj.scaleX = t.getScale().x;
+				obj.scaleY = t.getScale().y;
+				obj.scaleZ = t.getScale().z;
+			}
+		}
+
+		var roots : Array<h3d.scene.Mesh> = [];
+		function extractMeshes( o : h3d.scene.Object, ?parent : h3d.scene.Mesh) {
+			var m = Std.downcast(o, h3d.scene.Mesh);
+
+			// If this object isn't a mesh, we have to find into his children which mesh(s)
+			// is/are associated to it
+			if (m == null) {
+				var associatedMesh : h3d.scene.Object = null;
+
+				for (c in @:privateAccess o.children)
+					if (c.name == "root") // Associated mesh is named root (see makeInstance() of Model)
+						associatedMesh = c;
+
+				if (associatedMesh != null) {
+					var m2 = Std.downcast(associatedMesh, h3d.scene.Mesh);
+					var alreadyExtracted = new Array<h3d.scene.Object>();
+
+					if (m2 != null) {
+						// Single mesh object
+						var mesh = clone(m2);
+
+						// Since it's the parent object that is holding informations
+						// apply it on mesh object
+						clone(o, mesh);
+
+						if (parent == null)
+							roots.push(mesh);
+						else {
+							parent.addChild(mesh);
+							applyInverseDefaultTransform(mesh, parent.defaultTransform);
+						}
+
+						parent = cast mesh;
+						alreadyExtracted.push(m2);
+					}
+					else {
+						// Multiple mesh object
+						var randomRootMesh : h3d.scene.Mesh = null;
+						for (c in @:privateAccess associatedMesh.children) {
+							var mesh = Std.downcast(c, h3d.scene.Mesh);
+
+							if (mesh != null) {
+								var copy = deepClone(mesh);
+								clone(o, copy);
+
+								if (parent == null)
+									roots.push(copy);
+								else {
+									parent.addChild(copy);
+									applyInverseDefaultTransform(copy, parent.defaultTransform);
+								}
+								randomRootMesh = copy;
+							}
+						}
+
+						parent = randomRootMesh;
+						alreadyExtracted.push(associatedMesh);
+					}
+
+					// Continue to extract meshes on other objects
+					for (c in @:privateAccess o.children) {
+						if (alreadyExtracted.contains(c))
+							continue;
+
+						extractMeshes(c, parent);
+					}
+				}
+				else {
+					// We're in the case where there is multiple meshes
+					// and no children
+					for (c in @:privateAccess o.children) {
+						var mesh = Std.downcast(c, h3d.scene.Mesh);
+
+						if (mesh != null) {
+							var copy = deepClone(mesh);
+							clone(o, copy);
+
+							if (parent == null)
+								roots.push(copy);
+							else {
+								parent.addChild(copy);
+								applyInverseDefaultTransform(copy, parent.defaultTransform);
+							}
+						}
+					}
+				}
+			}
+			else {
+				var copy = clone(m);
+				if (parent == null)
+					roots.push(copy);
+				else {
+					parent.addChild(copy);
+					applyInverseDefaultTransform(copy, parent.defaultTransform);
+				}
+			}
+		}
+
+		// We have to extract meshes object from the incomming objects to remove
+		// non-needed parent objects that are created in hide in make instance
+		// of model
+		for (o in @:privateAccess curEdit.rootObjects)
+			extractMeshes(o);
+
 		// Handle the export of selection into a fbx file
 		Ide.inst.chooseFileSave("Export.fbx", function(filePath) {
 			var out = new haxe.io.BytesOutput();
-			new hxd.fmt.fbx.Writer(out).write(cast @:privateAccess curEdit.rootObjects);
+			new hxd.fmt.fbx.Writer(out).write(cast curEdit.rootObjects, params);
 			sys.io.File.saveBytes(filePath, out.getBytes());
+			Ide.inst.message('Successfully exported object at path : ${filePath}');
 		});
+
 	}
 
 	function groupSelection() {