oneclick-c4d/send_to_speckle.py

120 строки
3.5 KiB
Python

import os
import c4d
import stl
from specklepy.api import operations
from specklepy.api.wrapper import StreamWrapper
from specklepy.objects.geometry import Mesh
from specklepy.logging.exceptions import SpeckleException
# the url to the stream or branch you want to send to (if not a branch url, it will default to the main branch)
STREAM_URL = "https://latest.speckle.dev/streams/0c6ad366c4/branches/c4d_tests"
# the file will get exported to an STL in this folder right next to your c4d file
STL_EXPORT_FOLDER_NAME = "stl_export"
# if you have a account on Speckle Manager, you don't need this
TOKEN = ""
def export_stl() -> str:
"""Export the current file to an STL in a subfolder next to this file's location"""
active_doc = c4d.documents.GetActiveDocument()
path = active_doc.GetDocumentPath()
export_folder = os.path.join(path, STL_EXPORT_FOLDER_NAME)
os.makedirs(export_folder, exist_ok=True)
export_path = os.path.join(
export_folder, f"{os.path.splitext(active_doc.GetDocumentName())[0]} EXPORT.stl"
)
saved = c4d.documents.SaveDocument(
active_doc,
export_path,
saveflags=c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST,
format=c4d.FORMAT_STL_EXPORT,
)
if not saved:
raise SpeckleException("Failed to export file to STL")
print(f"Exported STL to {export_path}")
return export_path
def convert_stl(stl_file_path: str) -> Mesh:
"""
Convert STL file into a Speckle Mesh
(from the [speckle server import service](https://github.com/specklesystems/speckle-server/blob/main/packages/fileimport-service/stl/import_file.py))
"""
# Parse input
stl_mesh = stl.mesh.Mesh.from_file(stl_file_path)
print(
f"Parsed mesh with {stl_mesh.points.shape[0]} faces ({stl_mesh.points.shape[0] * 3} vertices)"
)
# Construct speckle obj
vertices = stl_mesh.points.flatten().tolist()
faces = []
for i in range(stl_mesh.points.shape[0]):
faces.extend([0, 3 * i, 3 * i + 1, 3 * i + 2])
speckle_mesh = Mesh(
vertices=vertices, faces=faces, colors=[], textureCoordinates=[]
)
print("Constructed Speckle Mesh object")
return speckle_mesh
def send_to_speckle(
wrapper: StreamWrapper, speckle_mesh: Mesh, commit_msg: str = None
) -> str:
"""Send the mesh to speckle and create a commit"""
client = wrapper.get_client(TOKEN or None)
if wrapper.branch_name and not client.branch.get(
wrapper.stream_id, wrapper.branch_name
):
client.branch.create(
wrapper.stream_id,
wrapper.branch_name,
"File upload branch" if wrapper.branch_name == "uploads" else "",
)
obj_id = operations.send(base=speckle_mesh, transports=[wrapper.get_transport()])
return client.commit.create(
wrapper.stream_id,
obj_id,
wrapper.branch_name or "main",
commit_msg or "STL file upload",
source_application="cinema4D",
)
def main() -> None:
w = StreamWrapper(STREAM_URL)
acct = w.get_account()
if not acct.token or TOKEN:
raise SpeckleException(
"No token available. Please either add a Speckle Account to Speckle Manager or provide a token in `TOKEN`"
)
stl_path = export_stl()
speckle_mesh = convert_stl(stl_path)
commit_id = send_to_speckle(
w, speckle_mesh, f"File upload: {os.path.basename(stl_path)}"
)
print(
f"File uploaded to\n{w.server_url}/streams/{w.stream_id}/commits/{commit_id}\n"
)
if __name__ == "__main__":
main()