Compare commits

...

1 Commits

Author SHA1 Message Date
Jedd Morgan b1be7780df feat: CNX-8705 fe2 ur ls in blender (#182)
* Increased default branch get to 100 limit, and added as mesh conversion for text + surfaces + metaball

* poetry lock

* Upgraded typing module

* FE2 URL support

* Raised exceptions now display to user
2024-02-13 13:35:01 +00:00
13 changed files with 166 additions and 151 deletions
+2 -2
View File
@@ -41,7 +41,7 @@ class BlenderCommitObjectBuilder(CommitObjectBuilder[Object]):
# Set the Child -> Parent relationships # Set the Child -> Parent relationships
parent = native_object.parent parent = native_object.parent
parent_collections: Tuple[Collection] = native_object.users_collection # type: ignore parent_collections = native_object.users_collection
parent_collection = parent_collections[0] if len(parent_collections) > 0 else None #NOTE: we don't support objects appearing in more than one collection, for now, we will just take the zeroth one parent_collection = parent_collections[0] if len(parent_collections) > 0 else None #NOTE: we don't support objects appearing in more than one collection, for now, we will just take the zeroth one
app_id = _id(native_object) app_id = _id(native_object)
@@ -79,7 +79,7 @@ class BlenderCommitObjectBuilder(CommitObjectBuilder[Object]):
# Create all collections # Create all collections
root_col = self.ensure_collection(bpy.context.scene.collection) root_col = self.ensure_collection(bpy.context.scene.collection)
root_col.collectionType = "Scene Collection" root_col.collectionType = "Scene Collection"
for col in bpy.context.scene.collection.children_recursive: #type: ignore for col in bpy.context.scene.collection.children_recursive:
self.ensure_collection(col) self.ensure_collection(col)
objects_to_build = set(self.converted.values()) objects_to_build = set(self.converted.values())
+1 -1
View File
@@ -540,7 +540,7 @@ def transform_to_native(transform: Transform, scale: float) -> MMatrix:
) )
# scale the translation # scale the translation
for i in range(3): for i in range(3):
mat[i][3] *= scale # type: ignore mat[i][3] *= scale
return mat return mat
def plane_to_native_transform(plane: Plane, fallback_scale:float = 1) -> MMatrix: def plane_to_native_transform(plane: Plane, fallback_scale:float = 1) -> MMatrix:
+3 -3
View File
@@ -101,7 +101,7 @@ def mesh_to_speckle_meshes(blender_object: Object, data: bpy.types.Mesh) -> List
submesh_data[p.material_index].append(p) submesh_data[p.material_index].append(p)
transform = cast(MMatrix, blender_object.matrix_world) transform = cast(MMatrix, blender_object.matrix_world)
scaled_vertices = [tuple(transform @ x.co * UnitsScale) for x in data.vertices] # type: ignore scaled_vertices = [tuple(transform @ x.co * UnitsScale) for x in data.vertices]
# Create Speckle meshes for each material # Create Speckle meshes for each material
submeshes = [] submeshes = []
@@ -445,8 +445,8 @@ def camera_to_speckle_view(blender_object: Object, data: NCamera) -> Base:
raise Exception(f"Cameras of type {data.type} are not currently supported") raise Exception(f"Cameras of type {data.type} are not currently supported")
matrix = cast(MMatrix, blender_object.matrix_world) matrix = cast(MMatrix, blender_object.matrix_world)
up = matrix.col[1].xyz # type: ignore up = cast(MVector, matrix.col[1].xyz)
forwards = -matrix.col[2].xyz # type: ignore forwards = cast(MVector, -matrix.col[2].xyz)
translation = matrix.translation translation = matrix.translation
view = Base.of_type("Objects.BuiltElements.View:Objects.BuiltElements.View3D") #HACK: views are not in specklepy yet! view = Base.of_type("Objects.BuiltElements.View:Objects.BuiltElements.View3D") #HACK: views are not in specklepy yet!
+7 -7
View File
@@ -168,7 +168,7 @@ def add_faces(speckle_mesh: Mesh, blender_mesh: BMesh, indexOffset: int, materia
i += 1 i += 1
try: try:
f = blender_mesh.faces.new( f = blender_mesh.faces.new(
[blender_mesh.verts[x + indexOffset] for x in sfaces[i : i + n]] # type: ignore [blender_mesh.verts[x + indexOffset] for x in sfaces[i : i + n]]
) )
f.material_index = materialIndex f.material_index = materialIndex
f.smooth = smooth f.smooth = smooth
@@ -198,10 +198,10 @@ def add_colors(speckle_mesh: Mesh, blender_mesh: BMesh):
) )
# Make vertex colors # Make vertex colors
if len(scolors) == len(blender_mesh.verts): # type: ignore if len(scolors) == len(blender_mesh.verts):
color_layer = blender_mesh.loops.layers.color.new("Col") color_layer = blender_mesh.loops.layers.color.new("Col")
for face in blender_mesh.faces: # type: ignore for face in blender_mesh.faces:
for loop in face.loops: for loop in face.loops:
loop[color_layer] = colors[loop.vert.index] loop[color_layer] = colors[loop.vert.index]
@@ -220,21 +220,21 @@ def add_uv_coords(speckle_mesh: Mesh, blender_mesh: BMesh):
try: try:
uv = [] uv = []
if len(s_uvs) // 2 == len(blender_mesh.verts): # type: ignore if len(s_uvs) // 2 == len(blender_mesh.verts):
uv.extend( uv.extend(
(float(s_uvs[i]), float(s_uvs[i + 1])) (float(s_uvs[i]), float(s_uvs[i + 1]))
for i in range(0, len(s_uvs), 2) for i in range(0, len(s_uvs), 2)
) )
else: else:
_report( _report(
f"Failed to match UV coordinates to vert data. Blender mesh verts: {len(blender_mesh.verts)}, Speckle UVs: {len(s_uvs) // 2}" # type: ignore f"Failed to match UV coordinates to vert data. Blender mesh verts: {len(blender_mesh.verts)}, Speckle UVs: {len(s_uvs) // 2}"
) )
return return
# Make UVs # Make UVs
uv_layer = blender_mesh.loops.layers.uv.verify() uv_layer = blender_mesh.loops.layers.uv.verify()
for f in blender_mesh.faces: # type: ignore for f in blender_mesh.faces:
for l in f.loops: for l in f.loops:
luv = l[uv_layer] luv = l[uv_layer]
luv.uv = uv[l.vert.index] luv.uv = uv[l.vert.index]
@@ -450,7 +450,7 @@ def link_object_to_collection_nested(obj: Object, col: BCollection):
if obj.name not in col.objects: #type: ignore if obj.name not in col.objects: #type: ignore
col.objects.link(obj) col.objects.link(obj)
for child in obj.children: #type: ignore for child in obj.children:
link_object_to_collection_nested(child, col) link_object_to_collection_nested(child, col)
def add_to_hierarchy(converted: Union[Object, BCollection], traversalContext : 'TraversalContext', converted_objects: Dict[str, Union[Object, BCollection]], preserve_transform: bool) -> None: def add_to_hierarchy(converted: Union[Object, BCollection], traversalContext : 'TraversalContext', converted_objects: Dict[str, Union[Object, BCollection]], preserve_transform: bool) -> None:
+9 -12
View File
@@ -4,6 +4,7 @@ Commit operators
import bpy import bpy
from bpy.props import BoolProperty from bpy.props import BoolProperty
from bpy_speckle.clients import speckle_clients from bpy_speckle.clients import speckle_clients
from bpy_speckle.functions import _report
from bpy_speckle.properties.scene import get_speckle from bpy_speckle.properties.scene import get_speckle
from specklepy.logging import metrics from specklepy.logging import metrics
@@ -38,20 +39,16 @@ class DeleteCommit(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
def execute(self, context): def execute(self, context):
try:
self.delete_commit(context)
return {"FINISHED"}
except Exception as ex:
print(f"{self.bl_idname}: failed: {ex}")
return {"CANCELLED"}
def delete_commit(self, context: bpy.types.Context) -> None:
if not self.are_you_sure: if not self.are_you_sure:
raise Exception("Cancelled by user") _report("Cancelled by user")
return {"CANCELLED"}
self.are_you_sure = False self.are_you_sure = False
self.delete_commit(context)
return {"FINISHED"}
@staticmethod
def delete_commit(context: bpy.types.Context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
(_, stream, _, commit) = speckle.validate_commit_selection() (_, stream, _, commit) = speckle.validate_commit_selection()
@@ -71,5 +68,5 @@ class DeleteCommit(bpy.types.Operator):
if not deleted: if not deleted:
raise Exception("Delete operation failed") raise Exception("Delete operation failed")
print(f"{self.bl_idname}: succeeded - commit {commit.id} ({commit.message}) has been deleted from stream {stream.id}") print(f"Commit {commit.id} ({commit.message}) has been deleted from stream {stream.id}")
+2
View File
@@ -3,6 +3,8 @@ import webbrowser
from specklepy.logging import metrics from specklepy.logging import metrics
class OpenSpeckleGuide(bpy.types.Operator): class OpenSpeckleGuide(bpy.types.Operator):
bl_idname = "speckle.open_speckle_guide" bl_idname = "speckle.open_speckle_guide"
bl_label = "Speckle Guide" bl_label = "Speckle Guide"
+5 -4
View File
@@ -13,6 +13,7 @@ from bpy_speckle.functions import get_scale_length, _report
from bpy_speckle.clients import speckle_clients from bpy_speckle.clients import speckle_clients
from specklepy.logging import metrics from specklepy.logging import metrics
@deprecated
class UpdateObject(bpy.types.Operator): class UpdateObject(bpy.types.Operator):
""" """
Update local (receive) or remote (send) object depending on Update local (receive) or remote (send) object depending on
@@ -68,7 +69,7 @@ class UpdateObject(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
return {"CANCELLED"} return {"CANCELLED"}
@deprecated
class ResetObject(bpy.types.Operator): class ResetObject(bpy.types.Operator):
""" """
Reset Speckle object settings Reset Speckle object settings
@@ -96,7 +97,7 @@ class ResetObject(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
@deprecated
class DeleteObject(bpy.types.Operator): class DeleteObject(bpy.types.Operator):
""" """
Delete object from the server and update relevant stream Delete object from the server and update relevant stream
@@ -247,7 +248,7 @@ def get_custom_speckle_props(self, context):
return [(x, "{}".format(x), "") for x in active.keys()] return [(x, "{}".format(x), "") for x in active.keys()]
@deprecated
class SelectIfSameCustomProperty(bpy.types.Operator): class SelectIfSameCustomProperty(bpy.types.Operator):
""" """
Select scene objects if they have the same custom property Select scene objects if they have the same custom property
@@ -307,7 +308,7 @@ class SelectIfSameCustomProperty(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
@deprecated
class SelectIfHasCustomProperty(bpy.types.Operator): class SelectIfHasCustomProperty(bpy.types.Operator):
""" """
Select scene objects if they have the same custom property Select scene objects if they have the same custom property
+74 -82
View File
@@ -2,7 +2,7 @@
Stream operators Stream operators
""" """
from math import radians from math import radians
from typing import Callable, Dict, Optional, Union, cast from typing import Callable, Dict, Optional, Tuple, Union, cast
import webbrowser import webbrowser
import bpy import bpy
from bpy.props import ( from bpy.props import (
@@ -31,8 +31,9 @@ from bpy_speckle.functions import (
get_scale_length, get_scale_length,
) )
from bpy_speckle.clients import speckle_clients from bpy_speckle.clients import speckle_clients
from bpy_speckle.operators.users import add_user_stream from bpy_speckle.operators.helpers import ShowMessageBox
from bpy_speckle.properties.scene import SpeckleSceneSettings, SpeckleUserObject, get_speckle from bpy_speckle.operators.users import LoadUserStreams, add_user_stream
from bpy_speckle.properties.scene import SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle
from bpy_speckle.convert.util import ConversionSkippedException, add_to_hierarchy from bpy_speckle.convert.util import ConversionSkippedException, add_to_hierarchy
from specklepy.core.api.models import Commit from specklepy.core.api.models import Commit
from specklepy.core.api import operations, host_applications from specklepy.core.api import operations, host_applications
@@ -133,12 +134,8 @@ class ReceiveStreamObjects(bpy.types.Operator):
bpy.context.view_layer.objects.active = None bpy.context.view_layer.objects.active = None
def execute(self, context): def execute(self, context):
try: self.receive(context)
self.receive(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"Failed to receive objects: {type(ex)} {ex}")
return {"CANCELLED"}
def receive(self, context: Context) -> None: def receive(self, context: Context) -> None:
bpy.context.view_layer.objects.active = None bpy.context.view_layer.objects.active = None
@@ -146,7 +143,7 @@ class ReceiveStreamObjects(bpy.types.Operator):
speckle = get_speckle(context) speckle = get_speckle(context)
(user, stream, branch, commit) = speckle.validate_commit_selection() (user, stream, branch, commit) = speckle.validate_commit_selection()
client = speckle_clients[int(speckle.active_user)] client = speckle_clients[int(speckle.active_user)]
transport = ServerTransport(stream.id, client) transport = ServerTransport(stream.id, client)
@@ -201,7 +198,8 @@ class ReceiveStreamObjects(bpy.types.Operator):
if can_convert_to_native(current) or isinstance(current, SCollection): if can_convert_to_native(current) or isinstance(current, SCollection):
try: try:
if not current or not current.id: raise Exception(f"{current} was an invalid speckle object") if not current or not current.id:
raise Exception(f"{current} was an invalid speckle object")
#Convert the object! #Convert the object!
converted_data_type: str converted_data_type: str
@@ -270,7 +268,9 @@ class SendStreamObjects(bpy.types.Operator):
def invoke(self, context, event): def invoke(self, context, event):
wm = context.window_manager wm = context.window_manager
if len(context.scene.speckle.users) <= 0: return {"CANCELLED"} if len(context.scene.speckle.users) <= 0:
_report("No user accounts")
return {"CANCELLED"}
N = len(context.selected_objects) N = len(context.selected_objects)
if N == 1: if N == 1:
@@ -281,12 +281,8 @@ class SendStreamObjects(bpy.types.Operator):
def execute(self, context): def execute(self, context):
try: self.send(context)
self.send(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"Send failed: {ex}")
return {"CANCELLED"}
def send(self, context: Context) -> None: def send(self, context: Context) -> None:
@@ -376,7 +372,13 @@ class SendStreamObjects(bpy.types.Operator):
message=self.commit_message, message=self.commit_message,
source_application="blender", source_application="blender",
) )
_report(f"Commit Created {user.server_url}/streams/{stream.id}/commits/{COMMIT_ID}")
if client.account.serverInfo.frontend2:
sent_url = f"{user.server_url}/projects/{stream.id}/models/{branch.id}@{COMMIT_ID}"
else:
sent_url = f"{user.server_url}/streams/{stream.id}/commits/{COMMIT_ID}"
_report(f"Commit Created {sent_url}")
bpy.ops.speckle.load_user_streams() # refresh loaded commits bpy.ops.speckle.load_user_streams() # refresh loaded commits
context.view_layer.update() context.view_layer.update()
@@ -393,19 +395,21 @@ class ViewStreamDataApi(bpy.types.Operator):
bl_description = "View the stream in the web browser" bl_description = "View the stream in the web browser"
def execute(self, context): def execute(self, context):
try: self.view_stream_data_api(context)
self.view_stream_data_api(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def view_stream_data_api(self, context: Context) -> None: def view_stream_data_api(self, context: Context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
(user, stream) = speckle.validate_stream_selection() (user, stream) = speckle.validate_stream_selection()
if not webbrowser.open("%s/streams/%s" % (user.server_url, stream.id), new=2): client = speckle_clients[int(speckle.active_user)]
if client.account.serverInfo.frontend2:
stream_url = f"{user.server_url}/projects/{stream.id}"
else:
stream_url= f"{user.server_url}/streams/{stream.id}"
if not webbrowser.open(stream_url, new=2):
raise Exception("Failed to open stream in browser") raise Exception("Failed to open stream in browser")
metrics.track( metrics.track(
@@ -444,13 +448,25 @@ class AddStreamFromURL(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
def execute(self, context): def execute(self, context):
try: self.add_stream_from_url(context)
self.add_stream_from_url(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex: @staticmethod
_report(f"{self.bl_idname} failed: {ex}") def _get_or_add_stream(user : SpeckleUserObject, stream : Stream) -> Tuple[int, SpeckleStreamObject]:
return {"CANCELLED"} index, b_stream = next(
((i, cast(SpeckleStreamObject, s)) for i, s in enumerate(user.streams) if s.id == stream.id),
(None, None),
)
if index is not None:
return (index, b_stream)
add_user_stream(user, stream)
return next(
(i, cast(SpeckleStreamObject, s)) for i, s in enumerate(user.streams) if s.id == stream.id
)
def add_stream_from_url(self, context: Context) -> None: def add_stream_from_url(self, context: Context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
@@ -460,28 +476,20 @@ class AddStreamFromURL(bpy.types.Operator):
None, None,
) )
if user_index is None: if user_index is None:
raise Exception("Unable to find user stream server") raise Exception(f"No user account credentials for {wrapper.host}, have you added your account in Manager?")
speckle.active_user = str(user_index) speckle.active_user = str(user_index)
user = cast(SpeckleUserObject, speckle.users[user_index]) user = cast(SpeckleUserObject, speckle.users[user_index])
client = speckle_clients[user_index] client = speckle_clients[user_index]
stream = client.stream.get(wrapper.stream_id, branch_limit=20) stream = client.stream.get(wrapper.stream_id, branch_limit=LoadUserStreams.branch_limit, commit_limit=LoadUserStreams.commits_limit)
if not isinstance(stream, Stream): if not isinstance(stream, Stream):
raise SpeckleException("Could not get the requested stream") raise SpeckleException(f"Could not get the requested stream {wrapper.stream_id}")
index, b_stream = next( (index, b_stream) = self._get_or_add_stream(user, stream)
((i, s) for i, s in enumerate(user.streams) if s.id == stream.id), user.active_stream = index
(None, None),
)
if index is None: _report(f"Selecting stream at index {index} ({b_stream.id} - {b_stream.name})")
add_user_stream(user, stream)
user.active_stream, b_stream = next(
(i, s) for i, s in enumerate(user.streams) if s.id == stream.id
)
else:
user.active_stream = index
if wrapper.branch_name: if wrapper.branch_name:
b_index = b_stream.branches.find(wrapper.branch_name) b_index = b_stream.branches.find(wrapper.branch_name)
@@ -541,12 +549,8 @@ class CreateStream(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
def execute(self, context): def execute(self, context):
try: self.create_stream(context)
self.create_stream(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def create_stream(self, context: Context) -> None: def create_stream(self, context: Context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
@@ -611,19 +615,16 @@ class DeleteStream(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
def execute(self, context): def execute(self, context):
try:
self.delete_stream(context)
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def delete_stream(self, context: Context) -> None:
if not self.are_you_sure: if not self.are_you_sure:
raise Exception("Cancelled by user") _report(f"Cancelled by user - are_you_sure was {self.are_you_sure}")
return {"CANCELLED"}
self.are_you_sure = False self.are_you_sure = False
self.delete_stream(context, self.delete_collection)
return {"FINISHED"}
@staticmethod
def delete_stream(context: Context, delete_collection: bool) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
(_, stream) = speckle.validate_stream_selection() (_, stream) = speckle.validate_stream_selection()
@@ -631,7 +632,8 @@ class DeleteStream(bpy.types.Operator):
client.stream.delete(id=stream.id) client.stream.delete(id=stream.id)
if self.delete_collection: if delete_collection:
# This may not work anymore since we changed the collection naming...
col_name = "SpeckleStream_{}_{}".format(stream.name, stream.id) col_name = "SpeckleStream_{}_{}".format(stream.name, stream.id)
if col_name in bpy.data.collections: if col_name in bpy.data.collections:
collection = bpy.data.collections[col_name] collection = bpy.data.collections[col_name]
@@ -696,12 +698,8 @@ class CopyStreamId(bpy.types.Operator):
bl_description = "Copy stream ID to clipboard" bl_description = "Copy stream ID to clipboard"
def execute(self, context): def execute(self, context):
try: self.copy_stream_id(context)
self.copy_stream_id(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def copy_stream_id(self, context) -> None: def copy_stream_id(self, context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
@@ -727,12 +725,9 @@ class CopyCommitId(bpy.types.Operator):
bl_description = "Copy commit ID to clipboard" bl_description = "Copy commit ID to clipboard"
def execute(self, context): def execute(self, context):
try: self.copy_commit_id(context)
self.copy_commit_id(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def copy_commit_id(self, context) -> None: def copy_commit_id(self, context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
@@ -760,12 +755,9 @@ class CopyBranchName(bpy.types.Operator):
bl_description = "Copy branch name to clipboard" bl_description = "Copy branch name to clipboard"
def execute(self, context): def execute(self, context):
try: self.copy_branch_id(context)
self.copy_branch_id(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def copy_branch_id(self, context) -> None: def copy_branch_id(self, context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
+14 -12
View File
@@ -1,12 +1,12 @@
""" """
User account operators User account operators
""" """
from typing import cast from typing import List, cast
import bpy import bpy
from bpy.types import Context from bpy.types import Context
from bpy_speckle.functions import _report from bpy_speckle.functions import _report
from bpy_speckle.clients import speckle_clients from bpy_speckle.clients import speckle_clients
from bpy_speckle.properties.scene import SpeckleCommitObject, SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle from bpy_speckle.properties.scene import SpeckleBranchObject, SpeckleCommitObject, SpeckleSceneSettings, SpeckleStreamObject, SpeckleUserObject, get_speckle
from specklepy.core.api.client import SpeckleClient from specklepy.core.api.client import SpeckleClient
from specklepy.core.api.models import Stream from specklepy.core.api.models import Stream
from specklepy.core.api.credentials import get_local_accounts, Account from specklepy.core.api.credentials import get_local_accounts, Account
@@ -57,7 +57,7 @@ class LoadUsers(bpy.types.Operator):
_report("Loading users...") _report("Loading users...")
speckle = cast(SpeckleSceneSettings, context.scene.speckle) #type: ignore speckle = get_speckle(context)
users_list = speckle.users users_list = speckle.users
ResetUsers.reset_ui(context) ResetUsers.reset_ui(context)
@@ -133,13 +133,17 @@ def add_user_stream(user: SpeckleUserObject, stream: Stream):
s.id = stream.id s.id = stream.id
s.description = stream.description s.description = stream.description
_report(f"Adding stream {s.id} - {s.name}")
if not stream.branches: if not stream.branches:
return return
# branches = [branch for branch in stream.branches.items if branch.name != "globals"] # branches = [branch for branch in stream.branches.items if branch.name != "globals"]
for b in stream.branches.items: for b in stream.branches.items:
branch = s.branches.add() branch = cast(SpeckleBranchObject, s.branches.add())
branch.name = b.name branch.name = b.name
branch.id = b.id
branch.description = b.description or ""
if not b.commits: if not b.commits:
continue continue
@@ -172,14 +176,12 @@ class LoadUserStreams(bpy.types.Operator):
stream_limit: int = 20 stream_limit: int = 20
branch_limit: int = 100 branch_limit: int = 100
commits_limit: int = 10
def execute(self, context): def execute(self, context):
try: self.load_user_stream(context)
self.load_user_stream(context) return {"FINISHED"}
return {"FINISHED"}
except Exception as ex:
_report(f"{self.bl_idname} failed: {ex}")
return {"CANCELLED"}
def load_user_stream(self, context: Context) -> None: def load_user_stream(self, context: Context) -> None:
speckle = get_speckle(context) speckle = get_speckle(context)
@@ -193,14 +195,14 @@ class LoadUserStreams(bpy.types.Operator):
raise Exception(f"Failed to retrieve streams") from ex raise Exception(f"Failed to retrieve streams") from ex
if not streams: if not streams:
raise Exception("Zero streams found") _report("Zero streams found")
return return
user.streams.clear() user.streams.clear()
for s in streams: for s in streams:
assert(s.id) assert(s.id)
sstream = client.stream.get(id=s.id, branch_limit=self.branch_limit) sstream = client.stream.get(id=s.id, branch_limit=self.branch_limit, commit_limit=10)
add_user_stream(user, sstream) add_user_stream(user, sstream)
bpy.context.view_layer.update() bpy.context.view_layer.update()
+2
View File
@@ -37,6 +37,8 @@ class SpeckleBranchObject(bpy.types.PropertyGroup):
return [("0", "<none>", "<none>", 0)] return [("0", "<none>", "<none>", 0)]
name: StringProperty(default="main") name: StringProperty(default="main")
id: StringProperty(default="")
description: StringProperty(default="")
commits: CollectionProperty(type=SpeckleCommitObject) commits: CollectionProperty(type=SpeckleCommitObject)
commit: EnumProperty( commit: EnumProperty(
name="Commit", name="Commit",
+2 -1
View File
@@ -10,8 +10,9 @@ from bpy.props import (
CollectionProperty, CollectionProperty,
EnumProperty, EnumProperty,
) )
from deprecated import deprecated
@deprecated
class OBJECT_PT_speckle(bpy.types.Panel): class OBJECT_PT_speckle(bpy.types.Panel):
bl_space_type = "PROPERTIES" bl_space_type = "PROPERTIES"
# bl_idname = 'OBJECT_PT_speckle' # bl_idname = 'OBJECT_PT_speckle'
Generated
+42 -24
View File
@@ -98,32 +98,39 @@ files = [
[[package]] [[package]]
name = "black" name = "black"
version = "22.12.0" version = "23.11.0"
description = "The uncompromising code formatter." description = "The uncompromising code formatter."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
files = [ files = [
{file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, {file = "black-23.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911"},
{file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, {file = "black-23.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f"},
{file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, {file = "black-23.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394"},
{file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, {file = "black-23.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f"},
{file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, {file = "black-23.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479"},
{file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, {file = "black-23.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244"},
{file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, {file = "black-23.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221"},
{file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, {file = "black-23.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5"},
{file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, {file = "black-23.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187"},
{file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, {file = "black-23.11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6"},
{file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, {file = "black-23.11.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b"},
{file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, {file = "black-23.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142"},
{file = "black-23.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055"},
{file = "black-23.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4"},
{file = "black-23.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06"},
{file = "black-23.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07"},
{file = "black-23.11.0-py3-none-any.whl", hash = "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e"},
{file = "black-23.11.0.tar.gz", hash = "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05"},
] ]
[package.dependencies] [package.dependencies]
click = ">=8.0.0" click = ">=8.0.0"
mypy-extensions = ">=0.4.3" mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0" pathspec = ">=0.9.0"
platformdirs = ">=2" platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
[package.extras] [package.extras]
colorama = ["colorama (>=0.4.3)"] colorama = ["colorama (>=0.4.3)"]
@@ -314,13 +321,13 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "fake-bpy-module-latest" name = "fake-bpy-module-latest"
version = "20230117" version = "20240212"
description = "Collection of the fake Blender Python API module for the code completion." description = "Collection of the fake Blender Python API module for the code completion."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
files = [ files = [
{file = "fake-bpy-module-latest-20230117.tar.gz", hash = "sha256:b58957036fe5573b2374a159aeb7a4cbd92255f447e55a49e16ff7c06850cdd1"}, {file = "fake-bpy-module-latest-20240212.tar.gz", hash = "sha256:5b33c6cdeaaa92f1a55ca1e5f23771216dc5cd233dd6922a500bf8101e666a82"},
{file = "fake_bpy_module_latest-20230117-py3-none-any.whl", hash = "sha256:73613c27418446bc2942baed6220f8ac4ddde694a3712dd595aa97f902a79242"}, {file = "fake_bpy_module_latest-20240212-py3-none-any.whl", hash = "sha256:7616834644bf90d37bd774112a851fd940096fd859eca704ece63e3d8215719c"},
] ]
[[package]] [[package]]
@@ -613,6 +620,17 @@ files = [
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
] ]
[[package]]
name = "packaging"
version = "23.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]] [[package]]
name = "pathspec" name = "pathspec"
version = "0.12.1" version = "0.12.1"
@@ -851,13 +869,13 @@ files = [
[[package]] [[package]]
name = "specklepy" name = "specklepy"
version = "2.17.17" version = "2.18.0"
description = "The Python SDK for Speckle 2.0" description = "The Python SDK for Speckle 2.0"
optional = false optional = false
python-versions = ">=3.8.0,<4.0" python-versions = ">=3.8.0,<4.0"
files = [ files = [
{file = "specklepy-2.17.17-py3-none-any.whl", hash = "sha256:793705a803423b69d0873bc98314fbb0cd805b4b10657957bd13ef5cdcad08ce"}, {file = "specklepy-2.18.0-py3-none-any.whl", hash = "sha256:d4b229a4bdcb64453bd51d27da85753e8be25f6c03746a650d445020d0793726"},
{file = "specklepy-2.17.17.tar.gz", hash = "sha256:73abeee1c958299818518266dd734d4dc0c82b3e665bb6c4e5b54bad09f118c1"}, {file = "specklepy-2.18.0.tar.gz", hash = "sha256:3ec40a756e0e35ad0e35abe979265af79a43fbf933e832e061d5284085da5cc7"},
] ]
[package.dependencies] [package.dependencies]
@@ -1268,4 +1286,4 @@ multidict = ">=4.0"
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.8, <4.0.0" python-versions = ">=3.8, <4.0.0"
content-hash = "4013ed20ddaf1e3d73013848e1de434f487a9d53b4cbf4c902c70c9135f207b3" content-hash = "e10e6a322281da0f67bf194552df16c4c5d9a4a945311f16b376ffcfde1bff56"
+3 -3
View File
@@ -7,15 +7,15 @@ license = "Apache-2.0"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.8, <4.0.0" python = ">=3.8, <4.0.0"
specklepy = "^2.17.17" specklepy = "^2.18.0"
attrs = "^23.1.0" attrs = "^23.1.0"
# [tool.poetry.group.local_specklepy.dependencies] # [tool.poetry.group.local_specklepy.dependencies]
# specklepy = {path = "../specklepy", develop = true} # specklepy = {path = "../specklepy", develop = true}
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
fake-bpy-module-latest = "^20230117" fake-bpy-module-latest = "^20240212"
black = "^22.10.0" black = "23.11.0"
pylint = "^2.15.7" pylint = "^2.15.7"
ruff = "^0.0.187" ruff = "^0.0.187"