mirror of
https://git.datalinker.icu/kijai/ComfyUI-Hunyuan3DWrapper.git
synced 2026-05-20 07:37:11 +08:00
Add upload mesh node
This commit is contained in:
parent
205be20e08
commit
7bba1dd89a
37
nodes.py
37
nodes.py
@ -958,6 +958,41 @@ class Hy3DLoadMesh:
|
|||||||
|
|
||||||
return (mesh,)
|
return (mesh,)
|
||||||
|
|
||||||
|
class Hy3DUploadMesh:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
mesh_extensions = ['glb', 'gltf']
|
||||||
|
input_dir = folder_paths.get_input_directory()
|
||||||
|
files = []
|
||||||
|
for f in os.listdir(input_dir):
|
||||||
|
if os.path.isfile(os.path.join(input_dir, f)):
|
||||||
|
file_parts = f.split('.')
|
||||||
|
if len(file_parts) > 1 and (file_parts[-1] in mesh_extensions):
|
||||||
|
files.append(f)
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"mesh": (sorted(files),),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RETURN_TYPES = ("HY3DMESH",)
|
||||||
|
RETURN_NAMES = ("mesh",)
|
||||||
|
OUTPUT_TOOLTIPS = ("The glb model with mesh to texturize.",)
|
||||||
|
|
||||||
|
FUNCTION = "load"
|
||||||
|
CATEGORY = "Hunyuan3DWrapper"
|
||||||
|
DESCRIPTION = "Loads a glb model from the given path."
|
||||||
|
|
||||||
|
def load(self, mesh):
|
||||||
|
path = mesh.strip()
|
||||||
|
if path.startswith("\""):
|
||||||
|
path = path[1:]
|
||||||
|
if path.endswith("\""):
|
||||||
|
path = path[:-1]
|
||||||
|
mesh_file = folder_paths.get_annotated_filepath(path)
|
||||||
|
loaded_mesh = trimesh.load(mesh_file, force="mesh")
|
||||||
|
|
||||||
|
return (loaded_mesh,)
|
||||||
|
|
||||||
|
|
||||||
class Hy3DGenerateMesh:
|
class Hy3DGenerateMesh:
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -1504,6 +1539,7 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"Hy3DTorchCompileSettings": Hy3DTorchCompileSettings,
|
"Hy3DTorchCompileSettings": Hy3DTorchCompileSettings,
|
||||||
"Hy3DPostprocessMesh": Hy3DPostprocessMesh,
|
"Hy3DPostprocessMesh": Hy3DPostprocessMesh,
|
||||||
"Hy3DLoadMesh": Hy3DLoadMesh,
|
"Hy3DLoadMesh": Hy3DLoadMesh,
|
||||||
|
"Hy3DUploadMesh": Hy3DUploadMesh,
|
||||||
"Hy3DCameraConfig": Hy3DCameraConfig,
|
"Hy3DCameraConfig": Hy3DCameraConfig,
|
||||||
"Hy3DMeshUVWrap": Hy3DMeshUVWrap,
|
"Hy3DMeshUVWrap": Hy3DMeshUVWrap,
|
||||||
"Hy3DSampleMultiView": Hy3DSampleMultiView,
|
"Hy3DSampleMultiView": Hy3DSampleMultiView,
|
||||||
@ -1534,6 +1570,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"Hy3DTorchCompileSettings": "Hy3D Torch Compile Settings",
|
"Hy3DTorchCompileSettings": "Hy3D Torch Compile Settings",
|
||||||
"Hy3DPostprocessMesh": "Hy3D Postprocess Mesh",
|
"Hy3DPostprocessMesh": "Hy3D Postprocess Mesh",
|
||||||
"Hy3DLoadMesh": "Hy3D Load Mesh",
|
"Hy3DLoadMesh": "Hy3D Load Mesh",
|
||||||
|
"Hy3DUploadMesh": "Hy3D Upload Mesh",
|
||||||
"Hy3DCameraConfig": "Hy3D Camera Config",
|
"Hy3DCameraConfig": "Hy3D Camera Config",
|
||||||
"Hy3DMeshUVWrap": "Hy3D Mesh UV Wrap",
|
"Hy3DMeshUVWrap": "Hy3D Mesh UV Wrap",
|
||||||
"Hy3DSampleMultiView": "Hy3D Sample MultiView",
|
"Hy3DSampleMultiView": "Hy3D Sample MultiView",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { app } from "../../../scripts/app.js";
|
import { app } from "../../../scripts/app.js";
|
||||||
|
import { api } from "../../../scripts/api.js";
|
||||||
|
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "HY3D.jsnodes",
|
name: "HY3D.jsnodes",
|
||||||
@ -25,8 +26,100 @@ app.registerExtension({
|
|||||||
this.outputs[2]["name"] = values[1] + " faces"
|
this.outputs[2]["name"] = values[1] + " faces"
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "Hy3DUploadMesh":
|
||||||
|
addUploadWidget(nodeType, nodeData, "mesh");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//file upload code from VHS nodes: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite
|
||||||
|
async function uploadFile(file) {
|
||||||
|
//TODO: Add uploaded file to cache with Cache.put()?
|
||||||
|
try {
|
||||||
|
// Wrap file in formdata so it includes filename
|
||||||
|
const body = new FormData();
|
||||||
|
const i = file.webkitRelativePath.lastIndexOf('/');
|
||||||
|
const subfolder = file.webkitRelativePath.slice(0,i+1)
|
||||||
|
const new_file = new File([file], file.name, {
|
||||||
|
type: file.type,
|
||||||
|
lastModified: file.lastModified,
|
||||||
|
});
|
||||||
|
body.append("image", new_file);
|
||||||
|
if (i > 0) {
|
||||||
|
body.append("subfolder", subfolder);
|
||||||
|
}
|
||||||
|
const resp = await api.fetchApi("/upload/image", {
|
||||||
|
method: "POST",
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (resp.status === 200) {
|
||||||
|
return resp
|
||||||
|
} else {
|
||||||
|
alert(resp.status + " - " + resp.statusText);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
alert(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addUploadWidget(nodeType, nodeData, widgetName) {
|
||||||
|
chainCallback(nodeType.prototype, "onNodeCreated", function() {
|
||||||
|
const pathWidget = this.widgets.find((w) => w.name === widgetName);
|
||||||
|
const fileInput = document.createElement("input");
|
||||||
|
chainCallback(this, "onRemoved", () => {
|
||||||
|
fileInput?.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.assign(fileInput, {
|
||||||
|
type: "file",
|
||||||
|
accept: ".glb,.gltf,model/gltf-binary,model/gltf+json",
|
||||||
|
style: "display: none",
|
||||||
|
onchange: async () => {
|
||||||
|
if (fileInput.files.length) {
|
||||||
|
let resp = await uploadFile(fileInput.files[0])
|
||||||
|
if (resp.status != 200) {
|
||||||
|
//upload failed and file can not be added to options
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const filename = (await resp.json()).name;
|
||||||
|
pathWidget.options.values.push(filename);
|
||||||
|
pathWidget.value = filename;
|
||||||
|
if (pathWidget.callback) {
|
||||||
|
pathWidget.callback(filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(this)
|
||||||
|
document.body.append(fileInput);
|
||||||
|
let uploadWidget = this.addWidget("button", "choose glb file to upload", "image", () => {
|
||||||
|
//clear the active click event
|
||||||
|
app.canvas.node_widget = null
|
||||||
|
|
||||||
|
fileInput.click();
|
||||||
|
});
|
||||||
|
uploadWidget.options.serialize = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function chainCallback(object, property, callback) {
|
||||||
|
if (object == undefined) {
|
||||||
|
//This should not happen.
|
||||||
|
console.error("Tried to add callback to non-existant object")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (property in object && object[property]) {
|
||||||
|
const callback_orig = object[property]
|
||||||
|
object[property] = function () {
|
||||||
|
const r = callback_orig.apply(this, arguments);
|
||||||
|
callback.apply(this, arguments);
|
||||||
|
return r
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
object[property] = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user