Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c8d6b3ebea | |||
| b2e7a899f6 | |||
| ef0f7ef46f | |||
| 8799f52dfb | |||
| 22c1fb4fb2 | |||
| bce03f9e38 | |||
| dc1d1adefc | |||
| 4de1f6ecc1 | |||
| 4eaea0cc51 | |||
| ccf2996096 | |||
| aa0a4d2f3b | |||
| 48ef9420de | |||
| 6c223dba33 |
@@ -4,8 +4,7 @@ from mathutils import Matrix
|
||||
from .from_speckle import *
|
||||
from .to_speckle import *
|
||||
from .util import *
|
||||
from bpy_speckle.util import find_key_case_insensitive
|
||||
from bpy_speckle.functions import _report
|
||||
from bpy_speckle.functions import _report, get_scale_length
|
||||
|
||||
from specklepy.objects.geometry import *
|
||||
from specklepy.objects.other import RenderMaterial
|
||||
@@ -21,17 +20,6 @@ FROM_SPECKLE_SCHEMAS = {
|
||||
}
|
||||
|
||||
|
||||
# FROM_SPECKLE = {
|
||||
# "Mesh": import_mesh,
|
||||
# "Brep": import_brep,
|
||||
# "Curve": import_curve,
|
||||
# "Line": import_curve,
|
||||
# "Polyline": import_curve,
|
||||
# "Polycurve":import_curve,
|
||||
# "Arc":import_curve,
|
||||
# }
|
||||
|
||||
|
||||
TO_SPECKLE = {
|
||||
"MESH": export_mesh,
|
||||
"CURVE": export_curve,
|
||||
@@ -146,7 +134,10 @@ def add_custom_properties(speckle_object, blender_object):
|
||||
blender_object["_speckle_type"] = type(speckle_object).__name__
|
||||
# blender_object['_speckle_name'] = "SpeckleObject"
|
||||
|
||||
ignore = ["_chunkable", "_units"]
|
||||
ignore = ["_chunkable", "_units", "units"]
|
||||
|
||||
if hasattr(speckle_object, "applicationId"):
|
||||
blender_object["applicationId"] = speckle_object.applicationId
|
||||
|
||||
for key in speckle_object.get_dynamic_member_names():
|
||||
if key in ignore:
|
||||
@@ -180,17 +171,27 @@ def dict_to_speckle_object(data):
|
||||
|
||||
|
||||
def from_speckle_object(speckle_object, scale, name=None):
|
||||
speckle_name = (
|
||||
name
|
||||
or getattr(speckle_object, "name", None)
|
||||
or speckle_object.speckle_type + f" -- {speckle_object.id}"
|
||||
)
|
||||
|
||||
units = getattr(speckle_object, "units", None)
|
||||
if units:
|
||||
scale = get_scale_length(units) / bpy.context.scene.unit_settings.scale_length
|
||||
|
||||
# try native conversion
|
||||
if type(speckle_object) in FROM_SPECKLE_SCHEMAS.keys():
|
||||
print("Got object type: {}".format(type(speckle_object)))
|
||||
speckle_name = (
|
||||
name
|
||||
or getattr(speckle_object, "name", None)
|
||||
or speckle_object.speckle_type + f" -- {speckle_object.id}"
|
||||
)
|
||||
|
||||
obdata = FROM_SPECKLE_SCHEMAS[type(speckle_object)](
|
||||
speckle_object, scale, speckle_name
|
||||
)
|
||||
try:
|
||||
obdata = FROM_SPECKLE_SCHEMAS[type(speckle_object)](
|
||||
speckle_object, scale, speckle_name
|
||||
)
|
||||
except Exception as e: # conversion error
|
||||
_report(f"Error converting {speckle_object} \n{e}")
|
||||
return None
|
||||
|
||||
if speckle_name in bpy.data.objects.keys():
|
||||
blender_object = bpy.data.objects[speckle_name]
|
||||
@@ -210,9 +211,16 @@ def from_speckle_object(speckle_object, scale, name=None):
|
||||
|
||||
return blender_object
|
||||
|
||||
else:
|
||||
_report("Invalid input: {}".format(speckle_object))
|
||||
return None
|
||||
# try display mesh
|
||||
mesh = getattr(
|
||||
speckle_object, "displayMesh", getattr(speckle_object, "displayValue", None)
|
||||
)
|
||||
if mesh:
|
||||
return from_speckle_object(mesh, scale, speckle_name)
|
||||
|
||||
# return none if fail
|
||||
_report("Invalid input: {}".format(speckle_object))
|
||||
return None
|
||||
|
||||
|
||||
def get_speckle_subobjects(attr, scale, name):
|
||||
@@ -265,12 +273,12 @@ def get_blender_custom_properties(obj, max_depth=1000):
|
||||
return obj
|
||||
|
||||
if hasattr(obj, "keys"):
|
||||
d = {}
|
||||
for key in obj.keys():
|
||||
if key in ignored_keys or key.startswith("_"):
|
||||
continue
|
||||
d[key] = get_blender_custom_properties(obj[key], max_depth - 1)
|
||||
return d
|
||||
return {
|
||||
key: get_blender_custom_properties(obj[key], max_depth - 1)
|
||||
for key in obj.keys()
|
||||
if key not in ignored_keys and not key.startswith("_")
|
||||
}
|
||||
|
||||
elif isinstance(obj, (list, tuple, idprop.types.IDPropertyArray)):
|
||||
return [get_blender_custom_properties(o, max_depth - 1) for o in obj]
|
||||
else:
|
||||
@@ -289,6 +297,7 @@ def to_speckle_object(blender_object, scale):
|
||||
|
||||
for so in speckle_objects:
|
||||
so.properties = get_blender_custom_properties(blender_object)
|
||||
so.applicationId = so.properties.pop("applicationId", None)
|
||||
|
||||
if speckle_material:
|
||||
so["renderMaterial"] = speckle_material
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import bpy, math
|
||||
from bpy_speckle.util import find_key_case_insensitive
|
||||
from mathutils import Vector, Quaternion
|
||||
import mathutils
|
||||
from specklepy.objects.geometry import *
|
||||
|
||||
CONVERT = {}
|
||||
@@ -85,7 +85,7 @@ def import_nurbs_curve(scurve, bcurve, scale):
|
||||
1,
|
||||
)
|
||||
|
||||
if len(scurve.weights == len(nurbs.points)):
|
||||
if len(scurve.weights) == len(nurbs.points):
|
||||
for i, w in enumerate(scurve.weights):
|
||||
nurbs.points[i].weight = w
|
||||
|
||||
@@ -109,7 +109,7 @@ def import_arc(rcurve, bcurve, scale):
|
||||
return
|
||||
|
||||
origin = plane.origin
|
||||
normal = Vector(plane.normal.value)
|
||||
normal = mathutils.Vector([plane.normal.x, plane.normal.y, plane.normal.z])
|
||||
|
||||
xaxis = plane.xdir
|
||||
yaxis = plane.ydir
|
||||
@@ -118,20 +118,20 @@ def import_arc(rcurve, bcurve, scale):
|
||||
startAngle = rcurve.startAngle
|
||||
endAngle = rcurve.endAngle
|
||||
|
||||
startQuat = Quaternion(normal, startAngle)
|
||||
endQuat = Quaternion(normal, endAngle)
|
||||
startQuat = mathutils.Quaternion(normal, startAngle)
|
||||
endQuat = mathutils.Quaternion(normal, endAngle)
|
||||
|
||||
"""
|
||||
Get start and end vectors, centre point, angles, etc.
|
||||
"""
|
||||
|
||||
r1 = Vector(plane.xdir.value)
|
||||
r1 = mathutils.Vector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r1.rotate(startQuat)
|
||||
|
||||
r2 = Vector(plane.xdir.value)
|
||||
r2 = mathutils.Vector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r2.rotate(endQuat)
|
||||
|
||||
c = Vector(plane.origin.value) * scale
|
||||
c = mathutils.Vector([plane.origin.x, plane.origin.y, plane.origin.z]) * scale
|
||||
|
||||
spt = c + r1 * radius
|
||||
ept = c + r2 * radius
|
||||
@@ -149,7 +149,7 @@ def import_arc(rcurve, bcurve, scale):
|
||||
|
||||
Ndiv = max(int(math.floor(angle / 0.3)), 2)
|
||||
step = angle / float(Ndiv)
|
||||
stepQuat = Quaternion(normal, step)
|
||||
stepQuat = mathutils.Quaternion(normal, step)
|
||||
tan = math.tan(step / 2) * radius
|
||||
|
||||
arc.points.add(Ndiv + 1)
|
||||
|
||||
@@ -2,8 +2,100 @@ import bpy, bmesh, struct
|
||||
from specklepy.objects.geometry import Curve, Interval, Box, Polyline
|
||||
from bpy_speckle.convert.to_speckle.mesh import export_mesh
|
||||
|
||||
UNITS = "m"
|
||||
|
||||
|
||||
def bezier_to_speckle(matrix, spline, scale, name=None):
|
||||
degree = 3
|
||||
closed = spline.use_cyclic_u
|
||||
|
||||
points = []
|
||||
for i, bp in enumerate(spline.bezier_points):
|
||||
if i > 0:
|
||||
points.append(tuple(matrix @ bp.handle_left * scale))
|
||||
points.append(tuple(matrix @ bp.co * scale))
|
||||
if i < len(spline.bezier_points) - 1:
|
||||
points.append(tuple(matrix @ bp.handle_right * scale))
|
||||
|
||||
if closed:
|
||||
points.append(tuple(matrix @ spline.bezier_points[-1].handle_right * scale))
|
||||
points.append(tuple(matrix @ spline.bezier_points[0].handle_left * scale))
|
||||
points.append(tuple(matrix @ spline.bezier_points[0].co * scale))
|
||||
|
||||
num_points = len(points)
|
||||
|
||||
knot_count = num_points + degree - 1
|
||||
knots = [0] * knot_count
|
||||
|
||||
for i in range(1, len(knots)):
|
||||
knots[i] = i // 3
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
return Curve(
|
||||
name=name,
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
points=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
weights=[1] * num_points,
|
||||
knots=knots,
|
||||
rational=False,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units=UNITS,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
)
|
||||
|
||||
|
||||
def nurbs_to_speckle(matrix, spline, scale, name=None):
|
||||
knots = makeknots(spline)
|
||||
# print("knots: {}".format(knots))
|
||||
points = [tuple(matrix @ pt.co.xyz * scale) for pt in spline.points]
|
||||
degree = spline.order_u - 1
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
|
||||
return Curve(
|
||||
name=name,
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
points=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
weights=[pt.weight for pt in spline.points],
|
||||
knots=knots,
|
||||
rational=False,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units=UNITS,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
)
|
||||
|
||||
|
||||
def poly_to_speckle(matrix, spline, scale, name=None):
|
||||
points = [tuple(matrix @ pt.co.xyz * scale) for pt in spline.points]
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
return Polyline(
|
||||
name=name,
|
||||
closed=spline.use_cyclic_u,
|
||||
value=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
length=length,
|
||||
domain=domain,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
area=0,
|
||||
units=UNITS,
|
||||
)
|
||||
|
||||
|
||||
def export_curve(blender_object, data, scale=1.0):
|
||||
UNITS = "m" if bpy.context.scene.unit_settings.system == "METRIC" else "ft"
|
||||
|
||||
if blender_object.type != "CURVE":
|
||||
return None
|
||||
@@ -18,115 +110,22 @@ def export_curve(blender_object, data, scale=1.0):
|
||||
mesh = export_mesh(blender_object, blender_object.to_mesh(), scale)
|
||||
curves.extend(mesh)
|
||||
|
||||
unit_system = bpy.context.scene.unit_settings.system
|
||||
|
||||
for spline in data.splines:
|
||||
if spline.type == "BEZIER":
|
||||
|
||||
degree = 3
|
||||
closed = spline.use_cyclic_u
|
||||
|
||||
points = []
|
||||
for i, bp in enumerate(spline.bezier_points):
|
||||
if i > 0:
|
||||
points.append(tuple(mat @ bp.handle_left * scale))
|
||||
points.append(tuple(mat @ bp.co * scale))
|
||||
if i < len(spline.bezier_points) - 1:
|
||||
points.append(tuple(mat @ bp.handle_right * scale))
|
||||
|
||||
if closed:
|
||||
points.append(
|
||||
tuple(mat @ spline.bezier_points[-1].handle_right * scale)
|
||||
)
|
||||
points.append(tuple(mat @ spline.bezier_points[0].handle_left * scale))
|
||||
points.append(tuple(mat @ spline.bezier_points[0].co * scale))
|
||||
|
||||
num_points = len(points)
|
||||
|
||||
knot_count = num_points + degree - 1
|
||||
knots = [0] * knot_count
|
||||
|
||||
for i in range(1, len(knots), 1):
|
||||
knots[i] = i // 3
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(
|
||||
start=0, end=length, totalChildrenCount=0, applicationId="Blender"
|
||||
)
|
||||
bezier = Curve(
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
points=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
weights=[1] * num_points,
|
||||
knots=knots,
|
||||
rational=False,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units="m" if unit_system == "METRIC" else "ft",
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
applicationId="Blender",
|
||||
)
|
||||
|
||||
curves.append(bezier)
|
||||
curves.append(bezier_to_speckle(mat, spline, scale, blender_object.name))
|
||||
|
||||
elif spline.type == "NURBS":
|
||||
|
||||
knots = makeknots(spline)
|
||||
# print("knots: {}".format(knots))
|
||||
points = [tuple(mat @ pt.co.xyz * scale) for pt in spline.points]
|
||||
degree = spline.order_u - 1
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(
|
||||
start=0, end=length, totalChildrenCount=0, applicationId="Blender"
|
||||
)
|
||||
nurbs = Curve(
|
||||
name=blender_object.name,
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
points=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
weights=[pt.weight for pt in spline.points],
|
||||
knots=knots,
|
||||
rational=False,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units="m" if unit_system == "METRIC" else "ft",
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
applicationId="Blender",
|
||||
)
|
||||
|
||||
curves.append(nurbs)
|
||||
curves.append(nurbs_to_speckle(mat, spline, scale, blender_object.name))
|
||||
|
||||
elif spline.type == "POLY":
|
||||
points = [tuple(mat @ pt.co.xyz * scale) for pt in spline.points]
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(
|
||||
start=0, end=length, totalChildrenCount=0, applicationId="Blender"
|
||||
)
|
||||
poly = Polyline(
|
||||
name=blender_object.name,
|
||||
closed=spline.use_cyclic_u,
|
||||
value=list(sum(points, ())), # magic (flatten list of tuples)
|
||||
length=length,
|
||||
domain=domain,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
area=0,
|
||||
units="m" if unit_system == "METRIC" else "ft",
|
||||
applicationId="Blender",
|
||||
)
|
||||
curves.append(poly)
|
||||
curves.append(poly_to_speckle(mat, spline, scale, blender_object.name))
|
||||
|
||||
return curves
|
||||
|
||||
|
||||
def export_ngons_as_polylines(blender_object, data, scale=1.0):
|
||||
UNITS = "m" if bpy.context.scene.unit_settings.system == "METRIC" else "ft"
|
||||
|
||||
if blender_object.type != "MESH":
|
||||
return None
|
||||
|
||||
@@ -139,7 +138,7 @@ def export_ngons_as_polylines(blender_object, data, scale=1.0):
|
||||
for v in poly.vertices:
|
||||
value.extend(mat @ verts[v].co * scale)
|
||||
|
||||
domain = Interval(start=0, end=1, applicationId="Blender")
|
||||
domain = Interval(start=0, end=1)
|
||||
poly = Polyline(
|
||||
name="{}_{}".format(blender_object.name, i),
|
||||
closed=True,
|
||||
@@ -148,8 +147,7 @@ def export_ngons_as_polylines(blender_object, data, scale=1.0):
|
||||
domain=domain,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
area=0,
|
||||
units="m" if unit_system == "METRIC" else "ft",
|
||||
applicationId="Blender",
|
||||
units=UNITS,
|
||||
)
|
||||
|
||||
polylines.append(poly)
|
||||
|
||||
@@ -26,7 +26,6 @@ def export_mesh(blender_object, data, scale=1.0):
|
||||
colors=[],
|
||||
units="m" if unit_system == "METRIC" else "ft",
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
applicationId="Blender",
|
||||
)
|
||||
|
||||
for f in faces:
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
from specklepy.api.client import SpeckleClient
|
||||
import requests
|
||||
|
||||
from bpy_speckle.clients import speckle_clients
|
||||
|
||||
"""
|
||||
|
||||
@@ -110,7 +110,7 @@ class DeleteObject(bpy.types.Operator):
|
||||
for x in res["resource"]["objects"]
|
||||
if x["_id"] == active.speckle.object_id
|
||||
]
|
||||
if existing == None:
|
||||
if existing is None:
|
||||
return {"CANCELLED"}
|
||||
# print("Existing: %s" % SpeckleResource.to_json_pretty(existing))
|
||||
new_objects = [
|
||||
@@ -177,7 +177,7 @@ class UploadNgonsAsPolylines(bpy.types.Operator):
|
||||
res = client.objects.create([polyline])
|
||||
print(res)
|
||||
|
||||
if res == None:
|
||||
if res is None:
|
||||
_report(client.me)
|
||||
continue
|
||||
placeholders.extend(res)
|
||||
@@ -185,7 +185,7 @@ class UploadNgonsAsPolylines(bpy.types.Operator):
|
||||
# polyline['_id'] = res['_id']
|
||||
# placeholders.append({'type':'Placeholder', '_id':res['_id']})
|
||||
|
||||
if len(placeholders) < 1:
|
||||
if not placeholders:
|
||||
return {"CANCELLED"}
|
||||
|
||||
# Get list of existing objects in stream and append new object to list
|
||||
@@ -247,7 +247,7 @@ class UploadObject(bpy.types.Operator):
|
||||
sm = to_speckle_object(active, scale)
|
||||
|
||||
placeholders = client.objects.create([sm])
|
||||
if placeholders == None:
|
||||
if placeholders is None:
|
||||
return {"CANCELLED"}
|
||||
|
||||
sstream = client.streams.get(stream.id)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Stream operators
|
||||
"""
|
||||
|
||||
from itertools import chain
|
||||
import bpy, bmesh, os
|
||||
import webbrowser
|
||||
from bpy.props import (
|
||||
@@ -32,12 +32,13 @@ from specklepy.objects.geometry import *
|
||||
|
||||
|
||||
def get_objects_collections(base):
|
||||
"""Create collections based on the dynamic members on a root commit object"""
|
||||
collections = {}
|
||||
for name in base.get_dynamic_member_names():
|
||||
value = base[name]
|
||||
if isinstance(value, list):
|
||||
col = create_collection(name)
|
||||
collections[name] = [item for item in value if isinstance(item, Base)]
|
||||
collections[name] = get_objects_nested_lists(value)
|
||||
if isinstance(value, Base):
|
||||
col = create_collection(name)
|
||||
collections[name] = get_objects_collections_recursive(value, col)
|
||||
@@ -45,7 +46,21 @@ def get_objects_collections(base):
|
||||
return collections
|
||||
|
||||
|
||||
def get_objects_nested_lists(items):
|
||||
"""For handling the weird nested lists that come from Grasshopper"""
|
||||
objects = []
|
||||
|
||||
if isinstance(items[0], list):
|
||||
items = list(chain.from_iterable(items))
|
||||
objects.extend(get_objects_nested_lists(items))
|
||||
else:
|
||||
objects = [item for item in items if isinstance(item, Base)]
|
||||
|
||||
return objects
|
||||
|
||||
|
||||
def get_objects_collections_recursive(base, parent_col=None):
|
||||
"""Recursively create collections based on the dynamic members on nested `Base` objects within the root commit object"""
|
||||
objects = []
|
||||
for name in base.get_dynamic_member_names():
|
||||
value = base[name]
|
||||
@@ -234,7 +249,6 @@ class ReceiveStreamObjects(bpy.types.Operator):
|
||||
return {"CANCELLED"}
|
||||
|
||||
name = "{} [ {} @ {} ]".format(stream.name, branch.name, commit.id)
|
||||
|
||||
col = create_collection(name)
|
||||
col.speckle.stream_id = stream.id
|
||||
col.speckle.name = stream.name
|
||||
@@ -380,12 +394,16 @@ class SendStreamObjects(bpy.types.Operator):
|
||||
|
||||
transport = ServerTransport(client, stream.id)
|
||||
|
||||
obj_id = operations.send(base, [transport])
|
||||
obj_id = operations.send(
|
||||
base,
|
||||
[transport],
|
||||
)
|
||||
client.commit.create(
|
||||
stream.id,
|
||||
obj_id,
|
||||
branch.name,
|
||||
message=self.commit_message,
|
||||
source_application="blender",
|
||||
)
|
||||
|
||||
bpy.ops.speckle.load_user_streams()
|
||||
|
||||
@@ -83,7 +83,7 @@ class LoadUserStreams(bpy.types.Operator):
|
||||
client = speckle_clients[int(context.scene.speckle.active_user)]
|
||||
|
||||
try:
|
||||
streams = client.stream.list()
|
||||
streams = client.stream.list(stream_limit=20)
|
||||
except Exception as e:
|
||||
_report("Failed to retrieve streams: {}".format(e))
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user