feat: init repo
This commit is contained in:
Коммит
2720d8bbf5
|
@ -0,0 +1,117 @@
|
|||
.tool-versions
|
||||
.envrc
|
||||
reports/
|
||||
|
||||
deps_windows_py39/
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Jetbrains stuff:
|
||||
.idea
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
# other
|
||||
scratch.py
|
||||
settings.json
|
|
@ -0,0 +1,39 @@
|
|||
# Cinema 4D 26: One-Click Send to Speckle
|
||||
|
||||
## Introduction
|
||||
|
||||
This script allows you to send a Cinema4D model to Speckle with one click! Simply paste in a URL, execute the script, and away you go 🚀
|
||||
|
||||
![c4d-send](https://user-images.githubusercontent.com/7717434/166261286-eec09b76-2b0d-4651-bddf-8842e6c8b5c1.gif)
|
||||
|
||||
In order to achieve this, the script will (1) export your entire model to an `STL` file, (2) convert that file to Speckle, and (3) send and commit the converted mesh.
|
||||
|
||||
It is recommended that you have [Speckle Manager](https://speckle.guide/user/manager.html) installed before using this script, however you can also use a [token](https://speckle.guide/dev/tokens.html#personal-access-tokens) to authenticate yourself instead.
|
||||
|
||||
## Installation
|
||||
|
||||
### Windows
|
||||
|
||||
1. Extract the dependencies from `deps_windows_py39.zip`
|
||||
2. Copy the contents of the extracted `deps_windows_py39` folder into your `%APPDATA%\Maxon\python\python39\libs`
|
||||
|
||||
![c4d-deps](https://user-images.githubusercontent.com/7717434/166263648-e0694f8f-f0a9-44ef-8589-024288dd32aa.png)
|
||||
|
||||
2. Copy the `send_to_speckle.py` script into your `%APPDATA%\Maxon\Maxon Cinema 4D R26_7DC20B77\library\scripts` (or load it in from wherever you like to save your Cinema4D python scripts)
|
||||
|
||||
### Mac
|
||||
|
||||
I was not able to get this on an M1 Pro mac, but feel free to try this manual installation out as you may have better luck.
|
||||
|
||||
1. Using Python 3.9, `pip install specklepy numpy-stl` into `~/Library/Preferences/MAXON/python39/libs` (**NOTE:** it is critical that you use Python 3.9 as the major version needs to match the one bundled with Cinema4D)
|
||||
2. Copy the `send_to_speckle.py` script into your C4D scripts folder
|
||||
|
||||
## Usage
|
||||
|
||||
1. Load up the `send_to_speckle.py` script in the script tab
|
||||
2. Paste in the url of the stream or branch you want to send to in the `STREAM_URL` field (defaults to `main` branch)
|
||||
3. Optional: if you _don't_ have [Speckle Manager](https://speckle.guide/user/manager.html) installed with a Speckle account added to it, you can provide an authentication token to `TOKEN` field
|
||||
|
||||
![c4d-send](https://user-images.githubusercontent.com/7717434/166261286-eec09b76-2b0d-4651-bddf-8842e6c8b5c1.gif)
|
||||
|
||||
Note that C4D may become unresponsive for a minute or two until the operation is complete.
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,18 @@
|
|||
[tool.poetry]
|
||||
name = "oneclick-c4d"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["izzy lyseggen <izzy.lyseggen@gmail.com>"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9, <3.10"
|
||||
specklepy = "^2.6.7"
|
||||
numpy-stl = "^2.16.3"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
black = "^22.3.0"
|
||||
pylint = "^2.13.7"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
|
@ -0,0 +1,119 @@
|
|||
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()
|
Загрузка…
Ссылка в новой задаче